Van Docker naar Helm: inzichten uit mijn eerste Helm-project

Toen ik met Helm begon, zag ik het vooral als een templating-tool voor Kubernetes YAML bestanden. Door een eenvoudige FastAPI applicatie stap voor stap uit te rollen met een eigen Helm-chart ontdekte ik al snel dat Helm veel meer doet dan alleen manifests parametriseren.

In deze blog laat ik zien hoe Helm helpt bij configuratiebeheer, rollouts, Ingress, replica’s, health probes en resourcebeheer, en waarom het een waardevolle aanvulling is op Docker en Kubernetes.

Van Docker-image naar Kubernetes-deployment met Helm

Toen ik met Helm begon, dacht ik aanvankelijk dat Docker en Helm deels
hetzelfde probleem oplosten. Tijdens het bouwen van mijn omgeving werd
al snel duidelijk dat ze juist verschillende verantwoordelijkheden
hebben.

Docker verpakt de applicatie in een container-image met de
applicatiecode, dependencies en runtime. Daardoor kan dezelfde image op
verschillende omgevingen op dezelfde manier worden uitgevoerd.

Helm zit een laag hoger. Een Helm chart beschrijft hoe die
container-image binnen Kubernetes wordt uitgerold. Denk daarbij aan het
aantal replica’s, configuratie, netwerktoegang en CPU- en
geheugenrequests en -limits.

Docker en Helm vervangen elkaar dus niet, maar vullen elkaar aan: Docker
zorgt voor een reproduceerbare container-image, terwijl Helm beschrijft
hoe Kubernetes deze image moet configureren en uitrollen.

Configuratie loskoppelen van de applicatie

Een belangrijke volgende stap was het loskoppelen van configuratie en
applicatie. In mijn eerste versie stond een deel van de configuratie
rechtstreeks in de Deployment. Dat werkt, maar maakt het lastiger om
dezelfde container-image in verschillende omgevingen te gebruiken.

Daarom heb ik de configuratie ondergebracht in ConfigMaps en Secrets. De
applicatie image blijft hierdoor hetzelfde, terwijl instellingen per
omgeving kunnen verschillen.

Hier werd voor mij ook de rol van values.yaml binnen Helm duidelijker.
De values veranderen niet de applicatie zelf, maar bepalen hoe de
applicatie in een specifieke omgeving wordt uitgerold en geconfigureerd.
Dezelfde chart en container image kunnen daardoor met verschillende
configuraties worden gebruikt.

Een ConfigMap wijzigen is niet genoeg

Bij het aanpassen van een ConfigMap liep ik tegen gedrag aan waar ik
vooraf niet bij had stilgestaan. De ConfigMap werd correct bijgewerkt,
maar de bestaande pods werden niet automatisch opnieuw uitgerold.
Daardoor kon de applicatie nog met de oude configuratie blijven draaien.

De oplossing was een checksum annotation op de pod template. Helm
berekent daarbij een checksum over de relevante configuratie en neemt
deze op in de template van de pod. Zodra de ConfigMap verandert,
verandert ook de checksum.

Voor Kubernetes betekent dit dat de pod template is gewijzigd. De
deployment voert vervolgens een rolling update uit en maakt nieuwe pods
aan met de nieuwe configuratie.

Dit was een goed voorbeeld van een relatief klein technisch detail dat
belangrijk wordt zodra deployments reproduceerbaar en voorspelbaar
moeten zijn.

Ingress maakte de lokale omgeving realistischer

In het begin gebruikte ik voornamelijk kubectl port-forward om mijn
FastAPI applicatie lokaal bereikbaar te maken. Dat is handig tijdens
ontwikkeling, maar lijkt weinig op de manier waarop applicaties normaal
binnen een Kubernetes omgeving worden ontsloten.

Daarom heb ik Ingress toegevoegd en de applicatie via sslip.io
bereikbaar gemaakt. In plaats van een lokale poort kon ik de applicatie
vervolgens via een normale URL benaderen.

Dat lijkt een kleine verandering, maar maakte de omgeving een stuk
realistischer. Ook werd het eenvoudiger om meerdere applicaties naast
elkaar te draaien zonder voor iedere applicatie een aparte lokale poort
te hoeven onthouden.

Meerdere replica’s maken load balancing zichtbaar

Om te onderzoeken wat er gebeurt wanneer meerdere instanties van
dezelfde applicatie draaien, heb ik het aantal replica’s verhoogd.

Iedere pod liet via de API zijn eigen hostname teruggeven. Door meerdere
requests uit te voeren kon ik daardoor direct zien dat het verkeer via
de Kubernetes service over verschillende pods werd verdeeld.

Daarmee werd ook de rol van een service concreet. De service vormt een
stabiel aanspreekpunt voor de applicatie, terwijl de pods daarachter
tijdelijk zijn. pods kunnen opnieuw worden aangemaakt, vervangen of
opgeschaald zonder dat clients hoeven te weten welke specifieke pod een
request afhandelt.

Readiness en liveness lossen verschillende problemen op

Readiness- en liveness-probes leken op het eerste gezicht sterk op
elkaar: beide controleren immers de status van een applicatie. Door ze
daadwerkelijk uit te proberen werd het verschil veel duidelijker.

Met een readiness probe heb ik één pod bewust not ready gemaakt.
Kubernetes stopte vervolgens met het routeren van verkeer naar deze pod,
terwijl de overige pods requests bleven verwerken. De niet-ready pod
bleef bestaan, maar deed tijdelijk niet meer mee aan het verwerken van
verkeer.

Dat maakte direct zichtbaar waarom readiness belangrijk is voor
beschikbaarheid. Een pod hoeft niet per definitie kapot te zijn om
tijdelijk geen verkeer te moeten ontvangen. De applicatie kan
bijvoorbeeld nog bezig zijn met initialiseren of tijdelijk niet in staat
zijn requests correct af te handelen.

Een liveness probe lost een ander probleem op. Deze controleert of de
applicatie nog functioneert. Wanneer de liveness check blijft falen, kan
Kubernetes de container opnieuw starten. Dit is bijvoorbeeld relevant
wanneer een proces nog wel draait, maar intern is vastgelopen.

Door beide situaties zelf te simuleren werd het onderscheid tussen kan
deze pod verkeer verwerken? en functioneert deze applicatie nog? veel
concreter dan wanneer ik alleen de documentatie had gelezen.

Resources zijn meer dan alleen limieten

Ook CPU- en geheugenrequests en -limits bleken meer te doen dan alleen
voorkomen dat een applicatie onbeperkt resources gebruikt.

Requests geven aan hoeveel CPU en geheugen een workload nodig heeft.
Kubernetes gebruikt deze informatie onder andere bij het plannen van
pods op nodes. Limits bepalen vervolgens hoeveel resources een container
maximaal mag gebruiken.

Resourceconfiguratie heeft daarmee niet alleen invloed op het gedrag van
een individuele applicatie, maar ook op de manier waarop Kubernetes de
beschikbare capaciteit van een cluster verdeelt.

Van experiment naar een complete omgeving

Uiteindelijk draaide de FastAPI applicatie via een eigen Helm chart met
externe configuratie, automatische rollouts bij configuratiewijzigingen,
Ingress, meerdere replica’s, health probes en CPU- en geheugenrequests
en -limits.

De experimenten waren bewust kleinschalig, maar de onderliggende
principes zijn dezelfde die in grotere Kubernetes omgevingen belangrijk
worden: deployments reproduceerbaar maken, configuratie per omgeving
beheren, applicaties beschikbaar houden tijdens wijzigingen en resources
voorspelbaar verdelen.

Als volgende stap ben ik begonnen met het toevoegen van Prometheus en
Grafana. Daarmee wil ik naast deployment en beschikbaarheid ook
monitoring en observability onderdeel maken van de omgeving.

Conclusie

Wat begon als een manier om Kubernetes YAML bestanden eenvoudiger te
beheren en te parametriseren, werd uiteindelijk een veel breder
leerproject. Helm maakte niet alleen deployments overzichtelijker, maar
dwong mij ook om na te denken over de manier waarop een applicatie
binnen Kubernetes daadwerkelijk wordt beheerd.

Onderwerpen als configuratiebeheer, rolling updates, service discovery,
beschikbaarheid en resourceplanning werden vooral duidelijk doordat ik
ze zelf kon aanpassen, verstoren en observeren.

Daarmee werd Helm voor mij meer dan alleen een hulpmiddel om
Kubernetes manifests te templaten. Het vormde vooral een praktische
manier om beter te begrijpen hoe de verschillende onderdelen van
Kubernetes samenwerken om applicaties reproduceerbaar en betrouwbaar uit
te rollen.

 

 

 

 

 

Software Engineer

Meer weten?

"*" geeft vereiste velden aan

Privacyverklaring*

Toen ik met Helm begon, zag ik het vooral als een templating-tool voor Kubernetes YAML bestanden. Door een eenvoudige FastAPI applicatie stap voor stap uit te rollen met een eigen Helm-chart ontdekte ik al snel dat Helm veel meer doet dan alleen manifests parametriseren.

In deze blog laat ik zien hoe Helm helpt bij configuratiebeheer, rollouts, Ingress, replica’s, health probes en resourcebeheer, en waarom het een waardevolle aanvulling is op Docker en Kubernetes.

Software Engineer

Meer weten?

"*" geeft vereiste velden aan

Privacyverklaring*

Dit artikel delen

Bekijk ook deze artikelen

De reden dat het zo is aangeslagen is omdat de tool twee belangrijke dingen doet. Hij detecteert storingen met behulp van een slim machine learning model (technische deep-dive), en hij...
In het boek Philosophy of Software Design beschrijft software-engineer en hoogleraar John Ousterhout een aantal tijdloze principes voor het bouwen van software. Hoewel het boek geen specifieke programmeertalen, frameworks of...
  De conferentie was erg leerzaam- er waren presentaties over CIM specifieke software zoals CIMTool, hoe organisaties als TenneT omgaan met het CIM datamodel, en een “CIM University”. De CIM...

Samen met ons bouwen aan een duurzame toekomst? Neem contact op!

Maak impact. Samen. Jij ook?

"*" geeft vereiste velden aan

Privacyverklaring*