Liveness-sonder i Kubernetes kan være farlige

Bemærk. overs.: Ledende ingeniør fra Zalando, Henning Jacobs, har gentagne gange bemærket problemer blandt Kubernetes-brugere med at forstå formålet med liveness (og parathed) sonder og deres korrekte brug. Derfor samlede han sine tanker i denne rummelige note, som med tiden bliver en del af K8s dokumentation.

Liveness-sonder i Kubernetes kan være farlige

Sundhedstjek, kendt i Kubernetes som livlighedsonder (dvs. bogstaveligt talt "levedygtighedstests" - ca. oversættelse), kan være ret farligt. Jeg anbefaler at undgå dem, hvis det er muligt: ​​de eneste undtagelser er, når de virkelig er nødvendige, og du er fuldt ud klar over de specifikke og konsekvenser af deres brug. Denne publikation vil tale om livlighed og beredskabskontrol og vil også fortælle dig i hvilke tilfælde omkostninger og du bør ikke bruge dem.

Min kollega Sandor delte for nylig på Twitter de mest almindelige fejl, han støder på, inklusive dem, der er relateret til brugen af ​​paratheds-/liveness-sonder:

Liveness-sonder i Kubernetes kan være farlige

Forkert konfigureret livenessProbe kan forværre situationer med høj belastning (nedlukning af snebold + potentielt lang opstartstid for container/applikation) og føre til andre negative konsekvenser såsom afhængighedsfald (se også min seneste artikel om at begrænse antallet af anmodninger i kombinationen K3s+ACME). Det er endnu værre, når liveness-sonden er kombineret med et sundhedstjek, som er en ekstern database: en enkelt DB-fejl vil genstarte alle dine containere!

Generel besked "Brug ikke liveness-prober" i dette tilfælde hjælper det ikke meget, så lad os se på, hvad beredskabs- og liveness-tjekket går ud på.

Bemærk: Det meste af testen nedenfor var oprindeligt inkluderet i Zalandos interne udviklerdokumentation.

Beredskabs- og Liveness-tjek

Kubernetes giver to vigtige mekanismer kaldet liveness-sonder og parathedsonder. De udfører med jævne mellemrum en handling – såsom at sende en HTTP-anmodning, åbne en TCP-forbindelse eller udføre en kommando i containeren – for at bekræfte, at applikationen fungerer som forventet.

Kubernetes bruger beredskabsonderat forstå, hvornår containeren er klar til at acceptere trafik. En pod anses for klar til brug, hvis alle dens beholdere er klar. En anvendelse af denne mekanisme er at kontrollere, hvilke pods der bruges som backends til Kubernetes-tjenester (og især Ingress).

Liveness sonder hjælpe Kubernetes med at forstå, hvornår det er tid til at genstarte containeren. Et sådant tjek giver dig f.eks. mulighed for at opsnappe et dødvande, når en applikation sætter sig fast ét ​​sted. Genstart af beholderen i denne tilstand hjælper med at få applikationen i gang på trods af fejl, men det kan også føre til kaskadefejl (se nedenfor).

Hvis du forsøger at implementere en applikationsopdatering, der ikke klarer kontrollen af ​​liveness/beredskab, vil dens udrulning blive stoppet, mens Kubernetes venter på status Ready fra alle bælg.

Eksempel

Her er et eksempel på en parathedssonde, der kontrollerer en sti /health via HTTP med standardindstillinger (interval: 10 sekunder, timeout: 1 sekund, succesgrænse: 1, fejlgrænse: 3):

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

Anbefalinger

  1. Til mikrotjenester med HTTP-endepunkt (REST osv.) definere altid en parathedssonde, som kontrollerer, om applikationen (pod) er klar til at acceptere trafik.
  2. Sørg for parathedssonden dækker tilgængeligheden af ​​den faktiske webserverport:
    • bruge porte til administrative formål, kaldet "admin" eller "administration" (f.eks. 9090), for readinessProbe, sørg for, at endepunktet kun returnerer OK, hvis den primære HTTP-port (som 8080) er klar til at acceptere trafik*;

      *Jeg er bekendt med mindst et tilfælde hos Zalando, hvor dette ikke skete, dvs. readinessProbe Jeg tjekkede "management"-porten, men selve serveren begyndte ikke at fungere på grund af problemer med at indlæse cachen.

    • at tilslutte en parathedsprobe til en separat port kan føre til, at overbelastning på hovedporten ikke vil blive afspejlet i sundhedstjekket (det vil sige, at trådpuljen på serveren er fuld, men sundhedstjekket viser stadig, at alt er OK ).
  3. Sørg for at parathedssonde muliggør initialisering/migrering af databasen;
    • Den nemmeste måde at opnå dette på er først at kontakte HTTP-serveren efter initialiseringen er fuldført (f.eks. migrering af en database fra Flyvej og så videre.); det vil sige, i stedet for at ændre status for sundhedstjekket, skal du simpelthen ikke starte webserveren, før databasemigreringen er gennemført*.

      * Du kan også køre databasemigreringer fra init-beholdere uden for poden. Jeg er stadig fan af selvstændige applikationer, det vil sige dem, hvor applikationsbeholderen ved, hvordan man bringer databasen i den ønskede tilstand uden ekstern koordinering.

  4. brug httpGet til beredskabstjek gennem typiske sundhedstjek-endepunkter (f.eks. /health).
  5. Forstå standardkontrolparametrene (interval: 10s, timeout: 1s, successThreshold: 1, failureThreshold: 3):
    • standardindstillingerne betyder, at poden bliver ikke klar efter ca. 30 sekunder (3 mislykkede sundhedstjek).
  6. Brug en separat port til "admin" eller "administration", hvis teknologistakken (f.eks. Java/Spring) tillader det, for at adskille sundheds- og metrikstyring fra almindelig trafik:
    • men glem ikke punkt 2.
  7. Om nødvendigt kan parathedssonden bruges til at varme op/indlæse cachen og returnere en 503 statuskode, indtil beholderen varmer op:
    • Jeg anbefaler også, at du læser den nye check startupProbe, dukkede op i version 1.16 (vi skrev om det på russisk her - ca. oversættelse).

Forsigtig

  1. Stol ikke på eksterne afhængigheder (såsom datavarehuse), når du kører paratheds-/levetidstests - dette kan føre til kaskadefejl:
    • Lad os som eksempel tage en stateful REST-tjeneste med 10 pods afhængigt af en Postgres-database: når kontrollen afhænger af en fungerende forbindelse til DB'en, kan alle 10 pods fejle, hvis der er en forsinkelse på netværks-/DB-siden - normalt alt ender værre end det kunne;
    • Bemærk venligst, at Spring Data kontrollerer databaseforbindelsen som standard*;

      * Dette er standardadfærden for Spring Data Redis (det var i hvert fald sidste gang, jeg tjekkede), hvilket førte til en "katastrofisk" fejl: da Redis var utilgængelig i kort tid, "styrtede alle pods".

    • "ekstern" i denne forstand kan også betyde andre pods af samme applikation, dvs. ideelt set bør kontrollen ikke afhænge af tilstanden af ​​andre pods i samme klynge for at forhindre cascading crashes:
      • resultaterne kan variere for applikationer med distribueret tilstand (f.eks. caching i hukommelsen i pods).
  2. Brug ikke en liveness-sonde for bælg (undtagelser er tilfælde, hvor de virkelig er nødvendige, og du er fuldt ud klar over de specifikke og konsekvenser af deres brug):
    • En liveness-sonde kan hjælpe med at gendanne ophængte beholdere, men da du har fuld kontrol over din applikation, bør ting som hængte processer og deadlocks ideelt set ikke ske: Det bedste alternativ er bevidst at crashe applikationen og bringe den tilbage til tidligere stabil tilstand;
    • en mislykket liveness-sonde vil få containeren til at genstarte, og derved potentielt forværre konsekvenserne af indlæsningsrelaterede fejl: genstart af containeren vil resultere i nedetid (i det mindste under varigheden af ​​applikationens opstart, f.eks. 30 sekunder), hvilket forårsager nye fejl , øge belastningen på andre containere og øge sandsynligheden for deres fejl osv.;
    • Liveness-tjek kombineret med en ekstern afhængighed er den værst tænkelige kombination, der truer cascading-fejl: en lille forsinkelse på databasesiden vil føre til en genstart af alle dine containere!
  3. Parametre for kontrol af livlighed og beredskab skal være anderledes:
    • du kan bruge en liveness-sonde med det samme sundhedstjek, men en højere responstærskel (failureThreshold), for eksempel tildele status ikke klar efter 3 forsøg og overvej, at liveness-sonden har svigtet efter 10 forsøg;
  4. Brug ikke exec checks, da de er forbundet med kendte problemer, der fører til udseendet af zombieprocesser:

Resumé

  • Brug parathedsprober til at bestemme, hvornår en pod er klar til at acceptere trafik.
  • Brug kun liveness-prober, når de virkelig er nødvendige.
  • Forkert brug af beredskabs-/liveness-prober kan føre til reduceret tilgængelighed og kaskadefejl.

Liveness-sonder i Kubernetes kan være farlige

Yderligere materialer om emnet

Opdatering nr. 1 fra 2019-09-29

Om init-beholdere til databasemigrering: Fodnote tilføjet.

EJ mindede mig om FBF: et af problemerne med kontrol af livlighed er den manglende koordinering mellem pods. Kubernetes har Pod-forstyrrelsesbudgetter (PDB) for at begrænse antallet af samtidige fejl, som en applikation kan opleve, men kontrollerne tager ikke hensyn til FBF. Ideelt set kunne vi fortælle K8s at "Genstarte en pod, hvis testen mislykkes, men genstart ikke dem alle for at undgå at gøre tingene værre."

Bryan udtrykte det perfekt: “Brug liveness probing, når du ved præcis hvad den bedste ting at gøre er at dræbe applikationen"(igen, lad dig ikke rive med).

Liveness-sonder i Kubernetes kan være farlige

Opdatering nr. 2 fra 2019-09-29

Vedrørende læsning af dokumentationen før brug: Jeg oprettede den tilsvarende anmodning (funktion anmodning) for at tilføje dokumentation om liveness-sonder.

PS fra oversætteren

Læs også på vores blog:

Kilde: www.habr.com

Tilføj en kommentar