Viisi virhettä otettaessa käyttöön ensimmäistä sovellusta Kubernetesissa

Viisi virhettä otettaessa käyttöön ensimmäistä sovellusta KubernetesissaAris-Dreamer epäonnistui

Monet ihmiset uskovat, että sovelluksen siirtäminen Kubernetesiin (joko Helmin avulla tai manuaalisesti) riittää ja he ovat tyytyväisiä. Mutta se ei ole niin yksinkertaista.

Joukkue Mail.ru Pilviratkaisut kääntänyt DevOps-insinöörin Julian Gindin artikkelin. Hän kertoo, mitä sudenkuoppia hänen yrityksensä kohtasi siirtoprosessin aikana, jotta et astuisi saman haravan päälle.

Vaihe yksi: Pod-pyyntöjen ja rajoitusten määrittäminen

Aloitetaan luomalla puhdas ympäristö, jossa podimme toimivat. Kubernetes tekee erinomaista työtä podien ajoittamisessa ja vikatilanteiden käsittelyssä. Mutta kävi ilmi, että ajoittaja ei voi joskus sijoittaa podia, jos on vaikea arvioida kuinka monta resurssia se tarvitsee toimiakseen onnistuneesti. Tässä kohtaa resursseja ja rajoja koskevat pyynnöt. Parhaasta lähestymistavasta pyyntöjen ja rajojen asettamiseen käydään paljon keskustelua. Joskus todella tuntuu, että se on enemmän taidetta kuin tiedettä. Tässä on lähestymistapamme.

Pod-pyynnöt - Tämä on tärkein arvo, jota ajastin käyttää podin optimaaliseen sijoittamiseen.

Ja Kubernetesin dokumentaatio: Suodatusvaihe määrittää solmujoukon, joihin pod voidaan ajoittaa. Esimerkiksi PodFitsResources-suodatin tarkistaa, onko solmulla tarpeeksi resursseja tyydyttääkseen podin tietyt resurssipyynnöt.

Käytämme sovelluspyyntöjä, jotta niiden avulla voidaan arvioida kuinka monta resurssia itse asiassa Sovellus tarvitsee sen toimiakseen kunnolla. Tällä tavalla ajoittaja voi sijoittaa solmut realistisesti. Alun perin halusimme asettaa pyynnöt marginaalilla varmistaaksemme, että jokaisessa podissa on riittävän suuri määrä resursseja, mutta huomasimme, että aikataulutusajat pidentyivät merkittävästi ja joitain podeja ei koskaan ajoitettu kokonaan, ikään kuin niistä ei olisi saatu resurssipyyntöjä.

Tässä tapauksessa ajoittaja työstäisi usein podeja eikä pystyisi ajoittamaan niitä uudelleen, koska ohjaustasolla ei ollut aavistustakaan, kuinka monta resurssia sovellus vaatisi, mikä on ajoitusalgoritmin avainkomponentti.

Pod-rajoitukset - Tämä on selkeämpi raja podille. Se edustaa resurssien enimmäismäärää, jonka klusteri varaa säilölle.

Jälleen alkaen virallinen dokumentaatio: Jos säilölle on asetettu 4 Git:n muistiraja, kubelet (ja säilön suoritusaika) pakottaa sen. Suoritusaika ei salli säilön käyttää määritettyä resurssirajaa enempää. Esimerkiksi kun prosessi säilössä yrittää käyttää enemmän kuin sallittu määrä muistia, järjestelmän ydin lopettaa prosessin "muisti loppu" (OOM) -virheellä.

Säilö voi aina käyttää enemmän resursseja kuin resurssipyynnössä on määritetty, mutta se ei voi koskaan käyttää enempää kuin rajoituksessa on määritetty. Tätä arvoa on vaikea asettaa oikein, mutta se on erittäin tärkeä.

Ihannetapauksessa haluamme podin resurssitarpeen muuttuvan prosessin elinkaaren aikana häiritsemättä muita järjestelmän prosesseja – se on rajojen asettamisen tavoite.

Valitettavasti en voi antaa tarkkoja ohjeita siitä, mitkä arvot asetetaan, mutta noudatamme itse seuraavia sääntöjä:

  1. Kuormitustestaustyökalun avulla simuloimme liikenteen perustason ja seuraamme pod-resurssien käyttöä (muisti ja prosessori).
  2. Asetamme pod-pyynnöt mielivaltaisen alhaiselle arvolle (resurssirajalla noin 5 kertaa pyyntöjen arvo) ja tarkkailemme. Kun pyyntöjä on liian vähän, prosessi ei voi käynnistyä, mikä aiheuttaa usein salaperäisiä Go-ajonaikaisia ​​virheitä.

Huomaa, että korkeammat resurssirajat vaikeuttavat ajoitusta, koska pod tarvitsee kohdesolmun, jossa on riittävästi resursseja.

Kuvittele tilanne, jossa sinulla on kevyt verkkopalvelin, jolla on erittäin korkea resurssiraja, esimerkiksi 4 Gt muistia. Tämä prosessi on todennäköisesti skaalattava vaakatasossa, ja jokainen uusi moduuli on ajoitettava solmuun, jossa on vähintään 4 Gt vapaata muistia. Jos tällaista solmua ei ole, klusterin on esitettävä uusi solmu kyseisen podin käsittelemiseksi, mikä voi kestää jonkin aikaa. On tärkeää pitää resurssipyyntöjen ja rajoitusten välinen ero mahdollisimman pienenä nopean ja sujuvan skaalauksen varmistamiseksi.

Vaihe kaksi: Elävyys- ja valmiustestien määrittäminen

Tämä on toinen hienovarainen aihe, josta keskustellaan usein Kubernetes-yhteisössä. On tärkeää ymmärtää hyvin elävyys- ja valmiustestit, koska ne tarjoavat mekanismin ohjelmiston sujuvalle toiminnalle ja minimoivat seisokit. Ne voivat kuitenkin aiheuttaa vakavan suorituskyvyn sovelluksellesi, jos niitä ei ole määritetty oikein. Alla on yhteenveto siitä, millaisia ​​molemmat näytteet ovat.

elävyyden näyttää, onko säilö käynnissä. Jos se epäonnistuu, kubelet tappaa säilön ja sille otetaan käyttöön uudelleenkäynnistyskäytäntö. Jos säiliössä ei ole Liveness-anturia, oletustila on onnistunut - näin se lukee Kubernetesin dokumentaatio.

Elävyysluettimien tulee olla halpoja, eli niiden ei pitäisi kuluttaa paljon resursseja, koska ne toimivat usein ja niiden on ilmoitettava Kubernetesille, että sovellus on käynnissä.

Jos määrität vaihtoehdon suorittaa joka sekunti, tämä lisää yhden pyynnön sekunnissa, joten muista, että tämän liikenteen käsitteleminen vaatii lisäresursseja.

Yrityksessämme Liveness-testit tarkistavat sovelluksen ydinkomponentit, vaikka tiedot (esimerkiksi etätietokannasta tai välimuistista) eivät olisi täysin käytettävissä.

Olemme määrittäneet sovelluksiin "terveys"-päätepisteen, joka yksinkertaisesti palauttaa vastauskoodin 200. Tämä on osoitus siitä, että prosessi on käynnissä ja pystyy käsittelemään pyyntöjä (mutta ei vielä liikennettä).

testi valmius ilmaisee, onko säilö valmis palvelemaan pyyntöjä. Jos valmiusanturi epäonnistuu, päätepisteohjain poistaa podin IP-osoitteen kaikkien podia vastaavien palvelujen päätepisteistä. Tämä mainitaan myös Kubernetesin dokumentaatiossa.

Valmistelut kuluttavat enemmän resursseja, koska ne on lähetettävä taustajärjestelmään tavalla, joka osoittaa, että sovellus on valmis vastaanottamaan pyyntöjä.

Yhteisössä käydään paljon keskustelua siitä, päästäänkö tietokantaan suoraan. Ottaen huomioon yleiskustannukset (tarkistuksia tehdään usein, mutta niitä voidaan säätää), päätimme, että joissakin sovelluksissa liikenteen palveluvalmius lasketaan vasta sen jälkeen, kun on varmistettu, että tietueet palautetaan tietokannasta. Hyvin suunnitellut valmiuskokeet varmistivat korkeamman käytettävyyden ja eliminoivat seisokit käyttöönoton aikana.

Jos päätät tehdä kyselyn tietokannasta testataksesi sovelluksesi valmiutta, varmista, että se on mahdollisimman edullinen. Otetaan tämä pyyntö:

SELECT small_item FROM table LIMIT 1

Tässä on esimerkki siitä, kuinka määritämme nämä kaksi arvoa Kubernetesissa:

livenessProbe: 
 httpGet:   
   path: /api/liveness    
   port: http 
readinessProbe:  
 httpGet:    
   path: /api/readiness    
   port: http  periodSeconds: 2

Voit lisätä joitain muita määritysvaihtoehtoja:

  • initialDelaySeconds — kuinka monta sekuntia kuluu säiliön käynnistämisen ja näytteenoton välillä.
  • periodSeconds — näyteajojen välinen odotusaika.
  • timeoutSeconds — sekuntien lukumäärä, jonka jälkeen yksikkö katsotaan hätätilanteeksi. Säännöllinen aikakatkaisu.
  • failureThreshold — testivirheiden lukumäärä ennen kuin uudelleenkäynnistyssignaali lähetetään podille.
  • successThreshold — onnistuneiden antureiden määrä ennen kuin pod menee valmiustilaan (vian jälkeen, kun pod käynnistyy tai palautuu).

Vaihe kolme: oletusverkkokäytäntöjen määrittäminen podille

Kubernetesilla on "tasainen" verkkotopografia; oletusarvoisesti kaikki podit kommunikoivat suoraan keskenään. Joissakin tapauksissa tämä ei ole toivottavaa.

Mahdollinen tietoturvaongelma on se, että hyökkääjä voi käyttää yhtä haavoittuvaa sovellusta lähettääkseen liikennettä kaikkiin verkon koteloihin. Kuten monilla turvallisuusalueilla, tässäkin sovelletaan vähiten etuoikeuksien periaatetta. Ihannetapauksessa verkkokäytäntöjen tulisi erikseen määrittää, mitkä podien väliset yhteydet ovat sallittuja ja mitkä eivät.

Alla on esimerkiksi yksinkertainen käytäntö, joka estää kaiken saapuvan liikenteen tietyltä nimiavarilta:

---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:  
 name: default-deny-ingress
spec:  
 podSelector: {}  
 policyTypes:  
   - Ingress

Tämän kokoonpanon visualisointi:

Viisi virhettä otettaessa käyttöön ensimmäistä sovellusta Kubernetesissa
(https://miro.medium.com/max/875/1*-eiVw43azgzYzyN1th7cZg.gif)
Lisätietoja täällä.

Vaihe neljä: mukautettu toiminta koukkujen ja init-säiliöiden avulla

Yksi tärkeimmistä tavoitteistamme oli tarjota Kubernetesiin käyttöönottoja kehittäjille ilman seisokkeja. Tämä on vaikeaa, koska on monia vaihtoehtoja sovellusten sulkemiseen ja niiden käyttämien resurssien vapauttamiseen.

Erityisiä vaikeuksia ilmeni nginx. Huomasimme, että kun nämä podit otettiin käyttöön peräkkäin, aktiiviset yhteydet katkesivat ennen onnistunutta valmistumista.

Laajan verkossa tehdyn tutkimuksen jälkeen käy ilmi, että Kubernetes ei odota Nginx-yhteyksien tyhjenevän ennen podin lopettamista. Esipysähdyskoukun avulla otimme käyttöön seuraavat toiminnot ja pääsimme kokonaan eroon seisokeista:

lifecycle: 
 preStop:
   exec:
     command: ["/usr/local/bin/nginx-killer.sh"]

Mutta nginx-killer.sh:

#!/bin/bash
sleep 3
PID=$(cat /run/nginx.pid)
nginx -s quit
while [ -d /proc/$PID ]; do
   echo "Waiting while shutting down nginx..."
   sleep 10
done

Toinen erittäin hyödyllinen paradigma on init-säiliöiden käyttö tiettyjen sovellusten käynnistyksen käsittelemiseksi. Tämä on erityisen hyödyllistä, jos sinulla on resurssiintensiivinen tietokannan siirtoprosessi, joka on suoritettava ennen sovelluksen käynnistymistä. Voit myös määrittää tälle prosessille korkeamman resurssirajan asettamatta tällaista rajoitusta pääsovellukselle.

Toinen yleinen tapa on käyttää salaisuuksia aloitussäiliössä, joka antaa kyseiset valtuustiedot päämoduulille, mikä estää luvattoman pääsyn salaisuuksiin itse pääsovellusmoduulista.

Kuten tavallista, lainaus asiakirjoista: Init-säilöt suorittavat turvallisesti mukautettua koodia tai apuohjelmia, jotka muutoin heikentäisivät sovelluksen säilön kuvan turvallisuutta. Pitämällä tarpeettomat työkalut erillään, rajoitat sovellussäiliökuvan hyökkäyspintaa.

Vaihe viisi: Ytimen määrittäminen

Lopuksi puhutaan edistyneemmästä tekniikasta.

Kubernetes on erittäin joustava alusta, jonka avulla voit suorittaa työkuormia parhaaksi katsomallasi tavalla. Meillä on useita korkean suorituskyvyn sovelluksia, jotka ovat erittäin resurssivaltaisia. Laajan kuormitustestauksen jälkeen havaitsimme, että yksi sovellus kamppaili käsitellä odotettua liikennekuormitusta, kun Kubernetesin oletusasetukset olivat voimassa.

Kubernetes sallii kuitenkin käyttää etuoikeutettua säilöä, joka muuttaa ytimen parametreja vain tietylle ryhmälle. Muutimme auki olevien yhteyksien enimmäismäärää seuraavasti:

initContainers:
  - name: sysctl
     image: alpine:3.10
     securityContext:
         privileged: true
      command: ['sh', '-c', "sysctl -w net.core.somaxconn=32768"]

Tämä on edistyneempi tekniikka, jota ei usein tarvita. Mutta jos sovelluksellasi on vaikeuksia selviytyä raskaasta kuormituksesta, voit yrittää säätää joitain näistä asetuksista. Lisätietoja tästä prosessista ja eri arvojen asettamisesta - kuten aina virallisessa dokumentaatiossa.

lopuksi

Vaikka Kubernetes saattaa tuntua valmiilta ratkaisulta, sinun on suoritettava muutamia tärkeitä vaiheita, jotta sovelluksesi toimivat sujuvasti.

Kubernetes-siirtymisen aikana on tärkeää noudattaa "kuormitustestaussykliä": käynnistä sovellus, lataa se, tarkkaile mittareita ja skaalauskäyttäytymistä, säädä kokoonpanoa näiden tietojen perusteella ja toista sykli sitten uudelleen.

Ole realistinen odotetussa liikenteessäsi ja yritä päästä sen ulkopuolelle nähdäksesi, mitkä komponentit rikkoutuvat ensin. Tällä iteratiivisella lähestymistavalla vain muutama listatuista suosituksista saattaa riittää menestyksen saavuttamiseen. Tai se voi vaatia syvempää räätälöintiä.

Kysy itseltäsi aina nämä kysymykset:

  1. Kuinka paljon resursseja sovellukset kuluttavat ja miten tämä määrä muuttuu?
  2. Mitkä ovat todelliset skaalausvaatimukset? Kuinka paljon liikennettä sovellus käsittelee keskimäärin? Entä ruuhkahuippu?
  3. Kuinka usein palvelun tulee skaalata vaakasuunnassa? Kuinka nopeasti uudet podit on saatava verkkoon liikenteen vastaanottamiseksi?
  4. Kuinka oikein palot sammuvat? Onko tämä ollenkaan tarpeellista? Onko mahdollista saavuttaa käyttöönotto ilman seisokkeja?
  5. Kuinka voit minimoida tietoturvariskit ja rajoittaa vaarantuneiden koteloiden aiheuttamia vahinkoja? Onko palveluilla käyttöoikeuksia tai käyttöoikeuksia, joita ne eivät vaadi?

Kubernetes tarjoaa uskomattoman alustan, jonka avulla voit hyödyntää parhaita käytäntöjä tuhansien palveluiden käyttöönottamiseksi klusterissa. Jokainen sovellus on kuitenkin erilainen. Joskus toteutus vaatii hieman enemmän työtä.

Onneksi Kubernetes tarjoaa tarvittavat kokoonpanot kaikkien teknisten tavoitteiden saavuttamiseksi. Resurssipyyntöjen ja rajoitusten, Liveness- ja Readiness-anturien, aloitussäilöjen, verkkokäytäntöjen ja mukautetun ytimen virityksen yhdistelmän avulla voit saavuttaa korkean suorituskyvyn sekä vikasietoisuuden ja nopean skaalautuvuuden.

Mitä muuta luettavaa:

  1. Parhaat käytännöt ja parhaat käytännöt konttien ja Kubernetesin käyttöön tuotantoympäristöissä.
  2. Yli 90 hyödyllistä työkalua Kubernetesille: käyttöönotto, hallinta, valvonta, suojaus ja paljon muuta.
  3. Kanavamme Kubernetesin ympärillä Telegramissa.

Lähde: will.com

Lisää kommentti