Pods, resources en schaling

Geplaatst door

Het is best practice om pods CPU en memory limieten te geven. Doe je dat niet, dan loop je het risico dat een probleem in de software of bijvoorbeeld een brute force aanval van buitenaf er voor zorgen dat de pod alle beschikbare resources op een Kubernetes node kan claimen. Uiteindelijk kan die ene pod er voor zorgen dat de volledige node “out of memory” gaat en het auto healing mechanisme van Kubernetes de “desired state” probeert te herstellen met als resultaat dat het probleem groter wordt. Dat is natuurlijk een sneeuwbaleffect waar we niet op zitten te wachten. Door het gebruik van memory en cpu te begrenzen zorg je er voor dat dit soort situaties slimmer aangepakt kunnen worden. Het is beter dat je pod crasht dan dat je cluster het begeeft. Uiteindelijk wil je uiteraard ook niet dat je pod crasht. Misschien is dat het moment dat er (automatisch) geschaald moet worden.

Resource gebruik

De pods moeten dus resource limieten krijgen. Standaard wordt dit op de meeste Kubernetes clusters ondersteund maar zul je dit zelf aan je yaml definities moeten toevoegen. Maar wat zijn dan goede waardes? Te lage limieten laten je pod crashen en te hoge limieten claimen zinloos veel resources. Het vinden van de ideale waardes is niet altijd even makkelijk. Meten is weten. Het moet inzichtelijk worden hoeveel CPU en Memory resources een pod gebruikt. Hierbij zijn zowel de momentele waardes als de waardes over tijd belangrijk. Om dit voor elkaar te krijgen moeten een aantal zaken geconfigureerd/geïnstalleerd zijn:

Metrics-server  

Standaard geeft een commando als “kubectl top pods –all-namespaces” een foutmelding dat Heapster niet gevonden kan worden. Dit is een wat misleidende terugkoppeling van Kubernetes. Heapster is inmiddels al weer een tijdje vervangen door een ander project genaamd metrics-server. De yaml files om de metrics-server te installeren, kunnen gevonden worden op https://github.com/kubernetes/kubernetes/tree/master/cluster/addons/metrics-server
Al vrij snel wordt het mogelijk om met de volgende commando’s het actuele resource gebruik van nodes en containers zichtbaar te maken:

“kubectl top nodes” 

“kubectl top pods -n default”

Visualiseren van gebruikte resources door pods

Nu de metrics-server zijn werk doet, kan het ook interessant zijn om het gebruik van resources door pods door de tijd heen te meten. Je kan eens kijken naar Kube-state-metrics. Waar de metrics-server onder andere bedoeld is om horizontaal schalen mogelijk te maken, Is Kube-state-metrics een exporter om de staat van Kubernetes api objecten (waaronder pods en hun gebruik van resources) bij te houden. Met Prometheus kan de exporter vervolgens uitgelezen worden zodat je er mooie grafieken van kan maken.

De werking van resource limieten

Vanuit Kubernetes perspectief kun je voor zowel Memory als CPU resources twee dingen instellen:

Request: De Kubernetes scheduler verwacht dit minimum als beschikbare resources om de pod te starten op de node.
Limits: De pod mag nooit meer resources gebruik dan aangegeven in de limiet.

In de yaml file ziet zoiets er dan bijvoorbeeld zo uit:

apiVersion: v1
kind: Pod
metadata:
  name: demopod
  namespace: demo
spec:
  containers:
  - name: cpu-demo
    image: imagebouwer/image
    resources:
      limits:
        cpu: "1"
        memory: 512Mi
      requests:
        cpu: "0.5"
        memory: 256Mi

De abstractielaag die Kubernetes biedt maakt het werken met limieten een stuk eenvoudiger. Onder de motorkap blijft het Linux en worden er Control Groups of wel cgroups gebruikt en krijg je te maken met de linux process scheduler. Soms lijkt het er in Grafana op dat de gestelde limieten van een pod nooit gehaald worden terwijl je in Jaeger soms extreme uitschieters ziet. Het is dan tijd om de limieten toch iets hoger in te stellen en voor het automatische schalen de trigger niveau’s aan te passen. Voordat er productie gedraaid wordt, is het verstandig om hier uitvoerig mee te testen zodat uiteindelijk optimale waardes gebruikt worden. Cgroups en de Linux Kernel scheduler verdienen op zichzelf al een artikel. Verdere diepgang op deze onderwerpen valt daarom in dit artikel buiten de scope.

Horizontaal schalen

Tot slot nog even wat aandacht voor het horizontaal schalen van Pods. Dit is handmatig te doen maar kan ook geautomatiseerd worden. Als de workload voor een pod hoger wordt, en een specifiek trigger niveau bereikt heeft qua CPU/memory gebruik, dan kan er automatisch horizontaal geschaald worden zoals in het voorbeeld hieronder.

kubectl autoscale deployment testapplicatie --cpu-percent=50 --min=1 --max=10

Bedenk wel dat niet elke applicatie zich goed leent om horizontaal te schalen en dat sommige problemen niet opgelost worden door extra pods binnen de deployment toe te voegen. Ook worden Kubernetes nodes niet automatisch horizontaal geschaald. Zolang je je daar bewust van bent is het een ideale manier om piekbelasting op te vangen.

Tot slot

Resource limieten houden je platform online maar het is nog niet altijd even makkelijk om goede waardes te vinden. Het zelfde geldt voor het automatisch schalen op basis van bepaalde triggers. Welk probleem probeer je er mee op te lossen? Daarnaast werkt de schaling zolang de resource voorraad strekt. Het is daarom belangrijk om de zaken goed te testen zodat er geen onvoorziene situaties ontstaan in je productie omgeving.

Geef een reactie