Best practices voor Kubernetes-containers: statuscontroles

Best practices voor Kubernetes-containers: statuscontroles

TL; DR

  • Om een ​​hoge waarneembaarheid van containers en microservices te bereiken, zijn logboeken en primaire statistieken niet voldoende.
  • Voor sneller herstel en grotere veerkracht moeten toepassingen het High Observability Principle (HOP) toepassen.
  • Op applicatieniveau vereist NOP: goede logboekregistratie, nauwkeurige monitoring, sanity checks en prestatie-/transitietracering.
  • Gebruik cheques als onderdeel van NOR gereedheidsonde и levendigheid sonde Kubernetes.

Wat is een Health Check-sjabloon?

Bij het ontwerpen van een bedrijfskritische en zeer beschikbare applicatie is het erg belangrijk om na te denken over een aspect als fouttolerantie. Een applicatie wordt als fouttolerant beschouwd als deze snel herstelt na een storing. Een typische cloudapplicatie maakt gebruik van een microservices-architectuur, waarbij elk onderdeel in een afzonderlijke container wordt geplaatst. En om ervoor te zorgen dat de applicatie op k8s in hoge mate beschikbaar is wanneer u een cluster ontwerpt, moet u bepaalde patronen volgen. Eén daarvan is het Health Check-sjabloon. Het definieert hoe de applicatie met k8s communiceert dat deze in orde is. Dit is niet alleen informatie over de vraag of de pod actief is, maar ook over hoe deze verzoeken ontvangt en erop reageert. Hoe meer Kubernetes weet over de gezondheid van de pod, hoe slimmer de beslissingen worden genomen over verkeersroutering en taakverdeling. Het High Observability Principle zorgt er dus voor dat de applicatie tijdig op verzoeken kan reageren.

Principe van hoge waarneembaarheid (HOP)

Het principe van hoge waarneembaarheid is er één van principes voor het ontwerpen van gecontaineriseerde toepassingen. In een microservices-architectuur maakt het services niet uit hoe hun verzoek wordt verwerkt (en terecht), maar waar het om gaat is hoe ze antwoorden ontvangen van de ontvangende services. Om bijvoorbeeld een gebruiker te authenticeren, stuurt de ene container een HTTP-verzoek naar de andere, waarbij hij een antwoord in een bepaald formaat verwacht - dat is alles. PythonJS kan het verzoek ook verwerken en Python Flask kan reageren. Containers zijn als zwarte dozen met verborgen inhoud voor elkaar. Het NOP-principe vereist echter dat elke service meerdere API-eindpunten vrijgeeft die aangeven hoe gezond de service is, evenals de gereedheid en de fouttolerantiestatus. Kubernetes vraagt ​​deze indicatoren op om na te denken over de volgende stappen voor routing en load-balancing.

Een goed ontworpen cloudapplicatie registreert de belangrijkste gebeurtenissen met behulp van de standaard I/O-streams STDERR en STDOUT. Vervolgens komt er een hulpdienst, bijvoorbeeld filebeat, logstash of fluent, die logs levert aan een gecentraliseerd monitoringsysteem (bijvoorbeeld Prometheus) en een logverzamelingssysteem (ELK-softwaresuite). Onderstaand schema laat zien hoe een cloudapplicatie werkt volgens het Health Test Pattern en het High Observability Principle.

Best practices voor Kubernetes-containers: statuscontroles

Hoe pas ik het Health Check-patroon toe in Kubernetes?

Standaard bewaakt k8s de status van de pods met behulp van een van de controllers (implementaties, ReplicaSets, DaemonSets, StatefulSets Etc etc.). Nadat de controller heeft ontdekt dat de pod om de een of andere reden is gevallen, probeert hij deze opnieuw op te starten of naar een ander knooppunt te verplaatsen. Een pod kan echter melden dat hij actief is, maar zelf functioneert hij niet. Laten we een voorbeeld geven: uw applicatie gebruikt Apache als webserver, u hebt de component op verschillende pods van het cluster geïnstalleerd. Omdat de bibliotheek verkeerd is geconfigureerd, reageren alle verzoeken aan de applicatie met code 500 (interne serverfout). Bij het controleren van de levering geeft het controleren van de status van pods een succesvol resultaat, maar klanten denken daar anders over. Wij zullen deze ongewenste situatie als volgt omschrijven:

Best practices voor Kubernetes-containers: statuscontroles

In ons voorbeeld doet k8s dat wel functionaliteitscontrole. Bij dit type verificatie controleert de kubelet continu de status van het proces in de container. Zodra hij begrijpt dat het proces is gestopt, zal hij het opnieuw starten. Als de fout kan worden opgelost door simpelweg de applicatie opnieuw te starten, en het programma is ontworpen om bij elke fout af te sluiten, dan is een procesgezondheidscontrole alles wat u nodig hebt om de NOP en het Health Test Pattern te volgen. Het enige jammere is dat niet alle fouten worden geëlimineerd door opnieuw op te starten. In dit geval biedt k8s twee diepere manieren om problemen met de pod te identificeren: levendigheid sonde и gereedheidsonde.

LivenessProbe

Het is tijd levendigheid sonde kubelet voert 3 soorten controles uit: bepaalt niet alleen of de pod actief is, maar ook of deze klaar is om verzoeken te ontvangen en adequaat te reageren:

  • Stel een HTTP-verzoek in voor de pod. Het antwoord moet een HTTP-antwoordcode bevatten in het bereik van 200 tot 399. De codes 5xx en 4xx geven dus aan dat de pod problemen ondervindt, ook al wordt het proces uitgevoerd.
  • Als u pods wilt testen met niet-HTTP-services (bijvoorbeeld de Postfix-mailserver), moet u een TCP-verbinding tot stand brengen.
  • Voer een willekeurig commando uit voor een pod (intern). De controle wordt als succesvol beschouwd als de voltooiingscode van de opdracht 0 is.

Een voorbeeld van hoe dit werkt. De volgende poddefinitie bevat een NodeJS-toepassing die een fout van 500 genereert bij HTTP-verzoeken. Om ervoor te zorgen dat de container opnieuw wordt opgestart wanneer een dergelijke fout wordt ontvangen, gebruiken we de livenessProbe-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

Dit verschilt niet van elke andere poddefinitie, maar we voegen een object toe .spec.containers.livenessProbe. Parameter httpGet accepteert het pad waarnaar het HTTP GET-verzoek wordt verzonden (in ons voorbeeld is dit /, maar in gevechtsscenario's kan er zoiets zijn als /api/v1/status). Een andere livenessProbe accepteert een parameter initialDelaySeconds, die de verificatiebewerking instrueert een bepaald aantal seconden te wachten. De vertraging is nodig omdat de container tijd nodig heeft om op te starten en bij het opnieuw opstarten enige tijd niet beschikbaar zal zijn.

Om deze instelling op een cluster toe te passen, gebruikt u:

kubectl apply -f pod.yaml

Na een paar seconden kunt u de inhoud van de pod controleren met behulp van de volgende opdracht:

kubectl describe pods node500

Zoek aan het einde van de uitvoer dat is wat.

Zoals je kunt zien, initieerde livenessProbe een HTTP GET-verzoek, genereerde de container een fout 500 (waarvoor hij was geprogrammeerd) en startte de kubelet hem opnieuw op.

Als je je afvraagt ​​hoe de NideJS-applicatie is geprogrammeerd, zijn hier de app.js en Dockerfile die zijn gebruikt:

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

Het is belangrijk om dit op te merken: livenessProbe zal de container alleen opnieuw opstarten als deze mislukt. Als een herstart de fout die verhindert dat de container wordt uitgevoerd niet corrigeert, kan de kubelet geen actie ondernemen om het probleem te verhelpen.

gereedheidsonde

readinessProbe werkt op dezelfde manier als livenessProbes (GET-verzoeken, TCP-communicatie en uitvoering van opdrachten), behalve voor acties voor probleemoplossing. De container waarin de fout wordt gedetecteerd, wordt niet opnieuw opgestart, maar wordt geïsoleerd van inkomend verkeer. Stel je voor dat één van de containers veel berekeningen uitvoert of zwaar belast wordt, waardoor de responstijden toenemen. In het geval van livenessProbe wordt de controle op de beschikbaarheid van het antwoord geactiveerd (via de timeoutSeconds check-parameter), waarna de kubelet de container opnieuw start. Wanneer de container wordt gestart, begint hij resource-intensieve taken uit te voeren en wordt hij opnieuw opgestart. Dit kan van cruciaal belang zijn voor toepassingen die reactiesnelheid nodig hebben. Een auto wacht bijvoorbeeld onderweg op een reactie van de server, de reactie wordt vertraagd en de auto krijgt een ongeluk.

Laten we een redinessProbe-definitie schrijven die de responstijd van het GET-verzoek instelt op niet meer dan twee seconden, en de toepassing zal na vijf seconden op het GET-verzoek reageren. Het pod.yaml-bestand zou er als volgt uit moeten zien:

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

Laten we een pod met kubectl inzetten:

kubectl apply -f pod.yaml

Laten we een paar seconden wachten en dan kijken hoe de readinessProbe werkte:

kubectl describe pods nodedelayed

Aan het einde van de uitvoer kunt u zien dat sommige gebeurtenissen vergelijkbaar zijn deze.

Zoals u kunt zien, heeft kubectl de pod niet opnieuw opgestart toen de controletijd langer dan 2 seconden was. In plaats daarvan heeft hij het verzoek ingetrokken. Inkomende communicatie wordt doorgestuurd naar andere, werkende pods.

Houd er rekening mee dat nu de pod is ontladen, kubectl aanvragen er opnieuw naartoe stuurt: reacties op GET-aanvragen worden niet langer vertraagd.

Ter vergelijking vindt u hieronder het gewijzigde app.js-bestand:

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
Vóór de komst van cloudapplicaties waren logboeken het belangrijkste middel om de gezondheid van applicaties te monitoren en te controleren. Er waren echter geen middelen om corrigerende maatregelen te nemen. Logboeken zijn vandaag de dag nog steeds nuttig; ze moeten worden verzameld en naar een logverzamelingssysteem worden gestuurd om noodsituaties te analyseren en beslissingen te nemen. [Dit alles zou gedaan kunnen worden zonder cloudapplicaties die bijvoorbeeld monit gebruiken, maar met k8s werd het veel eenvoudiger :) – noot van de redactie. ]

Tegenwoordig moeten correcties vrijwel in realtime worden doorgevoerd, waardoor aanvragen geen black boxen meer hoeven te zijn. Nee, ze moeten eindpunten tonen waarmee monitoringsystemen waardevolle gegevens over de status van processen kunnen opvragen en verzamelen, zodat ze indien nodig onmiddellijk kunnen reageren. Dit wordt het Performance Test Design Pattern genoemd, dat het High Observability Principle (HOP) volgt.

Kubernetes biedt standaard 2 soorten gezondheidscontroles: readinessProbe en livenessProbe. Beide gebruiken dezelfde soorten controles (HTTP GET-verzoeken, TCP-communicatie en uitvoering van opdrachten). Ze verschillen in de beslissingen die ze nemen als reactie op problemen in de pods. livenessProbe start de container opnieuw op in de hoop dat de fout niet opnieuw zal optreden, en readinessProbe isoleert de pod van inkomend verkeer totdat de oorzaak van het probleem is opgelost.

Een goed applicatieontwerp moet beide soorten controles omvatten en ervoor zorgen dat ze voldoende gegevens verzamelen, vooral wanneer er een uitzondering optreedt. Het moet ook de noodzakelijke API-eindpunten tonen die het monitoringsysteem (Prometheus) voorzien van belangrijke gezondheidsstatistieken.

Bron: www.habr.com

Voeg een reactie