Praktikat më të mira për kontejnerët Kubernetes: Kontrollet shëndetësore

Praktikat më të mira për kontejnerët Kubernetes: Kontrollet shëndetësore

TL; DR

  • Për të arritur vëzhgueshmëri të lartë të kontejnerëve dhe mikroshërbimeve, shkrimet dhe metrikat kryesore nuk janë të mjaftueshme.
  • Për rikuperim më të shpejtë dhe rritje të elasticitetit, aplikacionet duhet të zbatojnë Parimin e Vëzhgueshmërisë së Lartë (HOP).
  • Në nivelin e aplikimit, NOP kërkon: regjistrimin e duhur, monitorim të ngushtë, kontrolle të arsyeshme dhe gjurmim të performancës/tranzicionit.
  • Përdorni çeqet si një element të NOR gatishmëriProbe и Sonda e gjallërisë Kubernetes.

Çfarë është një shabllon i kontrollit shëndetësor?

Kur hartoni një aplikacion kritik dhe shumë të disponueshëm për misionin, është shumë e rëndësishme të mendoni për një aspekt të tillë si toleranca ndaj gabimeve. Një aplikacion konsiderohet tolerant ndaj gabimeve nëse rikuperohet shpejt nga dështimi. Një aplikacion tipik cloud përdor një arkitekturë mikroshërbimesh - ku secili komponent vendoset në një enë të veçantë. Dhe për t'u siguruar që aplikacioni në k8s është shumë i disponueshëm kur hartoni një grup, duhet të ndiqni modele të caktuara. Midis tyre është modeli i kontrollit shëndetësor. Ai përcakton se si aplikacioni i komunikon k8s se është i shëndetshëm. Ky nuk është vetëm informacion nëse pod po funksionon, por edhe për mënyrën se si ai merr dhe u përgjigjet kërkesave. Sa më shumë të dijë Kubernetes për shëndetin e podit, aq më të zgjuara merr vendime për drejtimin e trafikut dhe balancimin e ngarkesës. Kështu, Parimi i Vëzhgueshmërisë së Lartë i lejon aplikacionit t'u përgjigjet kërkesave në kohën e duhur.

Parimi i Vëzhgueshmërisë së Lartë (HOP)

Parimi i vëzhgueshmërisë së lartë është një nga parimet për projektimin e aplikacioneve të kontejnerizuara. Në një arkitekturë të mikroshërbimeve, shërbimeve nuk u intereson se si përpunohet kërkesa e tyre (dhe me të drejtë), por ajo që ka rëndësi është se si marrin përgjigjet nga shërbimet marrëse. Për shembull, për të vërtetuar një përdorues, një kontejner i dërgon një kërkesë HTTP një tjetri, duke pritur një përgjigje në një format të caktuar - kjo është e gjitha. PythonJS gjithashtu mund të përpunojë kërkesën dhe Python Flask mund të përgjigjet. Kontejnerët janë si kuti të zeza me përmbajtje të fshehura me njëri-tjetrin. Megjithatë, parimi NOP kërkon që çdo shërbim të ekspozojë disa pika fundore të API që tregojnë se sa i shëndetshëm është, si dhe gatishmërinë dhe statusin e tij të tolerancës ndaj gabimeve. Kubernetes kërkon këta tregues në mënyrë që të mendojë për hapat e ardhshëm për drejtimin dhe balancimin e ngarkesës.

Një aplikacion cloud i projektuar mirë regjistron ngjarjet e tij kryesore duke përdorur transmetimet standarde I/O STDERR dhe STDOUT. Më pas vjen një shërbim ndihmës, për shembull filebeat, logstash ose fluentd, duke ofruar regjistra në një sistem monitorimi të centralizuar (për shembull Prometheus) dhe një sistem të mbledhjes së regjistrave (komutë softuerësh ELK). Diagrami më poshtë tregon se si funksionon një aplikacion cloud sipas Modelit të Testit Shëndetësor dhe Parimit të Vëzhgueshmërisë së Lartë.

Praktikat më të mira për kontejnerët Kubernetes: Kontrollet shëndetësore

Si të aplikoni modelin e kontrollit shëndetësor në Kubernetes?

Nga kutia, k8s monitoron statusin e pods duke përdorur një nga kontrollorët (vendosjet, ReplicaSets, DaemonSets, StatefulSets etj., etj.). Pasi zbuloi se pod ka rënë për ndonjë arsye, kontrolluesi përpiqet ta rifillojë atë ose ta zhvendosë atë në një nyje tjetër. Sidoqoftë, një pod mund të raportojë se është në funksion dhe funksionon, por ai vetë nuk po funksionon. Le të japim një shembull: aplikacioni juaj përdor Apache si një server në internet, ju keni instaluar komponentin në disa pods të grupit. Meqenëse biblioteka ishte konfiguruar gabimisht, të gjitha kërkesat për aplikacionin përgjigjen me kodin 500 (gabim i brendshëm i serverit). Kur kontrolloni dorëzimin, kontrollimi i statusit të pods jep një rezultat të suksesshëm, por klientët mendojnë ndryshe. Ne do ta përshkruajmë këtë situatë të padëshirueshme si më poshtë:

Praktikat më të mira për kontejnerët Kubernetes: Kontrollet shëndetësore

Në shembullin tonë, k8s bën kontrolli i funksionalitetit. Në këtë lloj verifikimi, kubelet kontrollon vazhdimisht gjendjen e procesit në kontejner. Sapo të kuptojë se procesi ka ndaluar, ai do ta rifillojë atë. Nëse gabimi mund të zgjidhet thjesht duke rifilluar aplikacionin dhe programi është krijuar për të mbyllur çdo gabim, atëherë një kontroll shëndetësor i procesit është gjithçka që ju nevojitet për të ndjekur NOP dhe modelin e testit shëndetësor. E vetmja keqardhje është se jo të gjitha gabimet eliminohen duke rifilluar. Në këtë rast, k8s ofron 2 mënyra më të thella për të identifikuar problemet me podin: Sonda e gjallërisë и gatishmëriProbe.

LivenessProbe

gjatë Sonda e gjallërisë kubelet kryen 3 lloje kontrollesh: jo vetëm që përcakton nëse pod po funksionon, por edhe nëse është gati për të marrë dhe për t'iu përgjigjur në mënyrë adekuate kërkesave:

  • Vendosni një kërkesë HTTP në pod. Përgjigja duhet të përmbajë një kod përgjigjeje HTTP në intervalin nga 200 në 399. Kështu, kodet 5xx dhe 4xx sinjalizojnë se pod ka probleme, edhe pse procesi po funksionon.
  • Për të testuar pods me shërbime jo HTTP (për shembull, serveri i postës Postfix), duhet të krijoni një lidhje TCP.
  • Ekzekutoni një komandë arbitrare për një pod (brenda). Kontrolli konsiderohet i suksesshëm nëse kodi i përfundimit të komandës është 0.

Një shembull se si funksionon kjo. Përkufizimi tjetër i pod përmban një aplikacion NodeJS që hedh një gabim 500 në kërkesat HTTP. Për t'u siguruar që kontejneri të riniset kur merr një gabim të tillë, ne përdorim parametrin 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

Ky nuk është i ndryshëm nga çdo përkufizim tjetër i pod, por ne po shtojmë një objekt .spec.containers.livenessProbe... Parametri httpGet pranon rrugën në të cilën dërgohet kërkesa HTTP GET (në shembullin tonë kjo është /, por në skenarë luftarakë mund të ketë diçka të tillë /api/v1/status). Një tjetër livenessProbe pranon një parametër initialDelaySeconds, i cili udhëzon operacionin e verifikimit të presë një numër të caktuar sekondash. Vonesa është e nevojshme sepse kontejneri ka nevojë për kohë për t'u nisur dhe kur të rindizet ai do të jetë i padisponueshëm për ca kohë.

Për të aplikuar këtë cilësim në një grup, përdorni:

kubectl apply -f pod.yaml

Pas disa sekondash, mund të kontrolloni përmbajtjen e pod duke përdorur komandën e mëposhtme:

kubectl describe pods node500

Në fund të prodhimit, gjeni Ja cfarë.

Siç mund ta shihni, livenessProbe inicioi një kërkesë HTTP GET, kontejneri gjeneroi një gabim 500 (që është ajo që ishte programuar të bënte) dhe kubelet e rifilloi atë.

Nëse po pyesni se si u programua aplikacioni NideJS, këtu janë app.js dhe Dockerfile që janë përdorur:

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" ]

Është e rëndësishme të kihet parasysh kjo: livenessProbe do të rifillojë kontejnerin vetëm nëse dështon. Nëse një rinisje nuk korrigjon gabimin që po pengon funksionimin e kontejnerit, kubelet nuk do të jetë në gjendje të ndërmarrë veprime për të korrigjuar problemin.

gatishmëriProbe

ReadinessProbe punon në mënyrë të ngjashme me livenessProbes (kërkesat GET, komunikimet TCP dhe ekzekutimi i komandave), me përjashtim të veprimeve për zgjidhjen e problemeve. Kontejneri në të cilin zbulohet dështimi nuk riniset, por është i izoluar nga trafiku në hyrje. Imagjinoni që një nga kontejnerët po kryen shumë llogaritje ose është nën ngarkesë të madhe, duke bërë që koha e përgjigjes të rritet. Në rastin e livenessProbe, aktivizohet kontrolli i disponueshmërisë së përgjigjes (përmes parametrit të kontrollit timeoutSeconds), pas së cilës kubelet rinis kontejnerin. Kur niset, kontejneri fillon të kryejë detyra me burime intensive dhe riniset përsëri. Kjo mund të jetë kritike për aplikacionet që kanë nevojë për shpejtësi përgjigjeje. Për shembull, një makinë ndërsa është në rrugë është duke pritur për një përgjigje nga serveri, përgjigja vonohet - dhe makina futet në një aksident.

Le të shkruajmë një përkufizim redinessProbe që do të vendosë kohën e përgjigjes së kërkesës GET në jo më shumë se dy sekonda dhe aplikacioni do t'i përgjigjet kërkesës GET pas 5 sekondash. Skedari pod.yaml duhet të duket kështu:

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

Le të vendosim një pod me kubectl:

kubectl apply -f pod.yaml

Le të presim disa sekonda dhe pastaj të shohim se si funksionoi ReadinessProbe:

kubectl describe pods nodedelayed

Në fund të daljes mund të shihni se disa nga ngjarjet janë të ngjashme këtë.

Siç mund ta shihni, kubectl nuk e rifilloi podin kur koha e kontrollit i kaloi 2 sekonda. Në vend të kësaj, ai e anuloi kërkesën. Komunikimet hyrëse ridrejtohen në pods të tjera funksionale.

Vini re se tani që pod është shkarkuar, kubectl i drejton përsëri kërkesat tek ai: përgjigjet ndaj kërkesave GET nuk vonohen më.

Për krahasim, më poshtë është skedari i modifikuar app.js:

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
Para ardhjes së aplikacioneve cloud, regjistrat ishin mjetet kryesore të monitorimit dhe kontrollit të shëndetit të aplikacionit. Megjithatë, nuk kishte asnjë mjet për të ndërmarrë ndonjë veprim korrigjues. Regjistrat janë ende të dobishëm sot; ato duhet të mblidhen dhe të dërgohen në një sistem të mbledhjes së regjistrave për të analizuar situatat emergjente dhe për të marrë vendime. [E gjithë kjo mund të bëhej pa aplikacione cloud duke përdorur monit, për shembull, por me k8 u bë shumë më e lehtë :) - shënimi i redaktorit. ]

Sot, korrigjimet duhet të bëhen pothuajse në kohë reale, kështu që aplikacionet nuk duhet të jenë më kuti të zeza. Jo, ato duhet të tregojnë pikat përfundimtare që lejojnë sistemet e monitorimit të kërkojnë dhe të mbledhin të dhëna të vlefshme për gjendjen e proceseve në mënyrë që ata të mund të përgjigjen menjëherë nëse është e nevojshme. Ky quhet modeli i dizajnit të testit të performancës, i cili ndjek Parimin e Vëzhgueshmërisë së Lartë (HOP).

Kubernetes ofron 2 lloje kontrollesh shëndetësore si parazgjedhje: ReadinessProbe dhe LivenessProbe. Të dy përdorin të njëjtat lloje kontrollesh (kërkesat HTTP GET, komunikimet TCP dhe ekzekutimi i komandave). Ato ndryshojnë në vendimet që marrin në përgjigje të problemeve në bishtaja. livenessProbe rinis kontejnerin me shpresën se gabimi nuk do të ndodhë më dhe ReadinessProbe izolon podin nga trafiku në hyrje derisa të zgjidhet shkaku i problemit.

Dizajni i duhur i aplikacionit duhet të përfshijë të dy llojet e kontrollit dhe të sigurojë që ato të mbledhin të dhëna të mjaftueshme, veçanërisht kur bëhet një përjashtim. Ai gjithashtu duhet të tregojë pikat fundore të nevojshme të API-së që i ofrojnë sistemit të monitorimit (Prometheus) metrika të rëndësishme shëndetësore.

Burimi: www.habr.com

Shto një koment