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

Toen ik begon met Helm verwachtte ik niet meer dan een templating-tool voor Kubernetes YAML-bestanden. Ik had al ervaring met Docker en Kubernetes, maar Helm was voor mij nog een ontbrekend onderdeel. Ik wilde begrijpen waarom zoveel Kubernetes projecten Helm gebruiken en of het daadwerkelijk meerwaarde biedt ten opzichte van losse manifesten.

Omdat ik Helm nog niet eerder in een eigen project had gebruikt, besloot ik een eenvoudige FastAPI-applicatie stap voor stap uit te breiden en te deployen met een zelfgeschreven Helm-chart.

Docker bouwt de applicatie, Helm regeld de uitrol

Mijn eerste inzicht was misschien wel de belangrijkste. Ik dacht aanvankelijk dat Docker en Helm deels hetzelfde doel hadden. Tijdens het experimenteren werd echter duidelijk dat ze ieder een eigen verantwoordelijkheid hebben.

Docker zorgt ervoor dat mijn applicatie overal op dezelfde manier kan draaien. De image bevat de applicatie, de benodigde dependencies en de runtime.

Helm doet iets anders. Helm beschrijft hoe die applicatie binnen Kubernetes wordt uitgerold. Zaken zoals het aantal replica’s, configuratie, netwerktoegang en CPU- en geheugenlimieten worden niet in de Docker-image vastgelegd, maar in de Helm chart.

Wat mij vooral opviel, is dat Docker en Helm elkaar niet vervangen, maar juist aanvullen. Docker beschrijft de applicatie zelf, terwijl Helm beschrijft hoe Kubernetes die applicatie uitrolt en beheert.

Configuratie loskoppelen van de applicatie

Een ander inzicht was het scheiden van configuratie en applicatie. In eerste instantie plaatste ik configuratie in mijn Deployment. Tijdens het bouwen ben ik dit gaan vervangen door ConfigMaps en Secrets, waardoor dezelfde Docker-image in verschillende omgevingen gebruikt kan worden zonder opnieuw gebouwd te hoeven worden. Hierdoor werd ook duidelijk waarom Helm zoveel gebruikmaakt van `values.yaml`: niet om de applicatie te veranderen, maar om de omgeving waarin deze draait te configureren.

Een ConfigMap wijzigen is niet genoeg

Een inzicht waar ik niet direct rekening mee had gehouden, was dat een wijziging in een ConfigMap niet automatisch leidt tot een nieuwe rollout van de pods.

Daardoor bleef mijn applicatie met de oude configuratie draaien. Terwijl de ConfigMap al was aangepast.

Daar kwam ik uit bij een oplossing die ik inmiddels regelmatig terugzie in Helm charts: een checksum-annotation op de Pod-template. Zodra de inhoud van de ConfigMap verandert, verandert ook de checksum. Kubernetes ziet daardoor de Pod-template als gewijzigd en voert automatisch een rolling update uit.

Dat vond ik een mooi voorbeeld van hoe Helm en Kubernetes elkaar aanvullen.

Ingress maakte de lokale omgeving realistischer

Tot dat moment gebruikte ik voornamelijk  kubectl port-forward om mijn applicatie lokaal bereikbaar te maken.

Daarna heb ik Ingress toegevoegd en mijn applicatie bereikbaar gemaakt via sslip.io. Hierdoor kon ik de applicatie benaderen via een normale URL in plaats van een lokale poort.

Dat lijkt misschien een kleine stap, maar de omgeving begon hierdoor veel meer op een productieomgeving te lijken. Bovendien kon ik meerdere applicaties naast elkaar draaien zonder telkens verschillende lokale poorten te onthouden.

Meerdere replica’s laten zien hoe Kubernetes verkeer verdeelt

Om beter te begrijpen hoe Kubernetes verkeer over meerdere pods verdeelt, heb ik het aantal replica’s verhoogd.

Door de hostname van iedere pod terug te geven in de API kon ik direct zien dat requests door Kubernetes automatisch over meerdere pods werden verdeeld.

Dat maakte ook meteen duidelijk welke rol een Service binnen Kubernetes speelt. De Service vormt het vaste aanspreekpunt, terwijl de achterliggende pods zonder problemen kunnen worden vervangen of opgeschaald.

Readiness en liveness bleken twee verschillende problemen op te lossen

Een onderdeel dat ik bijzonder interessant vond, waren de readiness- en liveness-probes. In eerste instantie leek het alsof beide hetzelfde doel hadden: controleren of een applicatie gezond is. Tijdens het experimenteren werd echter duidelijk dat ze verschillende verantwoordelijkheden hebben. Met een readiness probe heb ik één pod bewust “Not Ready” gemaakt. Kubernetes haalde deze direct uit de load balancer, terwijl de overige pods gewoon verkeer bleven verwerken. De applicatie bleef daardoor volledig beschikbaar.

Dat vond ik misschien wel de meest interessante demonstratie van het hele leerproject. In plaats van alleen over readiness te lezen, zag ik direct welk effect het had op de beschikbaarheid van de applicatie.

Een liveness probe heeft juist een ander doel. Wanneer een applicatie niet meer gezond is of vastloopt, zal Kubernetes de container automatisch opnieuw starten om de gewenste situatie te herstellen.

Door beide situaties zelf uit te proberen werd het verschil veel duidelijker dan wanneer ik alleen de documentatie had gelezen.

Resources zijn meer dan alleen limieten

Tot slot heb ik CPU- en geheugenrequests en -limits toegevoegd aan mijn Deployment.

In eerste instantie zag ik dit vooral als een manier om resourcegebruik te beperken. Tijdens het experimenteren werd duidelijk dat Kubernetes requests ook gebruikt om workloads op nodes te plannen.

Resources zijn dus niet alleen een beveiliging tegen overmatig gebruik, maar ook een belangrijk onderdeel van de scheduler.

Onderdelen die ik heb geïmplementeerd

Tijdens dit leerproject heb ik onder andere gewerkt met:

  • een eigen Helm chart voor een FastAPI-applicatie
  • ConfigMaps en Secrets
  • automatische rollouts bij configuratiewijzigingen
  • Ingress met sslip.io
  • meerdere replica’s en load balancing
  • readiness- en liveness-probes
  • CPU- en geheugenrequests en -limits

Daarnaast ben ik begonnen met het uitbreiden van mijn omgeving met Prometheus en Grafana om monitoring ook onderdeel van de omgeving te maken.

Conclusie

Wat begon als een manier om Kubernetes YAML-bestanden eenvoudiger te beheren en te parametriseren, bleek uiteindelijk veel meer te zijn. Helm helpt om deployments herhaalbaar, onderhoudbaar en overzichtelijk te maken. Tegelijkertijd dwong het mij om beter na te denken over onderwerpen als configuratiebeheer, deployment-strategieën, beschikbaarheid en resourcebeheer. Juist doordat ik deze concepten zelf heb uitgeprobeerd, vielen veel Kubernetes-concepten op hun plek. Voor mij was Helm daarom niet alleen een hulpmiddel om applicaties uit te rollen, maar vooral een manier om Kubernetes beter te leren begrijpen.

Software Engineer

Meer weten?

"*" geeft vereiste velden aan

Privacyverklaring*

Toen ik begon met Helm verwachtte ik niet meer dan een templating-tool voor Kubernetes YAML-bestanden. Ik had al ervaring met Docker en Kubernetes, maar Helm was voor mij nog een ontbrekend onderdeel. Ik wilde begrijpen waarom zoveel Kubernetes projecten Helm gebruiken en of het daadwerkelijk meerwaarde biedt ten opzichte van losse manifesten.

Omdat ik Helm nog niet eerder in een eigen project had gebruikt, besloot ik een eenvoudige FastAPI-applicatie stap voor stap uit te breiden en te deployen met een zelfgeschreven Helm-chart.

Software Engineer

Meer weten?

"*" geeft vereiste velden aan

Privacyverklaring*

Dit artikel delen

Bekijk ook deze artikelen

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...
Infiniot op basisscholen Infiniot zet zich in voor de volgende generatie en leert kinderen op basisscholen al te graag over de energietransitie met leuke experimenten en interactieve spellen. Een dag...

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

Maak impact. Samen. Jij ook?

"*" geeft vereiste velden aan

Privacyverklaring*