Pinakamahuhusay na Kasanayan para sa Mga Container ng Kubernetes: Mga Pagsusuri sa Kalusugan

Pinakamahuhusay na Kasanayan para sa Mga Container ng Kubernetes: Mga Pagsusuri sa Kalusugan

Tl; DR

  • Para makamit ang mataas na observability ng mga container at microservice, hindi sapat ang mga log at pangunahing sukatan.
  • Para sa mas mabilis na pagbawi at mas mataas na katatagan, dapat ilapat ng mga aplikasyon ang High Observability Principle (HOP).
  • Sa antas ng aplikasyon, ang NOP ay nangangailangan ng: wastong pag-log, malapit na pagsubaybay, mga pagsusuri sa katinuan, at pagsubaybay sa pagganap/transisyon.
  • Gumamit ng mga tseke bilang elemento ng NOR kahandaanProbe ΠΈ livenessProbe Kubernetes.

Ano ang Template ng Health Check?

Kapag nagdidisenyo ng isang mission-critical at highly available na application, napakahalagang isipin ang tungkol sa aspetong tulad ng fault tolerance. Ang isang aplikasyon ay itinuturing na fault tolerant kung ito ay mabilis na nakabawi mula sa pagkabigo. Ang isang karaniwang cloud application ay gumagamit ng isang microservice architecture - kung saan ang bawat bahagi ay inilalagay sa isang hiwalay na lalagyan. At upang matiyak na ang application sa k8s ay lubos na magagamit kapag nagdisenyo ka ng isang cluster, kailangan mong sundin ang ilang mga pattern. Kabilang sa mga ito ay ang Health Check Template. Tinutukoy nito kung paano nakikipag-ugnayan ang application sa mga k8 na ito ay malusog. Ito ay hindi lamang impormasyon tungkol sa kung tumatakbo ang pod, kundi pati na rin kung paano ito tumatanggap at tumutugon sa mga kahilingan. Kung mas maraming Kubernetes ang nakakaalam tungkol sa kalusugan ng pod, mas matalinong mga desisyon na ginagawa nito tungkol sa pagruruta ng trapiko at pagbalanse ng load. Kaya, pinapayagan ng High Observability Principle ang application na tumugon sa mga kahilingan sa isang napapanahong paraan.

High Observability Principle (HOP)

Ang prinsipyo ng mataas na pagmamasid ay isa sa mga prinsipyo para sa pagdidisenyo ng mga containerized na aplikasyon. Sa isang arkitektura ng microservices, walang pakialam ang mga serbisyo kung paano pinoproseso ang kanilang kahilingan (at tama lang), ngunit ang mahalaga ay kung paano sila nakakatanggap ng mga tugon mula sa mga serbisyong tumatanggap. Halimbawa, para ma-authenticate ang isang user, nagpapadala ang isang container ng HTTP na kahilingan sa isa pa, na umaasa sa isang tugon sa isang partikular na format - iyon lang. Maaari ring iproseso ng PythonJS ang kahilingan, at maaaring tumugon ang Python Flask. Ang mga lalagyan ay parang mga itim na kahon na may mga nakatagong nilalaman sa bawat isa. Gayunpaman, ang prinsipyo ng NOP ay nangangailangan ng bawat serbisyo na ilantad ang maramihang mga endpoint ng API na nagsasaad kung gaano ito kalusog, pati na rin ang pagiging handa at fault tolerance nito. Hinihiling ng Kubernetes ang mga indicator na ito upang mapag-isipan ang mga susunod na hakbang para sa pagruruta at pagbalanse ng load.

Ang isang mahusay na idinisenyong cloud application ay nagla-log sa mga pangunahing kaganapan nito gamit ang karaniwang I/O stream na STDERR at STDOUT. Susunod ay isang auxiliary service, halimbawa filebeat, logstash o fluentd, naghahatid ng mga log sa isang sentralisadong sistema ng pagsubaybay (halimbawa Prometheus) at isang sistema ng koleksyon ng log (ELK software suite). Ipinapakita ng diagram sa ibaba kung paano gumagana ang cloud application ayon sa Health Test Pattern at High Observability Principle.

Pinakamahuhusay na Kasanayan para sa Mga Container ng Kubernetes: Mga Pagsusuri sa Kalusugan

Paano ilapat ang Health Check Pattern sa Kubernetes?

Sa labas ng kahon, sinusubaybayan ng k8s ang katayuan ng mga pod gamit ang isa sa mga controllers (Deployments, Mga ReplicaSets, Mga DaemonSets, StatefulSets atbp., atbp.). Nang matuklasan na ang pod ay nahulog sa ilang kadahilanan, sinusubukan ng controller na i-restart ito o ilipat ito sa isa pang node. Gayunpaman, ang isang pod ay maaaring mag-ulat na ito ay gumagana, ngunit ito mismo ay hindi gumagana. Magbigay tayo ng halimbawa: ang iyong application ay gumagamit ng Apache bilang isang web server, na-install mo ang bahagi sa ilang pod ng cluster. Dahil ang library ay na-configure nang hindi tama, ang lahat ng mga kahilingan sa application ay tumutugon sa code 500 (internal server error). Kapag sinusuri ang paghahatid, ang pagsuri sa katayuan ng mga pod ay nagbibigay ng matagumpay na resulta, ngunit iba ang iniisip ng mga customer. Ilalarawan namin ang hindi kanais-nais na sitwasyon tulad ng sumusunod:

Pinakamahuhusay na Kasanayan para sa Mga Container ng Kubernetes: Mga Pagsusuri sa Kalusugan

Sa aming halimbawa, ginagawa ng k8s pagsusuri ng pag-andar. Sa ganitong uri ng pag-verify, patuloy na sinusuri ng kubelet ang estado ng proseso sa container. Kapag naunawaan niya na huminto ang proseso, i-restart niya ito. Kung ang error ay malulutas sa pamamagitan lamang ng pag-restart ng application, at ang program ay idinisenyo upang isara ang anumang error, ang proseso ng pagsusuri sa kalusugan ay ang kailangan mo lang upang sundin ang NOP at ang Health Test Pattern. Ang tanging awa ay hindi lahat ng mga error ay tinanggal sa pamamagitan ng pag-restart. Sa kasong ito, nag-aalok ang k8s ng 2 mas malalim na paraan para matukoy ang mga problema sa pod: livenessProbe ΠΈ kahandaanProbe.

LivenessProbe

Sa panahon ng livenessProbe Ang kubelet ay nagsasagawa ng 3 uri ng mga pagsusuri: hindi lamang tinutukoy kung tumatakbo ang pod, kundi pati na rin kung handa na itong tumanggap at sapat na tumugon sa mga kahilingan:

  • Mag-set up ng HTTP na kahilingan sa pod. Ang tugon ay dapat maglaman ng isang HTTP response code sa hanay mula 200 hanggang 399. Kaya, ang mga code na 5xx at 4xx ay nagpapahiwatig na ang pod ay nagkakaroon ng mga problema, kahit na ang proseso ay tumatakbo.
  • Upang subukan ang mga pod na may mga serbisyong hindi HTTP (halimbawa, ang Postfix mail server), kailangan mong magtatag ng koneksyon sa TCP.
  • Magsagawa ng di-makatwirang utos para sa isang pod (sa loob). Ang tseke ay itinuturing na matagumpay kung ang command completion code ay 0.

Isang halimbawa kung paano ito gumagana. Ang susunod na pod definition ay naglalaman ng isang NodeJS application na naglalabas ng 500 error sa mga kahilingan sa HTTP. Upang matiyak na ang container ay na-restart kapag nakatanggap ng ganoong error, ginagamit namin ang livenessProbe na parameter:

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

Hindi ito naiiba sa anumang iba pang kahulugan ng pod, ngunit nagdaragdag kami ng isang bagay .spec.containers.livenessProbe. Parameter httpGet tinatanggap ang landas kung saan ipinapadala ang kahilingan ng HTTP GET (sa aming halimbawa ito ay /, ngunit sa mga senaryo ng labanan ay maaaring may katulad /api/v1/status). Ang isa pang livenessProbe ay tumatanggap ng isang parameter initialDelaySeconds, na nagtuturo sa pagpapatakbo ng pag-verify na maghintay ng tinukoy na bilang ng mga segundo. Kailangan ang pagkaantala dahil ang lalagyan ay nangangailangan ng oras upang magsimula, at kapag na-restart ito ay hindi ito magagamit sa loob ng ilang panahon.

Upang ilapat ang setting na ito sa isang cluster, gamitin ang:

kubectl apply -f pod.yaml

Pagkatapos ng ilang segundo, maaari mong suriin ang mga nilalaman ng pod gamit ang sumusunod na command:

kubectl describe pods node500

Sa dulo ng output, hanapin yan yan.

Tulad ng nakikita mo, pinasimulan ng livenessProbe ang isang kahilingan sa HTTP GET, ang container ay nakabuo ng error 500 (na kung ano ang naka-program na gawin), at ang kubelet ay nag-restart nito.

Kung nagtataka ka kung paano na-program ang NideJS application, narito ang app.js at Dockerfile na ginamit:

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

Mahalagang tandaan ito: Ire-restart lang ng livenessProbe ang container kung nabigo ito. Kung hindi naitama ng pag-restart ang error na pumipigil sa pagtakbo ng container, hindi makakagawa ang kubelet ng aksyon upang itama ang problema.

kahandaanProbe

Ang readinessProbe ay gumagana katulad ng livenessProbes (mga kahilingan sa GET, mga komunikasyon sa TCP at pagpapatupad ng command), maliban sa mga aksyon sa pag-troubleshoot. Ang lalagyan kung saan natukoy ang pagkabigo ay hindi na-restart, ngunit nakahiwalay sa papasok na trapiko. Isipin na ang isa sa mga lalagyan ay gumaganap ng maraming kalkulasyon o nasa ilalim ng mabigat na pagkarga, na nagiging sanhi ng pagtaas ng mga oras ng pagtugon. Sa kaso ng livenessProbe, ang pagsuri sa availability ng tugon ay na-trigger (sa pamamagitan ng timeoutSeconds check parameter), pagkatapos nito ay i-restart ng kubelet ang container. Kapag nagsimula, ang lalagyan ay magsisimulang magsagawa ng mga gawaing masinsinang mapagkukunan at muling magsisimulang muli. Maaari itong maging kritikal para sa mga application na nangangailangan ng bilis ng pagtugon. Halimbawa, ang isang kotse habang nasa kalsada ay naghihintay ng tugon mula sa server, ang tugon ay naantala - at ang sasakyan ay naaksidente.

Sumulat tayo ng redinessProbe na kahulugan na magtatakda ng oras ng pagtugon sa kahilingan ng GET sa hindi hihigit sa dalawang segundo, at tutugon ang application sa kahilingang GET pagkatapos ng 5 segundo. Ang pod.yaml file ay dapat magmukhang ganito:

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

Mag-deploy tayo ng pod na may kubectl:

kubectl apply -f pod.yaml

Maghintay tayo ng ilang segundo at pagkatapos ay tingnan kung paano gumana ang readinessProbe:

kubectl describe pods nodedelayed

Sa dulo ng output makikita mo na ang ilan sa mga kaganapan ay magkatulad itong isa.

Gaya ng nakikita mo, hindi na-restart ng kubectl ang pod kapag lumampas sa 2 segundo ang check time. Sa halip, kinansela niya ang kahilingan. Ang mga papasok na komunikasyon ay nire-redirect sa iba pang gumaganang pod.

Tandaan na ngayong na-offload na ang pod, humihiling muli ang mga ruta ng kubectl dito: hindi na naaantala ang mga tugon sa mga kahilingan sa GET.

Para sa paghahambing, nasa ibaba ang binagong app.js file:

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
Bago ang pagdating ng mga cloud application, ang mga log ay ang pangunahing paraan ng pagsubaybay at pagsuri sa kalusugan ng application. Gayunpaman, walang paraan upang gumawa ng anumang pagwawasto. Ang mga log ay kapaki-pakinabang pa rin ngayon; kailangan nilang kolektahin at ipadala sa isang sistema ng pagkolekta ng log para sa pagsusuri ng mga sitwasyong pang-emergency at paggawa ng mga desisyon. [Ang lahat ng ito ay maaaring gawin nang walang mga cloud application gamit ang monit, halimbawa, ngunit sa k8s ito ay naging mas madali :) - tala ng editor. ]

Ngayon, ang mga pagwawasto ay kailangang gawin halos sa real time, kaya ang mga application ay hindi na kailangang maging mga black box. Hindi, dapat silang magpakita ng mga endpoint na nagbibigay-daan sa mga monitoring system na mag-query at mangolekta ng mahalagang data tungkol sa estado ng mga proseso upang makatugon sila kaagad kung kinakailangan. Ito ay tinatawag na Performance Test Design Pattern, na sumusunod sa High Observability Principle (HOP).

Nag-aalok ang Kubernetes ng 2 uri ng mga pagsusuri sa kalusugan bilang default: readinessProbe at livenessProbe. Parehong gumagamit ng parehong uri ng mga pagsusuri (mga kahilingan sa HTTP GET, mga komunikasyon sa TCP at pagpapatupad ng command). Magkaiba sila sa kung anong mga desisyon ang kanilang gagawin bilang tugon sa mga problema sa mga pod. Nire-restart ng livenessProbe ang lalagyan sa pag-asang hindi na mauulit ang error, at ihihiwalay ng readinessProbe ang pod mula sa papasok na trapiko hanggang sa malutas ang sanhi ng problema.

Ang wastong disenyo ng application ay dapat magsama ng parehong uri ng pagsuri at tiyaking nakakakolekta ang mga ito ng sapat na data, lalo na kapag may inihagis na exception. Dapat din nitong ipakita ang mga kinakailangang endpoint ng API na nagbibigay sa monitoring system (Prometheus) ng mahahalagang sukatan sa kalusugan.

Pinagmulan: www.habr.com

Magdagdag ng komento