Liveness-sonder i Kubernetes kan være farlige

Merk. overs.: Ledende ingeniør fra Zalando, Henning Jacobs, har gjentatte ganger lagt merke til problemer blant Kubernetes-brukere med å forstå hensikten med liveness (og beredskap)-prober og deres korrekte bruk. Derfor samlet han tankene sine i denne fyldige notaten, som etter hvert vil bli en del av K8s dokumentasjon.

Liveness-sonder i Kubernetes kan være farlige

Helsesjekker, kjent i Kubernetes som livlighetsonder (dvs. bokstavelig talt "levedyktighetstester" - ca. oversettelse), kan være ganske farlig. Jeg anbefaler å unngå dem hvis mulig: de eneste unntakene er når de virkelig er nødvendige og du er fullstendig klar over spesifikasjonene og konsekvensene av bruken. Denne publikasjonen vil snakke om liveness- og beredskapskontroller, og vil også fortelle deg i hvilke tilfeller er og du bør ikke bruke dem.

Min kollega Sandor delte nylig på Twitter de vanligste feilene han støter på, inkludert de som er relatert til bruk av beredskaps-/liveness-sonder:

Liveness-sonder i Kubernetes kan være farlige

Feil konfigurert livenessProbe kan forverre situasjoner med høy belastning (avstengning av snølast + potensielt lang oppstartstid for container/applikasjon) og føre til andre negative konsekvenser som avhengighetsfall (se også min siste artikkel om å begrense antall forespørsler i kombinasjonen K3s+ACME). Det er enda verre når liveness-sonden er kombinert med en helsesjekk, som er en ekstern database: en enkelt DB-feil vil starte alle beholderne på nytt!

Generell melding "Ikke bruk liveness-prober" i dette tilfellet hjelper det lite, så la oss se på hva beredskaps- og liveness-sjekkene er for.

Merk: Det meste av testen nedenfor ble opprinnelig inkludert i Zalandos interne utviklerdokumentasjon.

Beredskaps- og Liveness-sjekker

Kubernetes gir to viktige mekanismer kalt liveness-sonder og beredskapssonder. De utfører med jevne mellomrom en handling – for eksempel å sende en HTTP-forespørsel, åpne en TCP-tilkobling eller utføre en kommando i beholderen – for å bekrefte at applikasjonen fungerer som forventet.

Kubernetes bruker beredskapsundersøkelserfor å forstå når beholderen er klar til å akseptere trafikk. En pod anses som klar til bruk hvis alle beholderne er klare. En bruk av denne mekanismen er å kontrollere hvilke pods som brukes som backends for Kubernetes-tjenester (og spesielt Ingress).

Liveness sonder hjelpe Kubernetes med å forstå når det er på tide å starte beholderen på nytt. En slik sjekk lar deg for eksempel avskjære en vranglås når en applikasjon blir sittende fast på ett sted. Å starte beholderen på nytt i denne tilstanden hjelper med å få applikasjonen i gang til tross for feil, men det kan også føre til kaskadefeil (se nedenfor).

Hvis du prøver å distribuere en applikasjonsoppdatering som mislykkes i live-/beredskapskontrollene, vil utrullingen stoppe mens Kubernetes venter på statusen Ready fra alle pods.

Eksempel

Her er et eksempel på en beredskapssonde som sjekker en bane /health via HTTP med standardinnstillinger (pause: 10 sekunder, timeout: 1 sekund, suksessgrense: 1, feilterskel: 3):

# часть общего описания deployment'а/стека
podTemplate:
  spec:
    containers:
    - name: my-container
      # ...
      readinessProbe:
        httpGet:
          path: /health
          port: 8080

anbefalinger

  1. For mikrotjenester med HTTP-endepunkt (REST, etc.) definer alltid en beredskapssonde, som sjekker om applikasjonen (pod) er klar til å akseptere trafikk.
  2. Sørg for at beredskapssonden dekker tilgjengeligheten til den faktiske webserverporten:
    • bruke porter for administrative formål, kalt "admin" eller "administrasjon" (for eksempel 9090), for readinessProbe, sørg for at endepunktet bare returnerer OK hvis den primære HTTP-porten (som 8080) er klar til å akseptere trafikk*;

      *Jeg kjenner til minst ett tilfelle hos Zalando hvor dette ikke skjedde, dvs. readinessProbe Jeg sjekket "administrasjon"-porten, men selve serveren begynte ikke å fungere på grunn av problemer med å laste cachen.

    • å koble en beredskapssonde til en egen port kan føre til at overbelastning på hovedporten ikke vil gjenspeiles i helsesjekken (det vil si at trådpoolen på serveren er full, men helsesjekken viser fortsatt at alt er i orden ).
  3. Sørge for at beredskapssonde muliggjør databaseinitialisering/migrering;
    • Den enkleste måten å oppnå dette på er å kontakte HTTP-serveren først etter at initialiseringen er fullført (for eksempel migrering av en database fra flyway og så videre.); det vil si at i stedet for å endre status for helsesjekk, må du ganske enkelt ikke starte webserveren før databasemigreringen er fullført*.

      * Du kan også kjøre databasemigreringer fra init-beholdere utenfor poden. Jeg er fortsatt en fan av selvstendige applikasjoner, det vil si de der applikasjonsbeholderen vet hvordan den skal bringe databasen til ønsket tilstand uten ekstern koordinering.

  4. bruk httpGet for beredskapskontroller gjennom typiske helsesjekkendepunkter (f.eks. /health).
  5. Forstå standard kontrollparametere (interval: 10s, timeout: 1s, successThreshold: 1, failureThreshold: 3):
    • standardalternativene betyr at poden blir ikke klar etter ca. 30 sekunder (3 mislykkede tilregnelighetskontroller).
  6. Bruk en egen port for "admin" eller "administrasjon" hvis teknologistabelen (f.eks. Java/Spring) tillater det, for å skille helse- og metrikkadministrasjon fra vanlig trafikk:
    • men ikke glem punkt 2.
  7. Om nødvendig kan beredskapssonden brukes til å varme opp/laste cachen og returnere en 503 statuskode til beholderen varmes opp:
    • Jeg anbefaler også at du leser den nye sjekken startupProbe, dukket opp i versjon 1.16 (vi skrev om det på russisk her — ca. oversett.).

Forsiktighetsregler

  1. Ikke stol på eksterne avhengigheter (for eksempel datavarehus) når du kjører beredskaps-/levetidstester - dette kan føre til kaskadefeil:
    • Som et eksempel, la oss ta en stateful REST-tjeneste med 10 pods avhengig av en Postgres-database: når sjekken avhenger av en fungerende tilkobling til DB, kan alle 10 pods mislykkes hvis det er en forsinkelse på nettverks-/DB-siden - vanligvis alt ender verre enn det kunne;
    • Vær oppmerksom på at Spring Data sjekker databasetilkoblingen som standard*;

      * Dette er standardoppførselen til Spring Data Redis (det var i alle fall siste gang jeg sjekket), noe som førte til en "katastrofal" feil: når Redis var utilgjengelig i en kort periode, "krasjet" alle pods.

    • "ekstern" i denne forstand kan også bety andre pods av samme applikasjon, det vil si at kontrollen ideelt sett ikke bør avhenge av tilstanden til andre pods i samme klynge for å forhindre kaskadekrasj:
      • resultatene kan variere for applikasjoner med distribuert tilstand (for eksempel caching i minnet i pods).
  2. Ikke bruk en liveness-sonde for pods (unntak er tilfeller når de virkelig er nødvendige og du er fullstendig klar over spesifikasjonene og konsekvensene av bruken):
    • En liveness-sonde kan hjelpe til med å gjenopprette hengte beholdere, men siden du har full kontroll over applikasjonen din, bør ting som hengte prosesser og vranglåser ideelt sett ikke skje: det beste alternativet er å bevisst krasje applikasjonen og bringe den tilbake til tidligere stabil tilstand;
    • en mislykket liveness-probe vil føre til at beholderen starter på nytt, og dermed potensielt forverre konsekvensene av lastingsrelaterte feil: omstart av beholderen vil resultere i nedetid (i det minste i løpet av programmets oppstart, for eksempel 30 sekunder), og forårsake nye feil , øke belastningen på andre containere og øke sannsynligheten for feil, etc.;
    • Liveness-sjekker kombinert med en ekstern avhengighet er den verst tenkelige kombinasjonen, som truer kaskadefeil: en liten forsinkelse på databasesiden vil føre til omstart av alle containerne dine!
  3. Parametre for liveness og beredskapskontroller må være annerledes:
    • du kan bruke en liveness-sonde med samme helsesjekk, men en høyere responsterskel (failureThreshold), for eksempel tilordne statusen ikke klar etter 3 forsøk og tenk på at liveness-sonden har sviktet etter 10 forsøk;
  4. Ikke bruk exec-sjekker, siden de er assosiert med kjente problemer som fører til utseendet til zombieprosesser:

Oppsummering

  • Bruk beredskapssonder for å finne ut når en pod er klar til å motta trafikk.
  • Bruk liveness-prober bare når de virkelig er nødvendige.
  • Feil bruk av beredskaps-/levende-prober kan føre til redusert tilgjengelighet og kaskadefeil.

Liveness-sonder i Kubernetes kan være farlige

Tilleggsmateriell om temaet

Oppdatering nr. 1 fra 2019-09-29

Om init-beholdere for databasemigrering: Fotnote lagt til.

EJ minnet meg på om PDB: et av problemene med liveness-sjekker er mangelen på koordinering mellom pods. Kubernetes har Pod-avbruddsbudsjetter (PDB) for å begrense antallet samtidige feil en applikasjon kan oppleve, men sjekkene tar ikke hensyn til PDB. Ideelt sett kan vi fortelle K8s å "Starte en pod på nytt hvis testen mislykkes, men ikke start dem alle på nytt for å unngå å gjøre ting verre."

Bryan sa det perfekt: «Bruk liveness-probing når du vet nøyaktig hva den beste tingen å gjøre er å drepe programmet"(igjen, ikke la deg rive med).

Liveness-sonder i Kubernetes kan være farlige

Oppdatering nr. 2 fra 2019-09-29

Angående lesing av dokumentasjonen før bruk: Jeg opprettet den tilsvarende forespørselen (funksjon forespørsel) for å legge til dokumentasjon om liveness-sonder.

PS fra oversetter

Les også på bloggen vår:

Kilde: www.habr.com

Legg til en kommentar