Bedste praksis for Kubernetes-beholdere: Sundhedstjek

Bedste praksis for Kubernetes-beholdere: Sundhedstjek

TL; DR

  • For at opnå høj observerbarhed af containere og mikrotjenester er logfiler og primære metrikker ikke nok.
  • For hurtigere genopretning og øget modstandsdygtighed bør applikationer anvende High Observability Principle (HOP).
  • På applikationsniveau kræver NOP: korrekt logning, tæt overvågning, sundhedstjek og præstations-/overgangssporing.
  • Brug checks som et element i NOR parathed Probe и livlighed Sonde Kubernetes.

Hvad er en Health Check-skabelon?

Når man designer en missionskritisk og yderst tilgængelig applikation, er det meget vigtigt at tænke på et sådant aspekt som fejltolerance. En applikation betragtes som fejltolerant, hvis den kommer sig hurtigt efter fejl. En typisk cloud-applikation bruger en microservices-arkitektur - hvor hver komponent er placeret i en separat container. Og for at sikre, at applikationen på k8s er yderst tilgængelig, når du designer en klynge, skal du følge visse mønstre. Blandt dem er Health Check-skabelonen. Den definerer, hvordan applikationen kommunikerer til k8s, at den er sund. Dette er ikke kun information om, hvorvidt poden kører, men også om, hvordan den modtager og reagerer på anmodninger. Jo mere Kubernetes ved om pod'ens sundhed, jo smartere beslutninger træffer den om trafikdirigering og belastningsbalancering. Således giver High Observability Princippet applikationen mulighed for at reagere på anmodninger rettidigt.

High Observability Principle (HOP)

Princippet om høj observerbarhed er et af principper for design af containeriserede applikationer. I en mikroservicearkitektur er tjenester ligeglade med, hvordan deres anmodning behandles (og med rette), men det, der betyder noget, er, hvordan de modtager svar fra de modtagende tjenester. For at autentificere en bruger sender en container for eksempel en HTTP-anmodning til en anden og forventer et svar i et bestemt format - det er alt. PythonJS kan også behandle anmodningen, og Python Flask kan svare. Containere er som sorte kasser med skjult indhold for hinanden. NOP-princippet kræver dog, at hver tjeneste afslører flere API-endepunkter, der angiver, hvor sund den er, såvel som dens parathed og fejltolerancestatus. Kubernetes anmoder om disse indikatorer for at gennemtænke de næste trin for routing og belastningsbalancering.

En veldesignet cloud-applikation logger sine vigtigste begivenheder ved hjælp af standard I/O-streams STDERR og STDOUT. Dernæst kommer en hjælpetjeneste, for eksempel filebeat, logstash eller fluentd, der leverer logfiler til et centraliseret overvågningssystem (for eksempel Prometheus) og et logopsamlingssystem (ELK-softwaresuite). Diagrammet nedenfor viser, hvordan en cloud-applikation fungerer i henhold til Health Test Pattern og High Observability Principle.

Bedste praksis for Kubernetes-beholdere: Sundhedstjek

Hvordan anvender man sundhedstjekmønsteret i Kubernetes?

Ud af æsken overvåger k8s podsens status ved hjælp af en af ​​controllerne (implementeringer, Replikasæt, Dæmonsæt, StatefulSets osv., osv.). Efter at have opdaget, at poden er faldet af en eller anden grund, forsøger controlleren at genstarte den eller flytte den til en anden node. En pod kan dog rapportere, at den er oppe at køre, men at den i sig selv ikke fungerer. Lad os give et eksempel: din applikation bruger Apache som en webserver, du installerede komponenten på flere cluster pods. Da biblioteket var konfigureret forkert, svarer alle anmodninger til applikationen med kode 500 (intern serverfejl). Ved kontrol af levering giver kontrol af pods status et vellykket resultat, men kunderne tænker anderledes. Vi vil beskrive denne uønskede situation som følger:

Bedste praksis for Kubernetes-beholdere: Sundhedstjek

I vores eksempel gør k8s funktionstjek. Ved denne type verifikation kontrollerer kubelet løbende processens tilstand i containeren. Når han forstår, at processen er stoppet, vil han genstarte den. Hvis fejlen kan løses ved blot at genstarte applikationen, og programmet er designet til at lukke ned ved enhver fejl, så er et processundhedstjek alt hvad du behøver for at følge NOP og Health Test Pattern. Den eneste skam er, at ikke alle fejl elimineres ved genstart. I dette tilfælde tilbyder k8s 2 dybere måder at identificere problemer med poden på: livlighed Sonde и parathed Probe.

LivenessProbe

Under livlighed Sonde kubelet udfører 3 typer kontroller: ikke kun bestemmer, om poden kører, men også om den er klar til at modtage og reagere tilstrækkeligt på anmodninger:

  • Konfigurer en HTTP-anmodning til poden. Svaret skal indeholde en HTTP-svarkode i området fra 200 til 399. Koderne 5xx og 4xx signalerer således, at poden har problemer, selvom processen kører.
  • For at teste pods med ikke-HTTP-tjenester (f.eks. Postfix-mailserveren), skal du oprette en TCP-forbindelse.
  • Udfør en vilkårlig kommando for en pod (internt). Kontrollen anses for at være vellykket, hvis kommandoudførelseskoden er 0.

Et eksempel på, hvordan dette fungerer. Den næste pod-definition indeholder en NodeJS-applikation, der kaster en 500-fejl på HTTP-anmodninger. For at sikre, at containeren genstartes, når der modtages en sådan fejl, bruger vi parameteren livenessProbe:

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 adskiller sig ikke fra enhver anden pod-definition, men vi tilføjer et objekt .spec.containers.livenessProbe. Parameter httpGet accepterer stien, som HTTP GET-anmodningen sendes til (i vores eksempel er dette /, men i kampscenarier kan der være noget lignende /api/v1/status). En anden livenessProbe accepterer en parameter initialDelaySeconds, som instruerer verifikationsoperationen til at vente et angivet antal sekunder. Forsinkelsen er nødvendig, fordi containeren har brug for tid til at starte, og når den genstartes, vil den være utilgængelig i nogen tid.

For at anvende denne indstilling på en klynge skal du bruge:

kubectl apply -f pod.yaml

Efter et par sekunder kan du kontrollere indholdet af poden ved hjælp af følgende kommando:

kubectl describe pods node500

Find i slutningen af ​​outputtet det er hvad.

Som du kan se, startede livenessProbe en HTTP GET-anmodning, containeren genererede en fejl 500 (hvilket er, hvad den var programmeret til at gøre), og kubelet genstartede den.

Hvis du undrer dig over, hvordan NideJS-applikationen blev programmeret, er her app.js og Dockerfile, der blev brugt:

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')
})

Dockerfil

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

Det er vigtigt at bemærke dette: livenessProbe genstarter kun containeren, hvis den fejler. Hvis en genstart ikke retter den fejl, der forhindrer beholderen i at køre, vil kubelet ikke være i stand til at foretage sig noget for at rette problemet.

parathed Probe

readinessProbe fungerer på samme måde som livenessProbes (GET-anmodninger, TCP-kommunikation og kommandoudførelse), bortset fra fejlfindingshandlinger. Containeren, hvori fejlen er registreret, genstartes ikke, men er isoleret fra indgående trafik. Forestil dig, at en af ​​containerne udfører mange beregninger eller er under stor belastning, hvilket får responstiden til at øges. I tilfælde af livenessProbe udløses responstilgængelighedskontrollen (via timeoutSeconds check-parameteren), hvorefter kubelet genstarter containeren. Når den startes, begynder containeren at udføre ressourcekrævende opgaver og genstartes igen. Dette kan være kritisk for applikationer, der har brug for responshastighed. For eksempel venter en bil på vejen på svar fra serveren, responsen er forsinket - og bilen kommer ud for en ulykke.

Lad os skrive en redinessProbe-definition, der vil indstille GET-anmodningssvartiden til ikke mere end to sekunder, og applikationen vil svare på GET-anmodningen efter 5 sekunder. Filen pod.yaml skulle se sådan ud:

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

Lad os implementere en pod med kubectl:

kubectl apply -f pod.yaml

Lad os vente et par sekunder og så se, hvordan parathedsproben fungerede:

kubectl describe pods nodedelayed

I slutningen af ​​outputtet kan du se, at nogle af begivenhederne ligner hinanden denne.

Som du kan se, genstartede kubectl ikke poden, da kontroltiden oversteg 2 sekunder. I stedet annullerede han anmodningen. Indgående kommunikation omdirigeres til andre fungerende pods.

Bemærk, at nu hvor poden er afloadet, dirigerer kubectl anmodninger til den igen: svar på GET-anmodninger er ikke længere forsinket.

Til sammenligning er nedenfor den ændrede app.js-fil:

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 fremkomsten af ​​cloud-applikationer var logfiler det primære middel til at overvåge og kontrollere applikationstilstand. Der var dog ingen midler til at træffe korrigerende foranstaltninger. Logs er stadig nyttige i dag; de skal indsamles og sendes til et logindsamlingssystem for at analysere nødsituationer og træffe beslutninger. [Alt dette kunne gøres uden cloud-applikationer ved hjælp af for eksempel monit, men med k8s blev det meget nemmere :) – red. bemærkning. ]

I dag skal rettelser foretages næsten i realtid, så ansøgninger ikke længere skal være sorte bokse. Nej, de bør vise endepunkter, der gør det muligt for overvågningssystemer at forespørge og indsamle værdifulde data om processernes tilstand, så de kan reagere øjeblikkeligt, hvis det er nødvendigt. Dette kaldes Performance Test Design Pattern, som følger High Observability Principle (HOP).

Kubernetes tilbyder som standard 2 typer sundhedstjek: ReadinessProbe og livenessProbe. Begge bruger de samme typer kontroller (HTTP GET-anmodninger, TCP-kommunikation og kommandoudførelse). De er forskellige i, hvilke beslutninger de træffer som reaktion på problemer i bælgerne. livenessProbe genstarter containeren i håb om, at fejlen ikke vil ske igen, og readinessProbe isolerer poden fra indgående trafik, indtil årsagen til problemet er løst.

Korrekt applikationsdesign bør omfatte begge typer kontrol og sikre, at de indsamler nok data, især når der er smidt en undtagelse. Det bør også vise de nødvendige API-endepunkter, der forsyner overvågningssystemet (Prometheus) med vigtige sundhedsmålinger.

Kilde: www.habr.com

Tilføj en kommentar