Op. prev.: Glavni inženjer iz kompanije Zalando — Henning Jacobs — je više puta primetio probleme korisnika Kubernetes-a u razumevanju svrhe liveness (i readiness) probes i njihove pravilne primene. Zbog toga je sakupio svoje misli u ovu kratku belešku, koja će s vremenom postati deo dokumentacije K8s.

Provere stanja, poznate u Kubernetes-u kao liveness probes (tj., doslovno, „testovi na životnost“ — napomena prev.), mogu biti veoma opasne. Preporučujem da ih po mogućstvu izbegavate: izuzeci su samo slučajevi kada su stvarno potrebni i kada ste potpuno svesni specifičnosti i posledica njihove upotrebe. U ovoj objavi biće reči o liveness i readiness proverama, kao i o situacijama u kojima bi trebalo i ne bi trebalo da ih primenjujete.
Moj kolega Sandor je nedavno podelio na Twitteru najčešće greške koje mu se javljaju, uključujući one povezane sa korišćenjem readiness/liveness probes:
Pogrešno podešena livenessProbe može pogoršati situacije sa visokom opterećenošću (lavinasto isključivanje + potencijalno dug početak kontejnera/aplikacije) i dovesti do drugih negativnih posledica poput pada zavisnosti (vidi takođe o ograničavanju broja zahteva u kombinaciji K3s+ACME). Još gore, kada se liveness probe kombinuje sa proverom zdravlja zavisnosti (health check), gde je spoljašnja baza podataka: jedan jedini kvar Baze podataka resetovaće sve vaše kontejneri!
Opšti savet „Ne koristite liveness probes“ u ovom slučaju ne pomaže mnogo, pa hajde da razmotrimo za šta su intended readiness i liveness provere.
Napomena: veći deo u nastavku testiran je prvobitno uključen u internu dokumentaciju za programere Zalando.
Provere Readiness i Liveness
Kubernetes pruža dva važna mehanizma, nazivaju se . Oni povremeno izvršavaju neku radnju — na primer, šalju HTTP zahtev, otvaraju TCP vezu ili izvršavaju komandu unutar kontejnera — kako bi potvrdili da aplikacija ispravno radi.
Kubernetes uporablja readiness probes, da bi se razumelo, kdaj je kontejner pripravljen sprejemati promet. Pod se šteje za pripravljenega za delo, če so vsi njegovi kontejnerji pripravljeni. Ena od uporabe tega mehanizma je, da nadzira, kateri pod-se uporablja kot ozadje za Kubernetes storitve (in še posebej Ingress).
Preverjanje življenja pomaga Kubernetesu razumeti, kdaj je čas, da znova zažene kontejner. Na primer, takšna preverjanja lahko prestrežejo mrtvo točko, ko aplikacija 'obtiči' na enem mestu. Ponovni zagon kontejnerja v takem stanju pomaga premakniti aplikacijo z mrtve točke, kljub napakam, hkrati pa lahko privede do kaskadnih okvar (glej spodaj).
Če poskušate izvesti posodobitev aplikacije, ki ne uspe pri preverjanju življenja/začetne pripravljenosti, se bo njeno odvajanje ustavilo, saj bo Kubernetes čakal na stanje Ready vseh podov.
Primer
Tukaj je primer preverjanja pripravljenosti, ki preverja pot /health prek HTTP z privzetimi nastavitvami (interval: 10 sekund, časovni izostanek: 1 sekunda, prag uspeha: 1, prag neuspeha: 3):
# часть общего описания deployment'а/стека
podTemplate:
spec:
containers:
- name: my-container
# ...
readinessProbe:
httpGet:
path: /health
port: 8080Priporočila
- Za mikroservise z HTTP končnimi točkami (REST in podobno) vedno določite preverjanje pripravljenosti, ki preverja, ali je aplikacija (pod) pripravljena sprejemati promet.
- Preverite, da preverjanje pripravljenosti pokrije pripravljenost dejanskega porta spletnega strežnika:
- z uporabo portov za upravne namene, ki se imenujejo 'admin' ali 'management' (na primer 9090), za
preverjanjePripravljenosti, poskrbite, da končna točka vrne OK le, če je glavni HTTP port (kot 8080) pripravljen sprejemati promet*;* Zavedam se vsaj enega primera v Zalando, kjer tega ni bilo, namreč
preverjanjePripravljenostije preverila port 'management', vendar sam strežnik ni začel z delom zaradi težav z nalaganjem predpomnilnika. - dodeljevanje preverjanja pripravljenosti na ločen port lahko privede do tega, da obremenitev na glavnem portu ne bo odražala v zdravju preverjanja (to pomeni, da je rezerva niti na strežniku polna, vendar preverjanje zdravja še vedno kaže, da je vse OK).
- z uporabo portov za upravne namene, ki se imenujejo 'admin' ali 'management' (na primer 9090), za
- Uverite se da preverjanje pripravljenosti vključuje inicializacijo/migracijo baze podatkov;
- najlažji način, da to dosežete, je, da se obrnite na HTTP strežnik šele po končani inicializaciji (na primer, migraciji BDP z itd.); to pomeni, da namesto spreminjanja stanja zdravstvenega preverjanja, preprosto ne zaženete spletnega strežnika, dokler migracija baze podatkov ni zaključena*.
* Prav tako lahko zagnate migracije DB iz init-kontejnerjev zunaj pod’a. Še vedno sem privrženec samostojnih (self-contained) aplikacij, torej takih, kjer kontejner aplikacije brez zunanjega usklajevanja ve, kako postopati z DB in jo pripeljati v želeno stanje.
- najlažji način, da to dosežete, je, da se obrnite na HTTP strežnik šele po končani inicializaciji (na primer, migraciji BDP z itd.); to pomeni, da namesto spreminjanja stanja zdravstvenega preverjanja, preprosto ne zaženete spletnega strežnika, dokler migracija baze podatkov ni zaključena*.
- Iskoristite
httpGetza readiness preverjanja preko tipičnih endpointov health check-ov (na primer,/health). - Spoznajte privzete nastavitve preverjanj (
interval: 10s,timeout: 1s,successThreshold: 1,failureThreshold: 3):- privzete nastavitve pomenijo, da bo pod not-ready približno po 30 sekundah (3 neuspešna preverjanja delovanja).
- Za 'admin' ali 'management' uporabite ločeno vrata, če tehnologija (na primer, Java/Spring) to omogoča, da ločite upravljanje 'zdravja' in metrik od običajnega prometa:
- ampak ne pozabite na točko 2.
- Po potrebi se lahko readiness probe uporablja za ogrevanje/nalaganje predpomnilnika in vrača stanje 503, dokler se kontejner 'ne ogreje':
- priporočam tudi, da se seznanite z novim preverjanjem
startupProbe, (o tem smo pisali v slovenščini — op. prev.).
- priporočam tudi, da se seznanite z novim preverjanjem
Opozorila
- Ne zanašajte se na zunanje odvisnosti (kot so podatkovni skladi) pri izvedbi testov na readiness/liveness — to lahko povzroči kaskadne okvare:
- kot primer vzemimo stateful-storitev REST s 10 pod’i, odvisnimi od ene baze podatkov Postgres: ko preverjanje temelji na aktivni povezavi z DB, vseh 10 pod’ov lahko pade, če pride do zakasnitve v omrežju/na strani DB — običajno se vse skupaj konča slabše, kot bi se lahko;
- uporabite, da Spring Data privzeto preverja povezavo z DB*;
* Takšno je privzeto obnašanje Spring Data Redis (vsaj tako je bilo, ko sem to nazadnje preverjal), kar je pripeljalo do 'katastrofalne' napake: ko je bila Redis za kratek čas nedostopna, so vsi pod’i 'pali'.
- ‘zunanji’ v tem smislu lahko prav tako pomeni druge pod’e iste aplikacije, torej idealno preverjanje ne bi smelo biti odvisno od stanja drugih pod’ov v istem klastru, da se preprečijo kaskadna padanja:
- rezultati se lahko razlikujejo za aplikacije z razdistributed state (na primer, in-memory caching v pod’ih).
- Ne uporabljajte liveness probe za pod’e (izjeme so primeri, ko so res potrebni in popolnoma razumete specifikacijo in posledice njihove uporabe):
- liveness probe lahko prispeva k obnovitvi »zamrznjenih« kontejnerjev, vendar, saj imate popoln nadzor nad svojo aplikacijo, stvari, kot so »zamrznjeni« procesi in deadlock-i, v idealnem primeru ne bi smele nastati: najboljša alternativa je namerno sesutje aplikacije in njen povratak k prejšnjemu stabilnemu stanju;
- neuspela liveness probe bo povzročila ponovni zagon kontejnerja, kar lahko potencialno poslabša posledice napak, povezanih z nalaganjem: ponovni zagon kontejnerja bo povzročil zastoje (vsaj za čas zagon aplikacije, recimo, več kot 30 sekund), kar bo povzročilo nove napake, povečalo obremenitev drugih kontejnerjev in povečalo verjetnost njihovega sesutja itd.;
- liveness preizkusi skupaj z zunanjimi odvisnostmi so najslabša možna kombinacija, ki ogroža kaskadne napake: manjša zamuda na strani baze podatkov bo povzročila ponovni zagon vseh vaših kontejnerjev!
- Parametri liveness in readiness preizkusov morajo biti različni:
- lahko uporabite liveness probe z istim health check-om, vendar z višjo mejo sprožitve (
failureThreshold), na primer, dodelite status not-ready po 3 poskusih in štejete, da je liveness probe spodletel po 10 poskusih;
- lahko uporabite liveness probe z istim health check-om, vendar z višjo mejo sprožitve (
- Ne uporabljajte exec preizkusov, saj so povezane znane težave, ki vodijo do pojava zombijev procesov:
- podrobnosti: glej .
Резюме
- Uporabite readiness probes, da določite, kdaj je pod pripravljen za sprejem prometa.
- Uporabite liveness probes le, kadar so res potrebni.
- Nekoristna uporaba readiness/liveness probes lahko privede do zmanjšane dostopnosti in kaskadnih napak.
Dodatni materiali na to temo
- ;
- ;
- (govori tudi o livenessProbe).
Posodobitev №1 z dne 2019-09-29
: dodana opomba.
na PDB: ena od težav liveness preizkusov je pomanjkanje usklajevanja med pod-ji. V Kubernetesu obstaja za omejevanje števila hkratnih napak, ki jih lahko doživi aplikacija, vendar preizkusi ne upoštevajo PDB. V idealnem primeru lahko povemo K8s: »Ponovno zaženi en pod, če njegov preizkus ne uspe, vendar ne ponovno zaženi vseh, da ne bi poslabšal situacije«.
: „Uporabite liveness sondiranje, ko točno veste, da je najboljša izbira „ubiti“ aplikacijo“ (spet, ne pretiravajte).
Posodobitev št. 2 z dne 2019-09-29
: sem ustvaril ustrezen zahtevek () za dopolnitev dokumentacije o liveness sondah.
P.S. od prevajalca
Preberite tudi na našem blogu:
- «»;
- «»;
- «».
Izvor: habr.com
