Liveness probes i Kubernetes kan vara farliga

Obs. övers.: Ledande ingenjör pĂ„ Zalando — Henning Jacobs — har flera gĂ„nger noterat att anvĂ€ndare av Kubernetes har problem med att förstĂ„ syftet med liveness (och readiness) probes och hur de ska anvĂ€ndas korrekt. DĂ€rför har han samlat sina tankar i denna korta anteckning, som med tiden kommer att bli en del av K8s-dokumentationen.

Liveness probes i Kubernetes kan vara farliga

De tillstĂ„ndskontroller som i Kubernetes kallas liveness probes (dvs. bokstavligen "livskrafttester" — obs. övers.), kan vara bastante farliga. Jag rekommenderar att undvika dem om möjligt: undantagen Ă€r endast fall dĂ€r de verkligen Ă€r nödvĂ€ndiga och dĂ€r du fullt ut förstĂ„r specifiken och konsekvenserna av deras anvĂ€ndning. Denna publikation kommer att handla om liveness- och readiness-kontroller, och det kommer att diskuteras i vilka fall befinner sig och inte ska tillĂ€mpas.

Min kollega Sandor delade nyligen pÄ Twitter de vanligaste felen han stöter pÄ, inklusive de relaterade till anvÀndningen av readiness/liveness probes:

Liveness probes i Kubernetes kan vara farliga

Felaktigt konfigurerad livenessProbe kan förvĂ€rra situationer med hög belastning (snöbollseffekt + potentiellt lĂ„ng start av container/applikation) och leda till andra negativa konsekvenser som att beroenden faller (se Ă€ven min senaste artikel om att begrĂ€nsa antalet förfrĂ„gningar i kombinationen K3s+ACME). Ännu vĂ€rre Ă€r det nĂ€r en liveness probe kombineras med hĂ€lsokontroll av ett beroende (health check), som i detta fall Ă€r en extern databas: ett enda databasfel kommer att Ă„terstarta alla era containrar!

Det övergripande budskapet "AnvÀnd inte liveness probes" Àr i detta fall inte till stor hjÀlp, sÄ lÄt oss titta pÄ vad syftet med readiness- och liveness-kontroller Àr.

Obs: Största delen av testet nedan var ursprungligen inkluderat i den interna dokumentationen för utvecklare pÄ Zalando.

Readiness och Liveness-kontroller

Kubernetes erbjuder tvĂ„ viktiga mekanismer som kallas liveness probes och readiness probes. De utför regelbundet en Ă„tgĂ€rd — till exempel skickar en HTTP-förfrĂ„gan, öppnar en TCP-anslutning eller kör ett kommando i containern — för att bekrĂ€fta att applikationen fungerar korrekt.

Kubernetes anvÀnder readiness probes, för att förstÄ nÀr en pod Àr redo att ta emot trafik. En pod anses vara redo om alla dess containrar Àr klara. En av tillÀmpningarna av denna mekanism Àr att kontrollera vilka pods som anvÀnds som backend för Kubernetes-tjÀnster (och sÀrskilt Ingress).

LivlighetspÄstÄenden hjÀlper Kubernetes att förstÄ nÀr det Àr dags att starta om en container. Till exempel kan en sÄdan kontroll fÄnga ett deadlock, nÀr applikationen "fastnar" pÄ en plats. Att starta om containern i ett sÄdant tillstÄnd hjÀlper till att fÄ applikationen i rörelse igen, trots fel, men det kan ocksÄ leda till kaskadeffekter (se nedan).

Om du försöker driftsÀtta en applikationsuppdatering som misslyckas med livlighets-/beredskapskontroller, kommer driftsÀttningen att stanna, eftersom Kubernetes vÀntar pÄ status Redo frÄn alla pods.

Exempel

HÀr Àr ett exempel pÄ en beredskapskontroll som kontrollerar vÀgen /health via HTTP med standardinstÀllningar (intervall: 10 sekunder, timeout: 1 sekund, framgÄngströskel: 1, misslyckandetröskel: 3):

# часть ĐŸĐ±Ń‰Đ”ĐłĐŸ ĐŸĐżĐžŃĐ°ĐœĐžŃ deployment'а/стДĐșа
podTemplate:
  spec:
    containers:
    - name: my-container
      # ...
      readinessProbe:
        httpGet:
          path: /health
          port: 8080

Rekommendationer

  1. För mikrotjÀnster med HTTP-endpoint (REST osv.) definiera alltid en beredskapskontroll, som kontrollerar om applikationen (pod) Àr redo att ta emot trafik.
  2. Se till att beredskapskontrollen tÀckar beredskapen hos den faktiska webbserverporten:
    • anvĂ€nder portar för administrativa Ă€ndamĂ„l, kallade "admin" eller "management" (t.ex. 9090), för beredskapskontroll, se till att endpointen returnerar OK endast om den primĂ€ra HTTP-porten (som 8080) Ă€r redo att ta emot trafik*;

      * Jag vet Ätminstone om ett fall pÄ Zalando dÀr detta inte skedde, det vill sÀga beredskapskontroll kontrollerade "management"-porten, men servern startade aldrig pÄ grund av problem med cache-laddningen.

    • att koppla beredskapskontrollen till en separat port kan leda till att belastningen pĂ„ den primĂ€ra porten inte speglas i hĂ€lsokontrollen (det vill sĂ€ga trĂ„dpoolen pĂ„ servern Ă€r fylld, men hĂ€lsokontrollen visar fortfarande att allt Ă€r OK).
  3. Se till att beredskapskontrollen inkluderar initiering/migrering av databasen;
    • det enklaste sĂ€ttet att uppnĂ„ detta Ă€r att bara göra HTTP-anrop efter att initieringen har slutförts (t.ex. databas-migrering med Flyway osv.); det vill sĂ€ga istĂ€llet för att Ă€ndra hĂ€lsokontrollens status, starta helt enkelt inte webbservern förrĂ€n databas-migreringen Ă€r klar*.

      * Det gÄr ocksÄ att köra databasöverflyttningar frÄn init-containrar utanför podden. Jag Àr fortfarande en beundrare av fristÄende appar, dÀr applikationens container vet hur den ska stÀlla in databasen utan extern koordination.

  4. AnvÀnd httpGet för readiness-kontroller via typiska health check-endpoints (till exempel, /health).
  5. FörstÄ standardinstÀllningarna för kontrollerna (interval: 10s, timeout: 1s, successThreshold: 1, failureThreshold: 3):
    • standardinstĂ€llningarna innebĂ€r att podden kommer att bli not-ready ungefĂ€r efter 30 sekunder (3 misslyckade hĂ€lsokontroller).
  6. AnvÀnd en separat port för "admin" eller "management", om teknikstacken (till exempel, Java/Spring) tillÄter det, för att separera "hÀlsosam" och metrics frÄn vanlig trafik:
    • men glöm inte punkt 2.
  7. Om nödvÀndigt kan readiness probe anvÀndas för att förvÀrma/ladda cachen och returnera statuskod 503, tills containern Àr "fÀrdig":

Varningar

  1. Lita inte pĂ„ externa beroenden (sĂ„som datalagringssystem) vid utförande av readiness/liveness tester – detta kan leda till kaskadfel:
    • som ett exempel, lĂ„t oss ta en stateful REST-tjĂ€nst med 10 poddar som Ă€r beroende av en enda Postgres-databas: nĂ€r kontrollen beror pĂ„ en fungerande databasanslutning kan alla 10 poddar krascha om det blir en fördröjning i nĂ€tverket/vid databasen – vanligtvis slutar allt detta sĂ€mre Ă€n det borde;
    • Notera att Spring Data som standard kontrollerar databasanslutningen*;

      * Detta Àr standardbeteendet för Spring Data Redis (Ätminstone var det sÄ nÀr jag kontrollerade senast), vilket ledde till ett "katastrofalt" fel: nÀr Redis var otillgÀnglig under en kort tid, föll alla poddar.

    • "externt" i detta sammanhang kan ocksĂ„ betyda andra poddar av samma applikation, sĂ„ i idealfallet bör kontrollen inte bero pĂ„ tillstĂ„ndet hos andra poddar i samma kluster för att förhindra kaskadfel:
      • resultaten kan variera för applikationer med distribuerat tillstĂ„nd (till exempel, in-memory caching i poddar).
  2. AnvÀnd inte liveness probe för poddar (undantag ges för fall nÀr de verkligen behövs och du Àr fullt medveten om specifikationen och konsekvenserna av att anvÀnda dem):
    • liveness-proben kan hjĂ€lpa till att Ă„terstĂ€lla "hĂ€ngande" containrar, men eftersom du har full kontroll över din applikation bör sĂ„dana saker som "hĂ€ngande" processer och dödlĂ€gen i idealfallet inte intrĂ€ffa: det bĂ€sta alternativet Ă€r att avsiktligt stĂ€nga ner applikationen och Ă„terföra den till ett tidigare stabilt tillstĂ„nd;
    • ett misslyckat liveness-prover leder till att containern startas om, vilket potentiellt förvĂ€rrar konsekvenserna av fel relaterade till lastning: omstart av containern kommer att orsaka stillestĂ„nd (Ă„tminstone under applikationens starttid, sĂ€g mer Ă€n 30 sekunder), vilket skapar nya fel, ökar belastningen pĂ„ andra containrar och ökar risken för deras misslyckande, etc.;
    • liveness-kontroller i kombination med externa beroenden Ă€r den vĂ€rsta av möjliga kombinationer och hotar med kaskadmisslyckanden: en obetydlig fördröjning frĂ„n databasen leder till att alla dina containrar startas om!
  3. Parametrar för liveness- och readiness-kontroller bör vara olika:
    • liveness-proben kan anvĂ€nda samma hĂ€lsokontroll, men med en högre tröskel för utlösning (failureThreshold), till exempel, ge status not-ready efter 3 försök och betrakta att liveness-proben misslyckas efter 10 försök;
  4. AnvÀnd inte exec-kontroller, eftersom de Àr förknippade med vÀlkÀnda problem som leder till zombiprocesser:

Sammanfattning

  • AnvĂ€nd readiness probes för att bestĂ€mma nĂ€r podden Ă€r redo att ta emot trafik.
  • AnvĂ€nd liveness probes endast nĂ€r de verkligen Ă€r nödvĂ€ndiga.
  • Felaktig anvĂ€ndning av readiness/liveness probes kan leda till minskad tillgĂ€nglighet och kaskadmisslyckanden.

Liveness probes i Kubernetes kan vara farliga

Ytterligare material om Àmnet

Uppdatering nr 1 frÄn 2019-09-29

Om init-containrar för databasflyttningar: en fotnot har lagts till.

EJ pÄminde mig om PDB: en av problemen med liveness-kontroller Àr bristen pÄ samordning mellan poddar. I Kubernetes finns det Pod Disruption Budgets (PDB) för att begrÀnsa antalet parallella kraschningar som en applikation kan uppleva, men kontrollerna tar inte hÀnsyn till PDB. I idealfallet kan vi be K8s: "Starta om en pod om dess kontroll misslyckas, men starta inte om alla, för att inte göra det Ànnu vÀrre."

Bryan uttryckte det utmÀrkt: "AnvÀnd liveness-probing nÀr du Àr sÀker pÄ att det bÀsta som kan göras Àr att "döda" applikationen" (Äterigen, var försiktig med detta).

Liveness probes i Kubernetes kan vara farliga

Uppdatering #2 frÄn 2019-09-29

NÀr det kommer till att lÀsa dokumentationen innan anvÀndning: jag skapade en relevant begÀran (feature request) för att komplettera dokumentationen om liveness probes.

P.S. frÄn översÀttaren

LÀs Àven i vÄr blogg:

KĂ€lla: habr.com

Köp pĂ„litlig webbhotell med DDoS-skydd, VPS VDS-servrar đŸ”„ Köp pĂ„litlig webbhotell med DDoS-skydd, VPS VDS-servrar | ProHoster