Beste praksis for Kubernetes-beholdere: Helsesjekker

Beste praksis for Kubernetes-beholdere: Helsesjekker

TL; DR

  • For å oppnå høy observerbarhet av containere og mikrotjenester er ikke logger og primære beregninger nok.
  • For raskere gjenoppretting og økt motstandskraft bør applikasjoner bruke High Observability Principle (HOP).
  • På applikasjonsnivå krever NOP: riktig logging, tett overvåking, helsekontroll og ytelse/overgangssporing.
  • Bruk sjekker som et element i NOR beredskapProbe и livlighet Sonde Kubernetes.

Hva er en mal for helsesjekk?

Når du designer en virksomhetskritisk og svært tilgjengelig applikasjon, er det svært viktig å tenke på et slikt aspekt som feiltoleranse. En applikasjon anses som feiltolerant hvis den kommer seg raskt etter feil. En typisk skyapplikasjon bruker en mikrotjenestearkitektur – der hver komponent er plassert i en separat beholder. Og for å sikre at applikasjonen på k8s er svært tilgjengelig når du designer en klynge, må du følge visse mønstre. Blant dem er malen for helsesjekk. Den definerer hvordan applikasjonen kommuniserer til k8s at den er sunn. Dette er ikke bare informasjon om poden kjører, men også om hvordan den mottar og svarer på forespørsler. Jo mer Kubernetes vet om helsen til poden, jo smartere avgjørelser tar den om trafikkruting og lastbalansering. Derfor tillater High Observability Principle applikasjonen å svare på forespørsler i tide.

Høyt observerbarhetsprinsipp (HOP)

Prinsippet om høy observerbarhet er ett av prinsipper for utforming av containeriserte applikasjoner. I en mikrotjenestearkitektur bryr ikke tjenester seg om hvordan forespørselen deres behandles (og med rette), men det som betyr noe er hvordan de mottar svar fra mottakstjenestene. For eksempel, for å autentisere en bruker, sender en beholder en HTTP-forespørsel til en annen, og forventer et svar i et bestemt format - det er alt. PythonJS kan også behandle forespørselen, og Python Flask kan svare. Containere er som svarte bokser med skjult innhold for hverandre. NOP-prinsippet krever imidlertid at hver tjeneste eksponerer flere API-endepunkter som indikerer hvor sunn den er, samt dens beredskap og feiltoleransestatus. Kubernetes ber om disse indikatorene for å tenke gjennom de neste trinnene for ruting og lastbalansering.

En godt designet skyapplikasjon logger hovedhendelsene sine ved å bruke standard I/O-strømmene STDERR og STDOUT. Deretter kommer en tilleggstjeneste, for eksempel filebeat, logstash eller fluentd, som leverer logger til et sentralisert overvåkingssystem (for eksempel Prometheus) og et logginnsamlingssystem (ELK programvarepakke). Diagrammet nedenfor viser hvordan en skyapplikasjon fungerer i henhold til Health Test Pattern og High Observability Principle.

Beste praksis for Kubernetes-beholdere: Helsesjekker

Hvordan bruker jeg helsesjekkmønsteret i Kubernetes?

Ut av esken overvåker k8s statusen til podene ved hjelp av en av kontrollerene (distribusjoner, Replikasett, DaemonSets, StatefulSets etc., etc.). Etter å ha oppdaget at poden har falt av en eller annen grunn, prøver kontrolleren å starte den på nytt eller flytte den til en annen node. En pod kan imidlertid rapportere at den er oppe og går, men at den i seg selv ikke fungerer. La oss gi et eksempel: applikasjonen din bruker Apache som en webserver, du installerte komponenten på flere pods i klyngen. Siden biblioteket ble konfigurert feil, svarer alle forespørsler til applikasjonen med kode 500 (intern serverfeil). Når du sjekker levering, gir sjekk av status på pod et vellykket resultat, men kundene tenker annerledes. Vi vil beskrive denne uønskede situasjonen som følger:

Beste praksis for Kubernetes-beholdere: Helsesjekker

I vårt eksempel gjør k8s det funksjonssjekk. I denne typen verifisering sjekker kubelet kontinuerlig tilstanden til prosessen i beholderen. Når han forstår at prosessen har stoppet, vil han starte den på nytt. Hvis feilen kan løses ved ganske enkelt å starte applikasjonen på nytt, og programmet er utformet for å stenge av enhver feil, er en prosesshelsesjekk alt du trenger for å følge NOP og Health Test Pattern. Den eneste synden er at ikke alle feil elimineres ved omstart. I dette tilfellet tilbyr k8s 2 dypere måter å identifisere problemer med poden på: livlighet Sonde и beredskapProbe.

LivenessProbe

Under livlighet Sonde kubelet utfører 3 typer kontroller: ikke bare bestemmer om poden kjører, men også om den er klar til å motta og svare tilstrekkelig på forespørsler:

  • Sett opp en HTTP-forespørsel til poden. Svaret må inneholde en HTTP-svarkode i området fra 200 til 399. Dermed signaliserer kodene 5xx og 4xx at poden har problemer, selv om prosessen kjører.
  • For å teste poder med ikke-HTTP-tjenester (for eksempel Postfix-postserveren), må du opprette en TCP-tilkobling.
  • Utfør en vilkårlig kommando for en pod (internt). Kontrollen anses som vellykket hvis kommandofullføringskoden er 0.

Et eksempel på hvordan dette fungerer. Den neste poddefinisjonen inneholder en NodeJS-applikasjon som kaster en 500-feil på HTTP-forespørsler. For å sikre at beholderen startes på nytt når en slik feil mottas, bruker vi livenessProbe-parameteren:

apiVersion: v1
kind: Pod
metadata:
 name: node500
spec:
 containers:
   - image: magalix/node500
     name: node500
     ports:
       - containerPort: 3000
         protocol: TCP
     livenessProbe:
       httpGet:
         path: /
         port: 3000
       initialDelaySeconds: 5

Dette er ikke forskjellig fra noen annen pod-definisjon, men vi legger til et objekt .spec.containers.livenessProbe. Parameter httpGet godtar banen som HTTP GET-forespørselen sendes til (i vårt eksempel er dette /, men i kampscenarier kan det være noe sånt /api/v1/status). En annen livenessProbe godtar en parameter initialDelaySeconds, som instruerer verifiseringsoperasjonen til å vente et spesifisert antall sekunder. Forsinkelsen er nødvendig fordi beholderen trenger tid for å starte, og når den startes på nytt vil den være utilgjengelig i en stund.

For å bruke denne innstillingen på en klynge, bruk:

kubectl apply -f pod.yaml

Etter noen sekunder kan du sjekke innholdet i poden ved å bruke følgende kommando:

kubectl describe pods node500

På slutten av utgangen, finn det er hva.

Som du kan se, initierte livenessProbe en HTTP GET-forespørsel, containeren genererte en feil 500 (som er det den ble programmert til å gjøre), og kubelet startet den på nytt.

Hvis du lurer på hvordan NideJS-applikasjonen ble programmert, her er app.js og Dockerfile som ble brukt:

app.js

var http = require('http');

var server = http.createServer(function(req, res) {
    res.writeHead(500, { "Content-type": "text/plain" });
    res.end("We have run into an errorn");
});

server.listen(3000, function() {
    console.log('Server is running at 3000')
})

Dockerfile

FROM node
COPY app.js /
EXPOSE 3000
ENTRYPOINT [ "node","/app.js" ]

Det er viktig å merke seg dette: livenessProbe vil bare starte beholderen på nytt hvis den mislykkes. Hvis en omstart ikke retter feilen som hindrer beholderen i å kjøre, vil ikke kubelet kunne iverksette tiltak for å rette opp problemet.

beredskapProbe

readinessProbe fungerer på samme måte som livenessProbes (GET-forespørsler, TCP-kommunikasjon og kommandoutførelse), bortsett fra feilsøkingshandlinger. Beholderen der feilen oppdages, startes ikke på nytt, men er isolert fra innkommende trafikk. Tenk deg at en av containerne utfører mange beregninger eller er under stor belastning, noe som fører til at responstidene øker. Ved livenessProbe utløses responstilgjengelighetskontrollen (via timeoutSeconds check-parameteren), hvoretter kubelet starter beholderen på nytt. Når den startes, begynner beholderen å utføre ressurskrevende oppgaver og startes på nytt. Dette kan være kritisk for applikasjoner som trenger responshastighet. For eksempel venter en bil mens den er på veien på svar fra serveren, responsen er forsinket - og bilen havner i en ulykke.

La oss skrive en redinessProbe-definisjon som vil sette GET-forespørselens responstid til ikke mer enn to sekunder, og applikasjonen vil svare på GET-forespørselen etter 5 sekunder. Pod.yaml-filen skal se slik ut:

apiVersion: v1
kind: Pod
metadata:
 name: nodedelayed
spec:
 containers:
   - image: afakharany/node_delayed
     name: nodedelayed
     ports:
       - containerPort: 3000
         protocol: TCP
     readinessProbe:
       httpGet:
         path: /
         port: 3000
       timeoutSeconds: 2

La oss distribuere en pod med kubectl:

kubectl apply -f pod.yaml

La oss vente et par sekunder og så se hvordan beredskapsproben fungerte:

kubectl describe pods nodedelayed

På slutten av utgangen kan du se at noen av hendelsene er like denne.

Som du kan se, startet ikke kubectl poden på nytt når kontrolltiden oversteg 2 sekunder. I stedet kansellerte han forespørselen. Innkommende kommunikasjon blir omdirigert til andre fungerende pods.

Merk at nå som poden er avlastet, ruter kubectl forespørsler til den igjen: svar på GET-forespørsler er ikke lenger forsinket.

Til sammenligning er den modifiserte app.js-filen nedenfor:

var http = require('http');

var server = http.createServer(function(req, res) {
   const sleep = (milliseconds) => {
       return new Promise(resolve => setTimeout(resolve, milliseconds))
   }
   sleep(5000).then(() => {
       res.writeHead(200, { "Content-type": "text/plain" });
       res.end("Hellon");
   })
});

server.listen(3000, function() {
   console.log('Server is running at 3000')
})

TL; DR
Før bruken av skyapplikasjoner var logger det primære middelet for å overvåke og sjekke applikasjonshelse. Det var imidlertid ingen midler til å iverksette korrigerende tiltak. Logger er fortsatt nyttige i dag, de må samles inn og sendes til et logginnsamlingssystem for å analysere nødsituasjoner og ta beslutninger. [Alt dette kunne gjøres uten skyapplikasjoner ved å bruke monit, for eksempel, men med k8s ble det mye enklere :) – red.anm. ]

I dag må korrigeringer gjøres nesten i sanntid, så søknader trenger ikke lenger være svarte bokser. Nei, de bør vise endepunkter som lar overvåkingssystemer forespørre og samle inn verdifulle data om tilstanden til prosesser, slik at de kan svare umiddelbart om nødvendig. Dette kalles Performance Test Design Pattern, som følger High Observability Principle (HOP).

Kubernetes tilbyr 2 typer helsesjekker som standard: readinessProbe og livenessProbe. Begge bruker samme typer kontroller (HTTP GET-forespørsler, TCP-kommunikasjon og kommandoutførelse). De er forskjellige i hvilke avgjørelser de tar som svar på problemer i podene. livenessProbe starter beholderen på nytt i håp om at feilen ikke skal skje igjen, og readinessProbe isolerer poden fra innkommende trafikk til årsaken til problemet er løst.

Riktig applikasjonsdesign bør inkludere begge typer kontroller og sikre at de samler inn nok data, spesielt når et unntak blir kastet. Den skal også vise de nødvendige API-endepunktene som gir overvåkingssystemet (Prometheus) viktige helsemålinger.

Kilde: www.habr.com

Legg til en kommentar