Paikalliset tiedostot siirrettäessä sovellusta Kubernetesiin

Paikalliset tiedostot siirrettäessä sovellusta Kubernetesiin

Kun rakennetaan CI/CD-prosessia Kubernetesilla, joskus syntyy ongelma uuden infrastruktuurin vaatimusten ja siihen siirrettävän sovelluksen välillä. Erityisesti sovelluksen rakennusvaiheessa on tärkeää saada yksi kuva, jota käytetään Kaikki projektiympäristöjä ja klustereita. Tämä periaate on oikean perusta Googlen mukaan kontinhallinta (useammin kuin kerran tästä hän sanoi ja tekninen osastomme).

Et kuitenkaan näe ketään tilanteissa, joissa sivuston koodi käyttää valmiita puitteita, joiden käyttö asettaa rajoituksia sen jatkokäytölle. Ja vaikka "normaalissa ympäristössä" tämä on helppo käsitellä, Kubernetesissa tämä käyttäytyminen voi muodostua ongelmaksi, varsinkin kun kohtaat sen ensimmäistä kertaa. Vaikka kekseliäs mieli voi keksiä infrastruktuuriratkaisuja, jotka näyttävät ensi silmäyksellä ilmeisiltä tai jopa hyviltä... on tärkeää muistaa, että useimmat tilanteet voivat ja pitäisi ratkaistaan ​​arkkitehtonisesti.

Tarkastellaan suosittuja kiertotaparatkaisuja tiedostojen tallentamiseen, jotka voivat johtaa epämiellyttäviin seurauksiin klusterin käytössä, ja osoitetaan myös oikeampi polku.

Staattinen tallennus

Havainnollistaa esimerkkinä verkkosovellusta, joka käyttää jonkinlaista staattista generaattoria kuvien, tyylien ja muiden asioiden muodostamiseen. Esimerkiksi Yii PHP -kehyksessä on sisäänrakennettu omaisuudenhallinta, joka luo ainutlaatuisia hakemistonimiä. Vastaavasti tulos on joukko staattisen paikan polkuja, jotka eivät ilmeisesti leikkaa toisiaan (tämä tehtiin useista syistä - esimerkiksi kaksoiskappaleiden poistamiseksi, kun useat komponentit käyttävät samaa resurssia). Joten heti, kun käytät verkkoresurssimoduulia ensimmäistä kertaa, staattiset tiedostot (itse asiassa usein symbolilinkit, mutta niistä lisää myöhemmin) muodostetaan ja asetetaan yhteisen juurihakemiston kanssa, joka on ainutlaatuinen tälle käyttöönotolle:

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

Mitä tämä tarkoittaa klusterin kannalta?

Yksinkertaisin esimerkki

Otetaanpa melko yleinen tapaus, kun PHP:tä edeltää nginx staattisen tiedon jakamiseksi ja yksinkertaisten pyyntöjen käsittelemiseksi. Helpoin tapa - käyttöönoton kahdella säiliöllä:

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

Yksinkertaistetussa muodossa nginx-kokoonpano tiivistyy seuraavaan:

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;
        }
    }

Kun käytät sivustoa ensimmäisen kerran, resurssit näkyvät PHP-säilössä. Mutta jos samassa podissa on kaksi konttia, nginx ei tiedä mitään näistä staattisista tiedostoista, jotka (kokoonpanon mukaan) pitäisi antaa heille. Tämän seurauksena asiakas näkee kaikissa CSS- ja JS-tiedostopyynnöissä virheen 404. Yksinkertaisin ratkaisu tässä olisi järjestää yhteinen hakemisto säilöille. Primitiivinen vaihtoehto - yleinen 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

Nyt nginx palvelee säilöön luotuja staattisia tiedostoja oikein. Mutta haluan muistuttaa, että tämä on primitiivinen ratkaisu, mikä tarkoittaa, että se on kaukana ihanteellisesta ja sillä on omat vivahteensa ja puutteensa, joita käsitellään alla.

Edistyneempi tallennustila

Kuvittele nyt tilanne, jossa käyttäjä vieraili sivustolla, latasi sivun säilön käytettävissä olevilla tyyleillä, ja kun hän luki tätä sivua, otimme säilön käyttöön uudelleen. Omaisuusluettelo on tyhjentynyt ja uusien luomisen aloittaminen edellyttää pyyntöä PHP:lle. Kuitenkin vielä tämän jälkeen linkit vanhaan statiikkaan ovat merkityksettömiä, mikä johtaa virheisiin staattisen näytön näyttämisessä.

Lisäksi meillä on todennäköisesti enemmän tai vähemmän ladattu projekti, mikä tarkoittaa, että yksi kopio sovelluksesta ei riitä:

  • Mittataan sitä käyttöönoton enintään kaksi kopiota.
  • Kun sivustoa käytettiin ensimmäisen kerran, resurssit luotiin yhdessä replikassa.
  • Jossain vaiheessa ingress päätti (kuormituksen tasapainottamista varten) lähettää pyynnön toiselle replikalle, eikä näitä resursseja vielä ollut. Tai ehkä niitä ei enää ole, koska käytämme RollingUpdate ja tällä hetkellä teemme käyttöönottoa.

Yleensä tulos on taas virheitä.

Voit vaihtaa, jotta et menetä vanhaa omaisuutta emptyDir päälle hostPath, lisäämällä staattisuutta fyysisesti klusterin solmuun. Tämä lähestymistapa on huono, koska meidän on todella pakko sitoutua tiettyyn klusterin solmuun sovelluksesi, koska - jos siirryt muihin solmuihin - hakemisto ei sisällä tarvittavia tiedostoja. Tai jonkinlainen taustahakemiston synkronointi solmujen välillä vaaditaan.

Mitkä ovat ratkaisut?

  1. Jos laitteisto ja resurssit sallivat, voit käyttää cephfs järjestää yhtä helposti saatavilla oleva hakemisto staattisia tarpeita varten. Virallinen dokumentaatio suosittelee SSD-asemia, vähintään kolminkertaista replikointia ja vakaata "paksua" yhteyttä klusterin solmujen välillä.
  2. Vähemmän vaativa vaihtoehto olisi järjestää NFS-palvelin. Tällöin sinun on kuitenkin otettava huomioon mahdollinen vasteajan pidentyminen verkkopalvelimen pyyntöjen käsittelyssä, ja vikasietoisuus jättää paljon toivomisen varaa. Epäonnistumisen seuraukset ovat katastrofaaliset: vuoren menetys tuhoaa klusterin kuolemaan taivaalle syöksyvän LA-kuorman paineessa.

Muun muassa kaikki pysyvän tallennustilan luomisvaihtoehdot vaativat taustan puhdistus tietyn ajanjakson aikana kertyneet vanhentuneet tiedostot. Edessä kontteja PHP voit laittaa DaemonSet välimuistista nginx, joka säilyttää kopioita resursseista rajoitetun ajan. Tämä toiminta on helposti määritettävissä käyttämällä proxy_cache tallennussyvyys päivinä tai gigatavuina levytilaa.

Tämän menetelmän yhdistäminen yllä mainittuihin hajautettuihin tiedostojärjestelmiin tarjoaa valtavan kentän mielikuvitukselle, jota rajoittavat vain sen toteuttajien ja tukevien budjetti ja tekninen potentiaali. Kokemuksesta voimme sanoa, että mitä yksinkertaisempi järjestelmä, sitä vakaammin se toimii. Kun tällaisia ​​kerroksia lisätään, infrastruktuurin ylläpito on paljon vaikeampaa, ja samalla vikojen diagnosointiin ja niistä toipumiseen kuluva aika kasvaa.

suositus

Jos myös ehdotettujen säilytysvaihtoehtojen toteuttaminen tuntuu sinusta perusteettomalta (monimutkaiselta, kalliilta...), niin kannattaa katsoa tilannetta toiselta puolelta. Nimittäin kaivaa projektin arkkitehtuuriin ja korjaa ongelma koodissa, joka on sidottu johonkin kuvan staattiseen tietorakenteeseen, sisällön tai menettelyn yksiselitteinen "lämmittely" ja/tai resurssien esikääntäminen kuvan kokoonpanovaiheessa. Tällä tavalla saamme täysin ennustettavan toiminnan ja samat tiedostot kaikkiin ympäristöihin ja käynnissä olevan sovelluksen replikoihin.

Jos palaamme erityiseen esimerkkiin Yii-kehyksen kanssa emmekä syvenny sen rakenteeseen (mikä ei ole artikkelin tarkoitus), riittää, että tuomme esiin kaksi suosittua lähestymistapaa:

  1. Muuta kuvanrakennusprosessia sijoittaaksesi resurssit ennustettavaan paikkaan. Tätä ehdotetaan/toteutetaan laajennuksissa, kuten yii2-static-assets.
  2. Määrittele omaisuushakemistoille erityisiä hajautusarvoja, kuten käsitellään esim. tämä esitys (alkaen diasta nro 35). Muuten, raportin kirjoittaja viime kädessä (eikä ilman syytä!) neuvoo, että kun resurssit on koottu koontipalvelimelle, lataa ne keskusmuistiin (kuten S3), jonka eteen sijoita CDN.

Lataukset

Toinen tapaus, joka tulee ehdottomasti esiin siirrettäessä sovellusta Kubernetes-klusteriin, on käyttäjätiedostojen tallentaminen tiedostojärjestelmään. Esimerkiksi meillä on taas PHP-sovellus, joka hyväksyy tiedostot latauslomakkeen kautta, tekee niille jotain käytön aikana ja lähettää ne takaisin.

Kubernetesissa näiden tiedostojen sijainnin tulisi olla yhteinen kaikille sovelluksen replikoille. Riippuen sovelluksen monimutkaisuudesta ja tarpeesta järjestää näiden tiedostojen pysyvyys, edellä mainitut jaetut laitevaihtoehdot voivat olla tällainen paikka, mutta kuten näemme, niillä on haittapuolensa.

suositus

Yksi ratkaisu on käyttämällä S3-yhteensopivaa tallennustilaa (vaikka se olisi jonkinlainen itseisännöity luokka, kuten minio). S3:een vaihtaminen vaatii muutoksia kooditasolla, ja kuinka sisältö toimitetaan käyttöliittymässä, olemme jo tehneet писали.

Käyttäjäistunnot

Erikseen on syytä huomata käyttäjäistuntojen tallennusjärjestely. Usein nämä ovat myös levyllä olevia tiedostoja, jotka Kubernetesin yhteydessä johtavat jatkuviin valtuutuspyyntöihin käyttäjältä, jos hänen pyyntönsä päätyy toiseen säiliöön.

Ongelma ratkeaa osittain käynnistämällä stickySessions sisäänpääsyn yhteydessä (ominaisuus on tuettu kaikissa suosituissa sisääntuloohjaimissa - lisätietoja on kohdassa meidän tarkastelu)sitoa käyttäjä tiettyyn podiin sovelluksen avulla:

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: /

Mutta tämä ei poista toistuvien käyttöönottojen ongelmia.

suositus

Oikeampi tapa olisi siirtää hakemus osoitteeseen istuntojen tallentaminen memcachediin, Redisiin ja vastaaviin ratkaisuihin - yleensä hylkää tiedostovaihtoehdot kokonaan.

Johtopäätös

Tekstissä käsitellyt infrastruktuuriratkaisut ovat käyttökelpoisia vain väliaikaisten "sauvoiden" muodossa (joka kuulostaa englannin kielellä kauniimmalta ratkaisuna). Ne voivat olla merkityksellisiä sovelluksen Kubernetesiin siirron ensimmäisissä vaiheissa, mutta niiden ei pitäisi juurtua.

Yleinen suositeltava tapa on päästä niistä eroon ja muuttaa sovelluksen arkkitehtonisesti sen mukaisesti, mikä on jo hyvin tiedossa. 12-faktorinen sovellus. Tämä - sovelluksen saattaminen tilattomaan muotoon - tarkoittaa kuitenkin väistämättä sitä, että koodiin tulee tehdä muutoksia, ja tässä on tärkeää löytää tasapaino liiketoiminnan kykyjen/vaatimusten ja valitun polun toteutus- ja ylläpitonäkymien välillä. .

PS.

Lue myös blogistamme:

Lähde: will.com

Lisää kommentti