Staðbundnar skrár þegar forrit er flutt yfir í Kubernetes

Staðbundnar skrár þegar forrit er flutt yfir í Kubernetes

Þegar CI/CD ferli er byggt með Kubernetes, kemur stundum upp vandamálið vegna ósamrýmanleika á milli krafna nýja innviðsins og forritsins sem er flutt á það. Sérstaklega er mikilvægt að fá á umsóknarstigi einn mynd sem verður notuð í allt verkefnisumhverfi og klasa. Þessi meginregla liggur til grundvallar réttinum samkvæmt Google gámastjórnun (oftar en einu sinni um þetta talaði og tæknideild okkar).

Hins vegar munt þú ekki sjá neinn í aðstæðum þar sem kóða síðunnar notar tilbúinn ramma, notkun þess setur takmarkanir á frekari notkun þess. Og þó að í „venjulegu umhverfi“ sé auðvelt að takast á við þetta, í Kubernetes getur þessi hegðun orðið vandamál, sérstaklega þegar þú lendir í henni í fyrsta skipti. Þó að frumlegur hugur geti fundið upp innviðalausnir sem virðast augljósar eða jafnvel góðar við fyrstu sýn... þá er mikilvægt að muna að flestar aðstæður geta og ættu að vera leyst byggingarfræðilega.

Skoðum vinsælar lausnir til að geyma skrár sem geta leitt til óþægilegra afleiðinga þegar þyrping er rekin og bendum einnig á réttari leið.

Statísk geymsla

Til skýringar skaltu íhuga vefforrit sem notar einhvers konar kyrrstöðurafall til að fá sett af myndum, stílum og öðru. Til dæmis, Yii PHP ramminn er með innbyggðan eignastjóra sem býr til einstök skráanöfn. Í samræmi við það er úttakið sett af slóðum fyrir kyrrstæðu síðuna sem augljóslega skerast ekki hvert annað (þetta var gert af nokkrum ástæðum - til dæmis til að útrýma tvíteknum þegar sama tilfang er notað með mörgum íhlutum). Svo, úr kassanum, í fyrsta skipti sem þú opnar vefforðaeiningu, myndast fastar skrár (reyndar oft tákntenglar, en meira um það síðar) og settar út með sameiginlegri rótarskrá sem er einstök fyrir þessa uppsetningu:

  • webroot/assets/2072c2df/css/…
  • webroot/assets/2072c2df/images/…
  • webroot/assets/2072c2df/js/…

Hvað þýðir þetta hvað varðar klasa?

Einfaldasta dæmið

Tökum nokkuð algengt dæmi, þegar PHP er á undan nginx til að dreifa kyrrstæðum gögnum og vinna úr einföldum beiðnum. Auðveldasta leiðin - dreifing með tveimur ílátum:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: site
spec:
  selector:
    matchLabels:
      component: backend
  template:
    metadata:
      labels:
        component: backend
    spec:
      volumes:
        - name: nginx-config
          configMap:
            name: nginx-configmap
      containers:
      - name: php
        image: own-image-with-php-backend:v1.0
        command: ["/usr/local/sbin/php-fpm","-F"]
        workingDir: /var/www
      - name: nginx
        image: nginx:1.16.0
        command: ["/usr/sbin/nginx", "-g", "daemon off;"]
        volumeMounts:
        - name: nginx-config
          mountPath: /etc/nginx/conf.d/default.conf
          subPath: nginx.conf

Í einfölduðu formi kemur nginx stillingin niður á eftirfarandi:

apiVersion: v1
kind: ConfigMap
metadata:
  name: "nginx-configmap"
data:
  nginx.conf: |
    server {
        listen 80;
        server_name _;
        charset utf-8;
        root  /var/www;

        access_log /dev/stdout;
        error_log /dev/stderr;

        location / {
            index index.php;
            try_files $uri $uri/ /index.php?$args;
        }

        location ~ .php$ {
            fastcgi_pass 127.0.0.1:9000;
            fastcgi_index index.php;
            include fastcgi_params;
        }
    }

Þegar þú opnar síðuna fyrst birtast eignir í PHP ílátinu. En ef um er að ræða tvo ílát innan eins belgs, þá veit nginx ekkert um þessar kyrrstæðu skrár, sem (samkvæmt uppsetningunni) ætti að gefa þeim. Fyrir vikið mun viðskiptavinurinn sjá 404 villu fyrir allar beiðnir um CSS og JS skrár. Einfaldasta lausnin hér væri að skipuleggja sameiginlega möppu fyrir gáma. Frumstæður valkostur - almennur emptyDir:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: site
spec:
  selector:
    matchLabels:
      component: backend
  template:
    metadata:
      labels:
        component: backend
    spec:
      volumes:
        - name: assets
          emptyDir: {}
        - name: nginx-config
          configMap:
            name: nginx-configmap
      containers:
      - name: php
        image: own-image-with-php-backend:v1.0
        command: ["/usr/local/sbin/php-fpm","-F"]
        workingDir: /var/www
        volumeMounts:
        - name: assets
          mountPath: /var/www/assets
      - name: nginx
        image: nginx:1.16.0
        command: ["/usr/sbin/nginx", "-g", "daemon off;"]
        volumeMounts:
        - name: assets
          mountPath: /var/www/assets
        - name: nginx-config
          mountPath: /etc/nginx/conf.d/default.conf
          subPath: nginx.conf

Nú eru kyrrstæðar skrár sem myndaðar eru í ílátinu þjónað af nginx á réttan hátt. En ég minni á að þetta er frumstæð lausn, sem þýðir að hún er langt frá því að vera tilvalin og hefur sín blæbrigði og galla sem fjallað er um hér á eftir.

Ítarlegri geymsla

Ímyndaðu þér núna aðstæður þar sem notandi heimsótti síðuna, hlóð síðu með þeim stílum sem eru tiltækir í gámnum og á meðan hann var að lesa þessa síðu, settum við ílátið aftur út. Eignaskráin er orðin tóm og beiðni til PHP er nauðsynleg til að byrja að búa til nýjar. Hins vegar, jafnvel eftir þetta, munu tenglar á gamla stöðutölur skipta engu máli, sem mun leiða til villna í birtingu truflana.

Að auki erum við líklega með meira eða minna hlaðið verkefni, sem þýðir að eitt eintak af forritinu dugar ekki:

  • Við skulum skala það upp dreifing allt að tvær eftirlíkingar.
  • Þegar fyrst var farið á síðuna voru eignir búnar til í einni eftirmynd.
  • Á einhverjum tímapunkti ákvað ingress (í álagsjöfnunarskyni) að senda beiðni til seinni eftirmyndarinnar og þessar eignir voru ekki til staðar ennþá. Eða kannski eru þeir ekki lengur til staðar vegna þess að við notum RollingUpdate og í augnablikinu erum við að dreifa.

Almennt, niðurstaðan er aftur mistök.

Til að forðast að tapa gömlum eignum geturðu breytt emptyDir á hostPath, bætir kyrrstöðu líkamlega við klasahnút. Þessi nálgun er slæm vegna þess að við þurfum í raun og veru að gera það bindast ákveðnum klasahnút forritið þitt, vegna þess að - ef þú færir til annarra hnúta - mun skráin ekki innihalda nauðsynlegar skrár. Eða einhvers konar bakgrunnsskráarsamstillingu milli hnúta er nauðsynleg.

Hverjar eru lausnirnar?

  1. Ef vélbúnaður og tilföng leyfa geturðu notað cephfs að skipuleggja jafnaðgengilega skrá fyrir staðbundnar þarfir. Opinber skjöl mælir með SSD drifum, að minnsta kosti þrefaldri afritun og stöðugri „þykkri“ tengingu milli klasahnúta.
  2. Minni krefjandi valkostur væri að skipuleggja NFS netþjón. Hins vegar þarftu að taka með í reikninginn mögulegan aukinn viðbragðstíma fyrir vinnslu beiðna frá vefþjóninum og bilanaþol mun skilja eftir mikið. Afleiðingar bilunar eru skelfilegar: tap fjallsins dæmir þyrpinguna til dauða undir þrýstingi LA-farsins sem þjóta til himins.

Meðal annars munu allir valkostir til að búa til viðvarandi geymslu krefjast bakgrunnsþrif úrelt sett af skrám sem safnast hafa upp á tilteknu tímabili. Fyrir framan gáma með PHP sem þú getur sett DaemonSet frá skyndiminni nginx, sem mun geyma afrit af eignum í takmarkaðan tíma. Þessa hegðun er auðvelt að stilla með því að nota proxy_cache með geymsludýpt í dögum eða gígabætum af plássi.

Sameining þessarar aðferðar við dreifða skráarkerfin sem nefnd eru hér að ofan veitir risastórt svið fyrir ímyndunarafl, takmarkað aðeins af fjárhagsáætlun og tæknilegum möguleikum þeirra sem munu innleiða og styðja það. Af reynslu getum við sagt að því einfaldara sem kerfið er, því stöðugra virkar það. Þegar slík lög bætast við verður mun erfiðara að viðhalda innviðum og um leið eykst tíminn sem fer í að greina og jafna sig á bilunum.

Tilmæli

Ef útfærsla fyrirhugaðra geymsluvalkosta virðist þér líka óréttlætanleg (flókið, dýrt ...), þá er það þess virði að skoða aðstæður frá hinni hliðinni. Nefnilega að grafa ofan í verkefnið arkitektúr og laga vandamálið í kóðanum, bundin við einhverja kyrrstæða gagnauppbyggingu í myndinni, ótvíræð skilgreiningu á innihaldi eða aðferð til að „hita upp“ og/eða forsamsetningu eigna á myndsamsetningarstigi. Þannig fáum við algerlega fyrirsjáanlega hegðun og sama sett af skrám fyrir öll umhverfi og eftirlíkingar af forritinu sem er í gangi.

Ef við snúum okkur aftur að tilteknu dæmi með Yii rammanum og kafa ekki í uppbyggingu þess (sem er ekki tilgangur greinarinnar), er nóg að benda á tvær vinsælar aðferðir:

  1. Breyttu myndbyggingarferlinu til að setja eignir á fyrirsjáanlegan stað. Þetta er lagt til/útfært í viðbótum eins og yii2-statískar-eignir.
  2. Skilgreindu tiltekna kjötkássa fyrir eignasöfn, eins og fjallað er um í t.d. þessari kynningu (að byrjað á glæru nr. 35). Við the vegur, höfundur skýrslunnar á endanum (og ekki að ástæðulausu!) ráðleggur að eftir að hafa sett saman eignir á byggingarþjóninum, hlaðið þeim upp á miðlæga geymslu (eins og S3), fyrir framan hana setja CDN.

Niðurhal

Annað mál sem mun örugglega koma við sögu þegar forrit er flutt yfir í Kubernetes klasa er að geyma notendaskrár í skráarkerfinu. Til dæmis erum við aftur með PHP forrit sem tekur við skrám í gegnum upphleðslueyðublað, gerir eitthvað við þær meðan á vinnslu stendur og sendir þær til baka.

Í Kubernetes ætti staðsetningin þar sem þessar skrár ættu að vera sameiginlegar fyrir allar eftirlíkingar af forritinu. Það fer eftir því hversu flókið forritið er og þörfinni á að skipuleggja þrautseigju þessara skráa, ofangreindir samnýttir tækisvalkostir geta verið slíkur staður, en eins og við sjáum hafa þeir sína galla.

Tilmæli

Ein lausn er með því að nota S3-samhæfða geymslu (jafnvel þótt það sé einhvers konar flokkur sem hýst er sjálfur eins og minio). Skipta yfir í S3 mun krefjast breytinga á kóðastigi, og hvernig efni verður afhent á framendanum, höfum við nú þegar писали.

Notendalotur

Sérstaklega er vert að taka eftir skipulagningu geymslu notendalota. Oft eru þetta líka skrár á diski, sem í samhengi Kubernetes mun leiða til stöðugra heimildabeiðna frá notanda ef beiðni hans endar í öðrum gámi.

Vandamálið er að hluta til leyst með því að kveikja á stickySessions við inngöngu (eiginleikinn er studdur í öllum vinsælum inngöngustýringum - fyrir frekari upplýsingar, sjá umfjöllun okkar)til að binda notandann við ákveðna belg með forritinu:

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: nginx-test
  annotations:
    nginx.ingress.kubernetes.io/affinity: "cookie"
    nginx.ingress.kubernetes.io/session-cookie-name: "route"
    nginx.ingress.kubernetes.io/session-cookie-expires: "172800"
    nginx.ingress.kubernetes.io/session-cookie-max-age: "172800"

spec:
  rules:
  - host: stickyingress.example.com
    http:
      paths:
      - backend:
          serviceName: http-svc
          servicePort: 80
        path: /

En þetta mun ekki útrýma vandamálum við endurtekna dreifingu.

Tilmæli

Réttari leið væri að flytja umsóknina á geymir lotur í memcached, Redis og svipuðum lausnum - Almennt, yfirgefa skráarvalkosti algjörlega.

Ályktun

Innviðalausnirnar sem fjallað er um í textanum eru aðeins þess virði að nota í formi tímabundinna „hækja“ (sem hljómar fallegri á ensku sem lausn). Þær gætu skipt máli á fyrstu stigum flutnings forrits til Kubernetes, en ættu ekki að skjóta rótum.

Almenn ráðlögð leið er að losna við þá í þágu byggingarbreytinga á umsókninni í samræmi við það sem mörgum er vel þekkt. 12-þátta app. Hins vegar - að færa umsóknina í ríkisfangslaust form - þýðir það óhjákvæmilega að breyta þarf kóðanum og hér er mikilvægt að finna jafnvægi á milli getu/krafna fyrirtækisins og horfanna til að innleiða og viðhalda valinni leið. .

PS

Lestu líka á blogginu okkar:

Heimild: www.habr.com

Bæta við athugasemd