Kubernetese esimese rakenduse juurutamisel viis puudu

Kubernetese esimese rakenduse juurutamisel viis puuduFail autor Aris Dreamer

Paljud arvavad, et piisab rakenduse Kubernetesesse ülekandmisest (kas Helmi abil või käsitsi) - ja õnn on olemas. Kuid mitte kõik pole nii lihtne.

Meeskond Mail.ru pilvelahendused tõlkinud DevOpsi inseneri Julian Gindy artikli. Ta räägib, milliste lõksudega tema ettevõte migratsiooniprotsessis kokku puutus, et te ei astuks sama reha otsa.

Esimene samm: seadistage Podi taotlused ja piirangud

Alustuseks loome puhta keskkonna, milles meie kaunad töötavad. Kubernetes on suurepärane pod-ajastamise ja tõrkeotsingu alal. Kuid selgus, et planeerija ei saa mõnikord podi paigutada, kui on raske hinnata, kui palju ressursse see edukaks tööks vajab. Siin ilmuvad ressursside ja piirangute taotlused. Päringute ja piirangute seadmise parima lähenemisviisi üle on palju arutelusid. Mõnikord tundub, et see on tõesti rohkem kunst kui teadus. Siin on meie lähenemine.

Podi taotlused on peamine väärtus, mida planeerija kasutab kausta optimaalseks paigutamiseks.

Kohta Kubernetese dokumentatsioon: Filtri samm määratleb sõlmede komplekti, kuhu saab Podi ajastada. Näiteks filter PodFitsResources kontrollib, kas sõlmel on piisavalt ressursse, et rahuldada kaustast pärinevaid konkreetseid ressursitaotlusi.

Rakenduspäringuid kasutame nii, et saame hinnata, kui palju ressursse tegelikult Rakendus vajab seda nõuetekohaseks toimimiseks. Nii saab planeerija sõlmed reaalselt paigutada. Algselt tahtsime taotlusi üle ajastada, et tagada iga Podi jaoks piisavalt ressursse, kuid märkasime, et ajastamise aeg pikenes märkimisväärselt ja mõned Pod ei olnud täielikult ajastatud, justkui poleks nende jaoks ressursitaotlusi.

Sellisel juhul "pigistab planeerija" sageli kaustasid ega saa neid ümber ajastada, kuna juhttasandil polnud aimugi, kui palju ressursse rakendus vajab, mis on ajastamisalgoritmi põhikomponent.

Podi piirangud on kauna jaoks selgem piir. See tähistab maksimaalset ressursside hulka, mille klaster konteinerile eraldab.

Jällegi, alates ametlik dokumentatsioon: kui konteineri mälupiirang on 4 GiB, siis kubelet (ja konteineri käitusaeg) jõustab selle. Käitusaeg takistab konteineril määratud ressursipiirangust rohkem kasutamast. Näiteks kui konteineris olev protsess üritab kasutada lubatust rohkem mälu, lõpetab süsteemituum protsessi "mälu otsas" (OOM) veaga.

Konteiner võib alati kasutada rohkem ressursse, kui ressursitaotlus määrab, kuid see ei saa kunagi kasutada rohkem kui piirang. Seda väärtust on raske õigesti seadistada, kuid see on väga oluline.

Ideaalis soovime, et podi ressursinõuded muutuksid protsessi elutsükli jooksul, ilma et see segaks teisi süsteemi protsesse – see on piiride seadmise eesmärk.

Kahjuks ei saa ma anda konkreetseid juhiseid, milliseid väärtusi seada, kuid me ise järgime järgmisi reegleid:

  1. Koormustestimise tööriista abil simuleerime liikluse baastaset ja jälgime podiressursside (mälu ja protsessori) kasutamist.
  2. Seadke pod-päringute suvaliselt madal väärtus (ressursipiiranguga umbes 5 korda päringu väärtusest) ja jälgige. Kui päringute tase on liiga madal, ei saa protsess käivituda, põhjustades sageli salapäraseid Go käitusaegseid vigu.

Märgin, et kõrgemad ressursilimiidid muudavad ajastamise keerulisemaks, kuna pod vajab sihtsõlme, millel on piisavalt ressursse.

Kujutage ette olukorda, kus teil on väga suure ressursipiiranguga (nt 4 GB mälu) kerge veebiserver. Seda protsessi tuleb tõenäoliselt horisontaalselt skaleerida ja iga uus pod tuleb ajastada sõlmes, millel on vähemalt 4 GB vaba mälu. Kui sellist sõlme pole, peab klaster selle pod töötlemiseks kasutusele võtma uue sõlme, mis võib võtta aega. Kiire ja sujuva skaleerimise tagamiseks on oluline saavutada minimaalne erinevus ressursitaotluste ja limiitide vahel.

Teine samm: seadistage elavuse ja valmisoleku testid

See on veel üks peen teema, mida Kubernetese kogukonnas sageli arutatakse. Elavsuse ja valmisoleku testidest on oluline hästi aru saada, kuna need pakuvad mehhanismi tarkvara stabiilseks tööks ja minimeerivad seisakuid. Kuid kui need pole õigesti konfigureeritud, võivad need teie rakenduse jõudlust tõsiselt mõjutada. Allpool on kokkuvõte sellest, millised on mõlemad näidised.

Elavus näitab, kas konteiner töötab. Kui see ebaõnnestub, tapab kubelet konteineri ja taaskäivituspoliitika on selle jaoks lubatud. Kui konteiner ei ole varustatud Liveness Probe'iga, on vaikeseisund edukas – nagu on märgitud Kubernetese dokumentatsioon.

Liveness sondid peaksid olema odavad, st mitte kulutama palju ressursse, kuna need töötavad sageli ja peaksid Kubernetesile rakenduse töötamise kohta teada andma.

Kui määrate suvandi käitada iga sekundi järel, lisab see 1 päringu sekundis, seega pidage meeles, et selle liikluse töötlemiseks on vaja lisaressursse.

Meie ettevõttes testivad Livenessi testid rakenduse põhikomponente isegi siis, kui andmed (näiteks kaugandmebaasist või vahemälust) pole täielikult kättesaadavad.

Oleme rakendustes seadistanud "tervise" lõpp-punkti, mis lihtsalt tagastab vastusekoodi 200. See näitab, et protsess töötab ja suudab taotlusi (kuid mitte liiklust) käsitleda.

Proov Valmisolek näitab, kas konteiner on päringute teenindamiseks valmis. Kui valmisolekusond ebaõnnestub, eemaldab lõpp-punkti kontroller podi IP-aadressi kõigi podiga sobivate teenuste lõpp-punktidest. See on kirjas ka Kubernetese dokumentatsioonis.

Valmisoleku proovid tarbivad rohkem ressursse, kuna need peavad tabama taustaprogrammi selliselt, et näidata, et rakendus on valmis taotlusi vastu võtma.

Kogukonnas on palju arutelusid selle üle, kas andmebaasile otse juurde pääseda. Arvestades üldkulusid (kontrollid on sagedased, kuid neid saab kontrollida), otsustasime, et mõne rakenduse puhul loetakse liikluse teenindamiseks valmisolekut alles pärast seda, kui on kontrollitud, et andmebaasist kirjed tagastatakse. Hästi läbimõeldud valmisolekukatsetused tagasid kõrgema kättesaadavuse ja kõrvaldasid kasutuselevõtu ajal seisakuid.

Kui otsustate oma rakenduse valmisoleku testimiseks andmebaasist päringuid teha, veenduge, et see oleks võimalikult odav. Võtame selle päringu:

SELECT small_item FROM table LIMIT 1

Siin on näide nende kahe väärtuse konfigureerimisest Kubernetesis:

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

Saate lisada mõned täiendavad konfiguratsioonisuvandid:

  • initialDelaySeconds - mitu sekundit möödub konteineri käivitamise ja sondide käivitamise vahel.
  • periodSeconds — ooteaeg proovivõtete vahel.
  • timeoutSeconds — sekundite arv, pärast mida käsitatakse avariisüsteemina. Tavaline ajalõpp.
  • failureThreshold on testi tõrgete arv enne taaskäivitussignaali saatmist taskusse.
  • successThreshold on edukate katsete arv enne, kui pod lülitub valmisolekusse (pärast ebaõnnestumist, kui pod käivitub või taastub).

Kolmas samm: Podi vaikevõrgupoliitikate määramine

Kubernetesil on "tasane" võrgu topograafia, vaikimisi suhtlevad kõik podid omavahel otse. Mõnel juhul pole see soovitav.

Võimalik turvaprobleem seisneb selles, et ründaja võib kasutada ühte haavatavat rakendust, et saata liiklus kõigile võrgus olevatele kaustadele. Nagu paljudes turvalisuse valdkondades, kehtib ka siin minimaalsete privileegide põhimõte. Ideaalis peaksid võrgupoliitikad sõnaselgelt näitama, millised ühendused kaustade vahel on lubatud ja millised mitte.

Näiteks järgmine on lihtne reegel, mis keelab kogu konkreetse nimeruumi sissetuleva liikluse:

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

Selle konfiguratsiooni visualiseerimine:

Kubernetese esimese rakenduse juurutamisel viis puudu
(https://miro.medium.com/max/875/1*-eiVw43azgzYzyN1th7cZg.gif)
Lisateave siin.

Neljas samm: kohandatud käitumine konksude ja algkonteinerite abil

Üks meie peamisi eesmärke oli pakkuda arendajatele Kubernetes juurutusi ilma seisakuteta. See on keeruline, kuna rakenduste sulgemiseks ja nende kasutatud ressursside vabastamiseks on palju võimalusi.

Erilisi raskusi tekkis sellega nginx. Märkasime, et nende Podide järjestikusel juurutamisel katkestati aktiivsed ühendused enne edukat lõpetamist.

Pärast põhjalikku Interneti-uuringut selgus, et Kubernetes ei oota enne podi sulgemist, kuni Nginxi ühendused end ammendavad. Peatamiseelse konksu abil rakendasime järgmise funktsionaalsuse ja vabanesime seisakutest täielikult:

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

ja siin 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

Teine äärmiselt kasulik paradigma on init-konteinerite kasutamine konkreetsete rakenduste käivitamiseks. See on eriti kasulik, kui teil on ressursimahukas andmebaasi migratsiooniprotsess, mis tuleb käivitada enne rakenduse käivitamist. Sellele protsessile saate määrata ka suurema ressursipiirangu ilma põhirakendusele sellist piirangut määramata.

Teine levinud skeem on juurdepääs salajastele init konteineris, mis annab need mandaadid põhimoodulile, mis hoiab ära volitamata juurdepääsu põhirakenduse mooduli enda saladustele.

Nagu ikka, tsitaat dokumentatsioonist: init konteinerid käitavad turvaliselt kasutajakoodi või utiliite, mis muidu ohustaksid rakenduse konteineri kujutise turvalisust. Kui hoiate mittevajalikud tööriistad eraldi, piirate rakenduse konteineri kujutise rünnakupinda.

Viies samm: tuuma konfigureerimine

Lõpuks räägime täiustatud tehnikast.

Kubernetes on äärmiselt paindlik platvorm, mis võimaldab teil töökoormust käitada nii, nagu teile sobib. Meil on mitmeid ülitõhusaid rakendusi, mis on äärmiselt ressursimahukad. Pärast põhjalikku koormustestimist avastasime, et ühel rakendusel oli Kubernetese vaikeseadete kehtimise ajal raskusi oodatava liikluskoormusega sammu pidama.

Kubernetes võimaldab aga käitada privilegeeritud konteinerit, mis muudab ainult konkreetse kausta tuumaparameetreid. Avatud ühenduste maksimaalse arvu muutmiseks kasutasime järgmist.

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

See on arenenum tehnika, mida sageli ei vajata. Kuid kui teie rakendusel on raske toime tulla suure koormusega, võite proovida mõnda neist sätetest kohandada. Lisateave selle protsessi ja erinevate väärtuste seadmise kohta - nagu alati ametlikus dokumentatsioonis.

Kokkuvõttes

Kuigi Kubernetes võib tunduda kasutusvalmis lahendusena, tuleb rakenduste tõrgeteta töötamiseks teha mõned olulised sammud.

Kogu Kubernetesesse migreerumise ajal on oluline järgida "koormuse testimise tsüklit": käivitage rakendus, testige seda koormuse all, jälgige mõõdikuid ja skaleerimise käitumist, kohandage nende andmete põhjal konfiguratsiooni ja korrake seda tsüklit uuesti.

Olge eeldatava liikluse suhtes realistlik ja proovige sellest kaugemale minna, et näha, millised komponendid purunevad enne. Selle iteratiivse lähenemise korral võib edu saavutamiseks piisata vaid mõnest loetletud soovitusest. Või see võib vajada põhjalikumat kohandamist.

Küsige endalt alati neid küsimusi:

  1. Kui palju ressursse rakendused tarbivad ja kuidas see summa muutub?
  2. Millised on tegelikud skaleerimisnõuded? Kui palju liiklust rakendus keskmiselt käsitleb? Aga tippliiklus?
  3. Kui sageli tuleb teenust laiendada? Kui kiiresti peavad uued taskud liikluse vastuvõtmiseks töökorda saama?
  4. Kui graatsiliselt kaunad lülituvad välja? Kas see on üldse vajalik? Kas kasutuselevõtt on võimalik ilma seisakuta?
  5. Kuidas minimeerida turvariske ja piirata kahjustatud kaustade põhjustatud kahju? Kas mõnel teenusel on õigused või juurdepääsud, mida nad ei vaja?

Kubernetes pakub uskumatut platvormi, mis võimaldab teil kasutada parimaid tavasid tuhandete teenuste juurutamiseks klastris. Kõik rakendused on aga erinevad. Mõnikord nõuab rakendamine veidi rohkem tööd.

Õnneks pakub Kubernetes vajalikke seadistusi kõigi tehniliste eesmärkide saavutamiseks. Kasutades ressursside taotluste ja piirangute kombinatsiooni, Liveness- ja Readiness-sonde, init-konteinereid, võrgupoliitikaid ja kohandatud tuuma häälestamist, saate saavutada suure jõudluse koos tõrketaluvuse ja kiire skaleeritavuse.

Mida veel lugeda:

  1. Konteinerite ja Kubernetese käitamise parimad tavad ja tavad tootmiskeskkondades.
  2. 90+ kasulikku tööriista Kubernetese jaoks: juurutamine, haldamine, jälgimine, turvalisus ja palju muud.
  3. Meie kanal Kubernetese ümber Telegramis.

Allikas: www.habr.com

Lisa kommentaar