
TL;DR
- Për të arritur një vëzhgim të lartë të kontejnerëve dhe mikroservicëve, janë të pamjaftueshme vetëm regjistrimet dhe metrikat fillestare.
- Për një rikuperim më të shpejtë dhe për të rritur qëndrueshmërinë, aplikacionet duhet të ndjekin parimin e vëzhgueshmërisë së lartë (HOP, High Observability Principle).
- Në nivelin e aplikacionit, për HOP kërkohet: regjistrim i duhur, monitorim të kujdesshëm, kontrolle të funksionimit dhe gjurmim të performancës/kalimeve.
- Si një element të HOP, përdorni kontrollet readinessProbe dhe livenessProbe Kubernetes.
Çfarë është model kontrolle funksionimi?
Kur ndisni një aplikacion kritik dhe me disponueshmëri të lartë, është shumë e rëndësishme të mendoni për një aspekt si qëndrueshmëria. Një aplikacion quhet i qëndrueshëm nëse kthehet shpejt pas një dështimi. Një aplikacion tipik në re përdor arkitekturën e mikroshërbimeve – ku çdo komponent është vendosur në një kontejner të veçantë. Për të siguruar që aplikacioni në k8s është me disponueshmëri të lartë, kur projektoni një klaster, duhet të ndiqni disa modele. Njëra prej tyre është Modeli i Monitorimit të Shëndetit. Ai përcakton se si aplikacioni i komunikon k8s-statusin e tij. Kjo nuk është vetëm informatë nëse pod-i po funksionon, por gjithashtu se si ai pranon kërkesa dhe u përgjigjet atyre. Sa më shumë që Kubernetes di për funksionalitetin e pod-it, aq më të zgjuara vendime merr për rrugëtimin e trafikut dhe balancimin e ngarkesës. Në këtë mënyrë, Parimi i Vëzhgueshmërisë së Lartë e ndihmon aplikacionin të përgjigjet në kohë për kërkesat.
Parimi i Vëzhgueshmërisë së Lartë (PËL)
Parimi i Vëzhgueshmërisë së Lartë është një nga . Në arkitekturën mikroservisore, shërbimet nuk i japin rëndësi si përpunohen kërkesat e tyre (dhe kjo është e drejtë), por është e rëndësishme sesi të marrin përgjigje nga shërbimet pranuese. Për shembull, për autentikimin e përdoruesit, një kontejner i dërgon një kërkesë HTTP një tjetri, duke pritur një përgjigje në një format të caktuar – kjo është gjithçka. Kërkesën mund ta trajtojë PythonJS, ndërsa mund ta përgjigjet Python Flask. Kontejnerët janë për njëri-tjetrin si kuti të zeza me përmbajtje të fshehur. Megjithatë, parimi NOR kërkon që çdo shërbim të zbulojë disa pikë fundore API, duke treguar sa funksional është ai, si dhe gjendjen e gatishmërisë dhe qëndrueshmërisë së tij. Këto tregues atëherë i kërkon Kubernetes për të menduar hapat e ardhshëm për rrugëzim dhe balancimin e ngarkesës.
Një aplikacion i dizajnuar mirë në re regjistron ngjarjet e tij kryesore duke përdorur rrjedhat standarde të input-output STDERR dhe STDOUT. Më pas funksionon një shërbim ndihmës, si p.sh. filebeat, logstash ose fluentd, i cili dërgon regjistrim në një sistem të centralizuar monitorimi (p.sh. Prometheus) dhe një sistem grumbullimi regjistrimesh (grupi i softuerit ELK). Në skemën më poshtë tregohet si funksionon një aplikacion në re në përputhje me Shablonin e Kontrollit të Disponueshmërisë dhe Parimin e Observueshmërisë së Lartë.

Si të aplikoni Shablonin e Kontrollit të Disponueshmërisë në Kubernetes?
Nga starti, k8s monitoron gjendjen e pod’ave me ndihmën e një prej kontrolleve (, , , dhe të tjera). Kur zbulon se pod ka rënë për ndonjë arsye, kontrolluesi përpiqet ta rinisë atë ose ta transferojë në një nod tjetër. Megjithatë, pod mund të raportojë se është aktiv dhe punon, ndërkohë që nuk funksionon. Të japim një shembull: aplikacioni juaj përdor Apache si server web, keni instaluar komponentin në disa pod të grupit. Pasi biblioteka është konfiguruar në mënyrë të gabuar – të gjitha kërkesat për aplikacionin kthejnë kodin 500 (gabim i brendshëm i serverit). Kur kontrollohet dorëzimi, verifikimi i gjendjes së pod-ve tregon rezultat të suksesshëm, megjithatë klientët mendojnë ndryshe. Këtë situatë të padëshirueshme do ta përshkruajmë si më poshtë:

Në shembullin tonë, k8s kryen kontrollin e funksionit. Në këtë lloj verifikimi, kubelet vazhdimisht kontrollon gjendjen e procesit në enë. Nese ai kupton se procesi ka ngecur, atëherë ai e restarton. Nëse gabimi zgjidhet me një rilançim të thjeshtë të aplikacionit, dhe programi është projektuar që të ndalojë për çdo gabim, atëherë për të ndjekur NORMAT dhe Shabllonin e Verifikimit të Funksionit, mjafton verifikimi i funksionit të procesit. E keqe është se jo të gjitha gabimet zgjidhen me rilançim. Në këtë rast, k8s ofron 2 metoda më të thella për identifikimin e problemeve në punën e pod-it: dhe .
LivenessProbe
Gjatë livenessProbe kubelet kryen 3 lloje kontrollesh: jo vetëm që përcakton nëse pod-i punon, por gjithashtu nëse ai është i gatshëm të pranojë dhe të përgjigjet adekuat ndaj kërkesave:
- Vendosni një kërkesë HTTP në pod. Përgjigjja duhet të përmbajë një kod përgjigjeje HTTP në intervalin nga 200 deri në 399. Kështu, kodet 5xx dhe 4xx sinjalizojnë se pod-i ka probleme, edhe pse procesi punon.
- Për të verifikuar pod-et me shërbime jo-HTTP (për shembull, serveri i postës Postfix), duhet vendosur një lidhje TCP.
- Ekzekutimi i një komande arbitrare për pod-in (brenda). Kontrolli është i suksesshëm nëse kodi i përfundimit të komandës është 0.
Shembuj se si funksionon. Përcaktimi i pod-it të ardhshëm përmban një aplikacion NodeJS, i cili kthen një gabim 500 në kërkesat HTTP. Për t'u siguruar që kontejneri rindezët pas një gabimi të tillë, 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: 5Kjo nuk ndryshon asgjë nga çdo përcaktim tjetër i pod-it, por ne shtojmë objektin .spec.containers.livenessProbe. Parametri httpGet pranon rrugën në të cilën dërgon një kërkesë HTTP GET (në shembullin tonë kjo është /, por në skenarë të vërtetë mund të jetë diçka si /api/v1/status). Gjithashtu, livenessProbe pranon parametrin initialDelaySeconds, i cili i thotë operacioneve të kontrollit të presin një numër të caktuar sekondash. Kjo vonesë është e nevojshme, sepse kontejneri ka nevojë për kohë për të u nisur, dhe gjatë rindezjes ai do të jetë për një periudhë të caktuar jashtë funksionit.
Për të aplikuar këtë konfigurim në klaster, përdorni:
kubectl apply -f pod.yamlPas disa sekondash, mund të kontrolloni përmbajtjen e pod-it me komandën e mëposhtme:
kubectl describe pods node500Në fund të daljes, kërkoni .
Si e shihni, livenessProbe iniciu një kërkesë HTTP GET, konteineri ktheu një gabim 500 (siç ishte programuar), kubelet e ri-nisi atë.
Nëse jeni të interesuar se si është programuar aplikacioni NodeJS, këtu janë skedari app.js dhe Dockerfile që u përdorën:
app.js
var http = require('http');
var server = http.createServer(function(req, res) {
res.writeHead(500, { "Content-type": "text/plain" });
res.end("Na është ndodhur një gabimn");
});
server.listen(3000, function() {
console.log('Serveri po funksionon në 3000')
})Dockerfile
FROM node
COPY app.js /
EXPOSE 3000
ENTRYPOINT [ "node","/app.js" ]Është e rëndësishme të jepni vëmendje kësaj: livenessProbe do të ri-nisi konteinerin vetëm në rast dështimi. Nëse rinisja nuk korrigjon gabimin që pengon funksionimin e konteinerit, kubelet nuk do të ketë mundësi të ndërmarrë masa për të zgjidhur defektin.
readinessProbe
readinessProbe funksionon në mënyrë të ngjashme me livenessProbes (kërkesat GET, TCP lidhjet dhe ekzekutimi i komandave), me përjashtim të veprimeve për shërimin e defekteve. Kontejneri në të cilin është regjistruar një dështim nuk rindez, por izolohet nga trafiku hyrës. Imagjinoni, një nga kontejnerët po kryen shumë llogaritje ose përballohet me ngarkesë të madhe, çka rrit kohën e përgjigjes për kërkesat. Në rastin e livenessProbe, bëhet një kontroll i disponueshmërisë së përgjigjes (nëpërmjet parametrave të kontrollit timeoutSeconds), pas së cilës kubelet rindez kontejnerin. Kur kontejneri nis, ai fillon të kryejë detyra që kërkojnë burime dhe rindezet përsëri. Kjo mund të jetë kritike për aplikacionet ku koha e përgjigjes është e rëndësishme. Për shembull, një makinë është duke udhëtuar dhe pret përgjigjën nga serveri, përgjigja vonohet – dhe makina përfundon në aksident.
Le të shkruajmë një definicion për redinessProbe, i cili do të vendosë kohën e përgjigjes për kërkesën GET të mos jetë më shumë se dy sekonda, ndërsa aplikacioni do të përgjigjet në kërkesën GET pas 5 sekondash. Skedari pod.yaml duhet të duket si më poshtë:
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: 2Do të zhvillojmë pod me kubectl:
kubectl apply -f pod.yamlDo të presim disa sekonda, pastaj do të shohim se si ka funksionuar readinessProbe:
kubectl describe pods nodedelayedNë fund të daljes, mund të shihni se një pjesë e ngjarjeve është e ngjashme me .
Siç e shihni, kubectl nuk e rindezi pod-in kur koha e kontrollit tejkaloi 2 sekonda. Në vend të kësaj, ai e anuloi kërkesën. Lidhjet e ardhshme janë ridrejtuar në pod-in tjetër, aktiv.
Vini re: tani, kur pod-in nuk ka ngarkesë të tepërt, kubectl përsëri i drejton kërkesat atij: përgjigjet ndaj kërkesave GET nuk pësojnë më vonesa.
Për krahasim: këtu është një skedar i ndryshuar 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('Serveri po punon në 3000')
})TL;DR
Para paraqitjes së aplikacioneve cloud, mjet kryesor për monitorimin dhe verifikimin e gjendjes së aplikacioneve ishin logjet. Megjithatë, nuk kishte mjete për të ndërmarrë ndonjë hap për të eliminuar problemet. Logjet, dhe sot janë të dobishme, duhet të mblidhen dhe dërgohen në sistemin e mbledhjes së logjeve për analizimin e situatave emergjente dhe marrjen e vendimeve. [kjo gjithashtu mund të bëhej edhe pa aplikacione cloud duke përdorur monit, për shembull, por me k8s kjo u bë shumë më e lehtë 🙂 – shënim redaktori. ]
Sot, korrigjimet duhet të bëhen thuajse në kohë reale, kështu që aplikacionet nuk duhet të jenë më kutia të errëta. Jo, ato duhet të tregojnë pikët e fundit, duke lejuar sistemet e monitorimit të kërkojnë dhe mbledhin të dhëna të vlefshme mbi gjendjen e proceseve, në mënyrë që në rast nevoje të reagojnë menjëherë. Kjo quhet Shkalla projektimi e kontrollit të funksionimit, e cila ndjek Parimin e Observueshmërisë të Lartë (OHA).
Kubernetes ofron dy lloje kontrolesh për funksionimin: readinessProbe dhe livenessProbe. Të dyja përdorin lloje të njëjta kontrolesh (kërkesat HTTP GET, lidhjet TCP dhe ekzekutimi i komandave). Ato dallohet në vendimet që marrin si përgjigje ndaj problemeve në pod. livenessProbe rinehë container-in me shpresën se gabimi nuk do të përsëritet, ndërsa readinessProbe izolon pod-in nga trafik i ardhshëm – derisa të eliminohet shkaku i problemit.
Projektimi i duhur i aplikacioneve duhet të përfshijë të dy llojet e kontrolit, dhe që ato të mbledhin mjaft të dhëna, veçanërisht kur krijohet një situatë emergjente. Ai gjithashtu duhet të tregojë endpoint-et e nevojshme API që i dërgojnë sistemit të monitorimit (si Prometheus) metricat e rëndësishme për gjendjen e funksionimit.
Burimi: habr.com
