Your web browser is out of date. Update your browser for more security, speed and the best experience on this site.

Hoe Kubernetes Operators stateful applicaties moeiteloos in de lucht kunnen houden

Het ontwikkelen en laten draaien van een applicatie is niet altijd even makkelijk. De applicatie moet liefst altijd beschikbaar zijn, maar het moet bijvoorbeeld ook piekbelasting kunnen verdragen, applicatie crashes, updates met minimale downtime… Gelukkig zijn er technische oplossingen zoals Kubernetes Operators om dit op te lossen op een generieke manier.

Deel dit artikel
Java

Het ontwikkelen en laten draaien van een applicatie is niet altijd even makkelijk. De applicatie moet liefst altijd beschikbaar zijn, maar het moet bijvoorbeeld ook piekbelasting kunnen verdragen, applicatie crashes, updates met minimale downtime. Gelukkig zijn er technische oplossingen om dit op te lossen op een generieke manier. Vraag dat maar aan Niels Claeys!

Niels gaf op Haxx Digital Edition een keynote over Kubernetes Operators. Dat is, in een notendop, een methode om stateful/complexe applicaties te verpakken, deployen en beheren binnen kubernetes. Een hele mondvol, maar eenmaal je weet waarvoor je ze kunt gebruiken zal het je werk een pak makkelijker maken!

Kubernetes wint al een jaar of acht aan populariteit. Het is een open source tool om containers te deployen en beheren. Een container bevat de code (functionaliteit) samen met al zijn afhankelijkheden (dependencies) en configuratie. Containers zijn met andere woorden een virtualisatie van je operating system; in tegenstelling tot virtuele machines (VM) die een virtualizatie van je hardware zijn. Doordat telkens enkel een klein laagje van de kernel geïmplementeerd is, is er veel minder overhead dan bij VM’s. In een notendop is Kubernetes de ideale manier om snel productie waardige applicaties in containers te bouwen, deployen en schalen.

Om applicaties in een productieomgeving te deployen moet er aan heel wat zaken voldaan zijn: automatisch afhandelen van crashes, configuratie management, geautomatiseerde updates en rollbacks, schalen in functie van de belasting, bepalen op welke host machine de applicatie moet draaien… Voor stateless applicaties bevat kubernetes de bouwblokken om al deze zaken te implementeren. Dankzij Kubernetes Operators kan je ook met stateful applicaties gewerkt worden, maar daar gaan we later dieper op in.

Een stateless applicatie bevat zelf geen data die onthouden moet worden wanneer de container wordt herstart/geüpdate. Een beetje zoals een schoolbord dat na gebruik steeds gewist wordt. Een typisch voorbeeld is een web applicatie die zijn data ophaalt uit een databank.

Het is dat automatische aspect dat Kubernetes zo aantrekkelijk maakt. Zonder al té technisch te gaan zorgt Kubernetes er namelijk voor dat je applicatie wat er ook gebeurt zal blijven draaien. Laten we dat illustreren met een voorbeeld!

Afbeelding1

Een voorbeeld: de deployment van een NGINX-applicatie

Dit is een voorbeeld van de deployment van een NGINX-applicatie. Zoals je ziet staat beschreven dat we twee instanties van deze applicatie in onze cluster willen draaien. Kubernetes zal er voor zorgen dat er ten alle tijden twee instanties draaien. Als er om de een of andere reden eentje zou crashen, zal Kubernetes ervoor zorgen dat er een tweede wordt opgestart.

Interactie met kubernetes gebeurd meestal via de kubectl command line (CLI), maar je zou ook de api-server rechtstreeks kunnen aanspreken. Als gebruiker definieer je de kubernetes objecten meestal in YAML-files omdat dit leesbaarder en gemakkelijker is, intern stelt Kubernetes zijn objecten voor in JSON-formaat.

Naast de api-server is de controller een andere cruciale component binnen kubernetes. Deze gaat, de naam zegt het zelf, bepalen wat er op welk moment moet gebeuren. Hiervoor vergelijkt de controller de huidige toestand van de cluster ten opzichte van de gewenste toestand. Als die niet hetzelfde is als gedefinieerd in json configuratie, zal die bijgestuurd worden. Dit mechanisme noemen we de control-loop. Wanneer er in ons voorbeeld maar één NGINX-instantie zou draaien, zal de controller een tweede aanmaken.

Elk object dat je in Kubernetes gedefinieerd hebt (pod, deployment, service…) heeft een controller die de logica bevat om te bepalen wat er moet gebeuren wanneer de huidige toestand afwijkt van de gewenste toestand. Deze ingebouwde controllers maken het makkelijke om automatisch stateless applicaties te deployen/updaten/runnen.

Afbeelding2

Kubernetes Operators voor stateful applicaties

Als je applicatie ‘state’ bevat – het is bijvoorbeeld een database – wordt het wat moeilijker. Deze applicaties vertrekken namelijk niet steeds van een blanco blad. In dat geval moet je de domeinlogica (zoals het maken van backups of een eventuele replica als master voor je een upgrade doet) ergens kunnen plaatsen. Ook dat wil je niet manueel doen maar ergens inbouwen. In zo’n geval gebruiken we een operator die de functionaliteit van kubernetes uitbreidt.

Een operator bevat twee belangrijke aspecten:

  • Een custom resource: dit is puur een declaratieve beschrijving van je object met de verschillende parameters/configuratie. Dit bevat alle informatie die nodig is om de applicatie te managen.
  • Een controller die op basis van je resource gaat bepalen wat er moet gebeuren om de kubernetes cluster in de juiste toestand te krijgen. Dit is dus een eigen implementatie en een uitbreiding van de Kubernetes-API. Die maakt uiteraard ook gebruik van de zogenaamde ‘control loop’, maar bevat eigen logica om om een verschil in toestand op te lossen. De huidige toestand van de cluster wordt vergeleken met de verwachtingen van de gebruiker om zo na te gaan welke stappen er ondernomen moeten worden om daar te geraken.

Dit is vooral belangrijk bij complexe, stateful applicaties. In dat geval zijn de primitieve objecten die binnen Kubernetes bestaan onvoldoende. Daarnaast wil je de domeinlogica embedden binnen Kubernetes zelf, zodat je niets manueel moet afhandelen.

Je kan het een beetje vergelijken met hoe je in objectgeoriënteerd programmeren objecten maakt met de primitieven die in je programmeertaal bestaan. Op diezelfde manier ga je in Kubernetes een operator maken die de primitieven van Kubernetes gaat combineren om tot de gewenste domeinlogica te komen.

Dit maakt het bijvoorbeeld mogelijk om het upgraden van een complexe applicatie te vereenvoudigen: wanneer je dit met de ingebouwde objecten van Kubernetes zou doen, moet je misschien vier of vijf verschillende resources in een bepaalde volgorde aanmaken. Met de operator moet je maar één custom resource aanmaken, waarna die er automatisch voor gaat zorgen dat achterliggend alle objecten in de juiste volgorde worden aangemaakt.

Heel wat bedrijven hebben hun eigen operators gedefinieerd. Denk bijvoorbeeld aan databases of queueing systemen, maar ook cloud providers. Zo maken ze het makkelijker voor mensen die vertrouwd zijn met Kubernetes om infrastructuur in de cloud te beheren. De S3 Operator van AWS bijvoorbeeld maakt het mogelijk om S3 buckets te managen zonder iets van AWS te kennen. Je moet als gebruiker enkel kennis van het desbetreffende custom resource om het binnen kubernetes te gebruiken. De belangrijkste parameters moet je definiëren en registreren bij Kubernetes, waarna de operator ervoor zal zorgen dat de connectie met AWS gelegd wordt en de juiste S3 Bucket aangemaakt zal worden.

Afbeelding3

Een voorbeeld: automatisch Markdown-documentatie in slides omzetten

Op Haxx Digital Edition toonde Java-coach Niels Claeys hoe hij met Kubernetes Operators zijn presentatie gedefinieerd als Markdown automatisch in slides kan laten omzetten. De volledige code van dit voorbeeld kan je hier bekijken.

Als eerste definieerde Niels het presentatie-object (Presentation yaml with markdown). Hierin staan de slides met hun inhoud beschreven. Op basis van die input bepaalt de operator (de Haxx operator) wat het moet doen om van de input een slideshow te maken.

Die zal de configuratie moeten nemen en deze opslaan in een configmap (configmap with markdown). Dan zal er een pod, een container dus (Pod serve ppt) gecreëerd worden die de configuratie zal nemen en er een presentatie van maakt. Om de operator te bouwen maken we gebruik van de Operator SDK, een framework ontwikkeld door Red Hat. De operator SDK maakt het makkelijk om operators te bouwen en te deployen op een Kubernetes cluster.

De operator wordt in Go geschreven net als de Operator SDK. Niels creëerde eerst de project structuur door het project te initializeren: hij gaf aan wat zijn operator is, welke naam ze krijgt en wat het domein is. Vervolgens werden heel wat files aangemaakt met boiler plate logica bij het schrijven van een operator.

De volgende stap was het creëren van de API: het presentatie-object en de achterliggende controller-logica. In dit geval was het presentatie-object een struct waar enkel een string in steekt. De controller is iets complexer: daarin steekt de logica van wat er moet gebeuren als er een nieuw presentatie-object wordt aangemaakt. In Niels’ voorbeeld moet er dan een nieuwe config map en de bijbehorende pod aangemaakt worden.

Die informatie vind je in de Reconcile function. Deze vraagt eerst de huidige toestand van de cluster op om dan te weten wat er moet gebeuren. Zo wordt er bijvoorbeeld nagegaan of er een nieuwe config map moet aangemaakt worden of dat de bestaande moet worden geüpdatet.

Daarnaast is er nog de pod – de container – die in dit geval de Markdown-logica in een presentatie zal gieten. Ook hier wordt er gekeken of de pod al bestaat zodat deze aangemaakt kan worden als dat nodig is.

Om dit vervolgens te deployen op Kubernetes heb je eerst een cluster nodig. Dat kan bijvoorbeeld met MicroK8s, een cluster die lokaal gedraaid wordt. Wanneer de operator gedeployed wordt, worden er meteen een aantal objecten aangemaakt: een deployment, een service en de custom resource definition. Deze laatste maakt het mogelijk om ons presentatie-object te registreren binnen kubernetes.


Minder manueel werk

Dankzij Kubernetes wordt het dus een stuk makkelijker om applicaties te managen doordat zoveel mogelijk geautomatiseerd wordt. Het manuele werk vermindert, doordat Kubernetes logica bevat om applicaties te herstarten, schalen, updaten,… Dankzij Kubernetes Operators is het ook mogelijk om deze bestaande functionaliteit uit te breiden naar de noden van je applicatie. Dit is vooral van belang voor ‘stateful applicaties’, toepassingen die niet per se van een blanco blad beginnen wanneer je ze gebruikt.

Benieuwd naar meer Axxes Insights?

Niels Claeys

Niels Claeys

Java

Hulp nodig met een GraphQL implementatie?

Onze experts staan klaar om je verder te helpen.

contacteer ons
Axxes