De basics: Waaruit bestaat Kubernetes?
Het gehele Kubernetes-systeem bestaat uit diverse hard- en softwarecomponenten. Met Kubernetes manage je een cluster van VMs. Vervolgens plan je – op basis van de beschikbare resources en de afzonderlijke containervereisten – welke containers op welke machines (nodes) moeten worden uitgevoerd. Samenwerkende containers worden gegroepeerd in pods, de operationele basiseenheid voor Kubernetes. Deze pods kun je wederom schalen, al naar gelang de gewenste status of beschikbare capaciteit.
De Hardware: Nodes, Clusters en Persistent Volumes
Nodes: Een node (“knooppunt”) is de kleinste hardware-eenheid in Kubernetes. Een node vertegenwoordigt één machine in je totale cluster. In de meeste productiesystemen is een node een fysieke machine in een datacenter of een virtuele machine die gehost wordt door een cloud provider. In theorie kun je van bijna alles een node maken, zelfs van je smart watch. Door een machine als ee node te beschouwen, voeg je een abstractielaag toe. In plaats van je zorgen te maken over de unieke kenmerken van elke afzonderlijke machine, kun je iedere machine nu zien als een set van CPU en RAM capaciteiten die kan worden geëxploiteerd. Op deze manier kan elke machine in een Kubernetes-cluster iedere andere machine in datzelfde cluster vervangen.
Clusters: Hoewel het werken met individuele nodes (machines) soms noodzakelijk is, is het niet de manier waarop Kubernetes werkt. Je moet aan de slag met het cluster als geheel, in plaats van met de individuele nodes. In Kubernetes worden de capaciteiten van de diverse nodes gebundeld om zo een krachtiger geheel, het cluster, te vormen. Wanneer je programma’s op dat cluster implementeert, zorgt Kubernetes op intelligente wijze voor de verdeling van de workload over de individuele nodes in het cluster. Als er nodes worden toegevoegd of verwijderd, wordt het werk automatisch herverdeeld. Welke afzonderlijke nodes de code uiteindelijk uitvoeren, is niet meer van belang.
Persistent Volumes: Applicaties in een cluster draaien niet gegarandeerd op één specifieke node. Data kunnen dan ook niet zomaar op een willekeurige plaats in het bestandssysteem worden opgeslagen. Als een applicatie data probeert op te slaan in een bestand op de node, maar vervolgens zélf verplaatst wordt naar een nieuwe node, zijn de data niet langer daar, waar de applicatie deze verwacht. Om deze reden wordt iedere traditionele lokale, met de node verbonden opslag behandeld als een tijdelijke cache voor programma’s. Maar van deze lokaal opgeslagen data mag niet worden verwacht dat ze altijd op hun oorspronkelijke plek aanwezig blijven.
Voor permanente gegevensopslag gebruikt Kubernetes zogeheten Persistent Volumes, blijvende (persistente) dataopslagplaatsen. Waar de CPU en RAM resources van alle nodes effectief worden gebundeld en beheerd door het Kubernetes-cluster, wordt de permanente opslag van bestanden dat juist níét. In plaats daarvan worden lokale of cloud drives als Persistent Volume aan het cluster in zijn geheel gekoppeld, zonder geassocieerd te worden met één bepaalde node.
De Software: Containers, Pods en Deployments
Containers: Programma’s op Kubernetes worden verpakt in standaard containers. De plaatsing in containers (‘containerisatie’) zorgt ervoor dat je autonome uitvoeringsomgevingen kunt creëren. Elk programma wordt samen met al zijn afhankelijkheden in één bestand gebundeld, dat vervolgens via het internet gedeeld kan worden. Iedereen kan de container downloaden en op de eigen infrastructuur installeren, waarbij slechts een minimum aan setup-werkzaamheden nodig is. Je kunt weliswaar meerdere programma’s aan een container toevoegen, maar het is beter om je te beperken tot één proces per container. Meerdere kleine containers zijn altijd beter dan één grote. Als elke container een strakke focus heeft, zijn updates eenvoudiger te implementeren en kunnen problemen gemakkelijker worden gediagnosticeerd.
Pods: In tegenstelling tot andere systemen die je in het verleden mogelijk hebt gebruikt, werkt Kubernetes niet rechtstreeks met de afzonderlijke containers. In plaats daarvan verpakt Kubernetes samenwerkende containers in een hoger gelegen structuur, een ‘pod’ (letterlijk: ‘peul’). Alle containers in dezelfde pod delen dezelfde naamruimte (‘namespace‘) en hetzelfde lokale netwerk. Containers in dezelfde pod kunnen onderling gemakkelijk communiceren. Het is dan alsof ze op dezelfde machine draaien, terwijl ze toch in zekere mate geïsoleerd van elkaar werken.
In Kubernetes worden pods gebruikt als replicatie-eenheid. Als een toepassing zó populair wordt dat een individuele pod de werklast niet (meer) kan dragen, kan Kubernetes nieuwe replica’s van de betreffende pod in het cluster installeren. Zelfs wanneer de pods géén zware werklast hebben, is het gebruikelijk om in een productiesysteem meerdere kopieën van dezelfde pod te hebben. Zo wordt werklast beter verdeeld en de faalbestendigheid (‘failover’) verhoogd. Pods kunnen dus vele containers bevatten, maar het is raadzaam om het aantal te beperken. Omdat pods als een eenheid worden geschaald, worden alle containers binnen die pod evenredig mee geschaald, ongeacht hun individuele behoeften. Dat leidt tot capaciteitsverspilling. Om dit op te lossen, moeten de pods zo klein mogelijk blijven. Ze bevatten daarom meestal slechts één hoofdproces en de nauw met dat proces verbonden, ondersteunende containers (deze ‘helper containers’ worden ook wel ‘zijspanwagens’ of ‘side-cars’ genoemd).
Implementatielagen (‘Deployments’): Hoewel pods de basiseenheid van de programmering in Kubernetes zijn, worden ze normaal gesproken niet direct op een cluster gelanceerd. In plaats daarvan worden pods veelal beheerd door een extra abstractielaag: de implementatielaag, ook wel ‘Deployment’ genoemd. Het primaire doel van zo’n implementatielaag is om aan te geven hoeveel replica’s van een pod tegelijkertijd moeten draaien. Wanneer een implementatielaag aan het cluster wordt toegevoegd, zal deze automatisch het vereiste aantal pods in gereedheid brengen en aansluitend monitoren. Als een pod niet meer functioneert, wordt deze automatisch opnieuw aangemaakt. Als je een implementatielaag gebruikt, hoef je dus niet langer iedere pod handmatig te bedienen. Je kunt simpelweg de gewenste systeemstatus aangeven. Deze wordt dan automatisch voor je beheerd.
Toegang verschaffen (‘Ingress’)
Met de hierboven beschreven hard- en softwarecomponenten creëer je een cluster van nodes en lanceer je implementaties van pods op dat cluster. Er moet echter nog een laatste probleem opgelost worden: het toestaan van extern verkeer naar je applicatie. Standaard isoleert Kubernetes de pods van de buitenwereld. Wil je communiceren met een in de pod draaiende dienst, zul je je cluster toegankelijk moeten maken. Dit heet ‘Ingress’, wat staat voor ‘toegangsverschaffing’ of ‘binnendringing’. Normaliter regel je dit via een Ingress Controller, of met de Kubernetes Load Balancer.
Wat zijn de grootste voordelen van Kubernetes?
Kubernetes is inmiddels enorm populair in de cloud-wereld; het is dé standaard voor gecontaineriseerde systemen. Maar waarom? Wat zijn de voordelen?
- Onbeperkte flexibiliteit
Doordat je met Kubernetes al je services en applicatiesoftware in hapklare brokken (namelijk in containers in pods) geautomatiseerd orkestreert, kun je continu op- en neerschalen. Dat levert je onbeperkte flexibiliteit qua capaciteiten en resources op.
- Optimalisatie van performance
Doordat je met gecontaineriseerde microservices werkt, kun je niet alleen onbeperkt maar ook héél exact schalen. Je applicatie is niet langer één geheel, maar bestaat uit kleine, vaststaande functieonderdelen of deelservices (microservices). Elk van die delen kan individueel geschaald worden. Dat zorgt voor optimale performance. Daarnaast houdt Kubernetes je nodes permanent in de gaten. Gaat er iets mis met een VM waarop een node draait, zal Kubernetes zelf proberen om het probleem op te lossen of een nieuwe node activeren om de taken over te nemen. Met deze zogeheten ‘high availability’ truc blijft de performance en beschikbaarheid optimaal.
- Sterkere focus op DevOps voor de business
Kubernetes werkt met API’s waardoor alle functionele onderdelen overal in de cloud gehost kunnen worden. Zodoende kun je applicaties en diensten op continue basis aanleveren, integreren en beheren. Een zegen én een boost voor je DevOps. Kubernetes stelt ontwikkelaars in staat om complexe applicaties te bouwen, onafhankelijk van de onderliggende infrastructuur. Het is niet meer nodig om applicaties platform-compatibel te maken. Ontwikkelen en testen gaat nu een stuk sneller. Je focus komt weer meer op de business te liggen en veel minder op de infrastructuur. Een snellere time-to-market dus!
- Kostenbesparing
De inzet van Kubernetes kan de impact van problemen aanzienlijk verkleinen. Met behulp van de ingebouwde Load Balancer, die ervoor zorgt dat nodes zo efficiënt mogelijk verdeeld worden over de serverhardware, is de benutting van de servicecapaciteit optimaal. Kubernetes checkt automatisch de functionaliteit van iedere clustercomponent (zie ook hoofdstuk 2) en corrigeert waar nodig. Zo heb je voor weinig geld hele hoge beschikbaarheidslevels.
- Tijdsbesparing
Met Kubernetes worden beheertaken geautomatiseerd, containers in pods gegroepeerd, pods in nodes en nodes in clusters gemanaged. Zo worden applicaties en nieuwe features sneller én schaalbaar uitgerold: je bespaart de tijd die voorheen nodig was voor de configuratie van dat alles.
- Omvangrijke ondersteuning
Kubernetes is opensource én zeer populair. De community der “Kubernauten” is groot en de code wordt aan de lopende band verbeterd en uitgebreid. Vele resources voor ondersteuning en ontwikkeling staan je ter beschikking.
Vier valkuilen van Kubernetes
1. Je raakt het overzicht kwijt
Een van de issues met Kubernetes is dat organisaties vaak alles te snel én tegelijkertijd willen: én naar de cloud én Kubernetes voor modernisering van het gehele applicatielandschap én meteen alle workloads migreren. Dat is niet verstandig. Kubernetes gaat niet zo zeer over het ‘draaien’ van de afzonderlijke applicaties in containers, maar juist over het inzetten van en werken met deze containers in je ecosysteem. Met containers kun je weliswaar eindeloos schuiven en schalen, maar het gevaar bestaat dat je, ondanks de orkestratie met Kubernetes, redelijk snel het overzicht over je infrastructuur verliest. Een container is nu eenmaal géén virtuele server, maar een relatief vluchtige eenheid binnen het VM-cluster. Containers zijn agile: in een seconde aangemaakt, maar ook in no time weer ‘weg’. En je overzicht net zo.
2. Je hebt geen eigen blauwdruk gemaakt
Met Kubernetes is ieder systeem uniek georkestreerd. Alles gebeurt automatisch. Maar elk systeem gaat uit van de zogenaamde ‘desired state’. Die beschrijft hóé het systeem moet functioneren: de blauwdruk waarin staat wat op welk moment automatisch uitgevoerd moet worden. Een voorbeeld: als je 16 containers met een bepaalde functie hebt en één daarvan valt uit, dan moet er ook automatisch weer eentje bijkomen. Ook het op- of neerschalen van loads gebeurt automatisch, maar moet wél exact gedefinieerd worden. Stel het je zo voor: iemand leert zwemmen. Aan de kant staat de instructeur die continu roept welke bewegingscombinaties de zwemmer moet maken om vooruit te komen. En jíj bent degene die de instructeur vertelt, wat hij op welk moment moet roepen om de zwemmer goed te laten zwemmen. Dat moet heel nauwkeurig en gedetailleerd, want anders gaat de zwemmer kopje onder. Dát is je blauwdruk.
3. Je beheerst de functionaliteiten niet
Containers kunnen enkel één functionaliteit bevatten, geen content (voor gegevensopslag zijn eigen pods en persistent volumes nodig). Een container is dus steeds maar voor één functie of Microservice verantwoordelijk. Die functionaliteitenscheiding moet je heel consequent – bijna tot in het extreme – doorvoeren. Alles in één monstercontainer stoppen, is namelijk precies wat je níét wilt. Naast containers voor upload, load balancing, logging, infrastructurele requests etc. heb je ook nog eens speciale containers voor de specifieke apps. Een symbiose tussen development en operations (DevOps) is dus absolute noodzaak voor de beheersing van alle functionaliteiten.
4. Je creëert een kettingreactie
Door die strikte scheiding tussen functionaliteiten (van een applicatie of site) moeten alle containers 24/7 naadloos samenwerken. Die coöperatie moet je wederom beschrijven (zie blauwdruk). Zo weten containers elkaar te vinden. Maar als dat niet goed gaat, moet je debuggen. Daarvoor zijn ook weer containers nodig die de fouten loggen. Het ene containerprobleem creëert weer een andere container om dat probleem op te lossen. Dan krijg je een kettingreactie met oneindig veel containers. Dat moet je voorkomen. Containers kun je ook niet updaten. Falende containers worden meteen uitgerangeerd en op basis van je blauwdruk vervangen door een nieuwe versie. Ook daarmee moet je rekening houden.
De Kubernetes Mindset
Als je met Kubernetes en containers werkt, zul je een nieuwe, stringente en consequente denkwijze moeten adopteren. Alles draait om overzichtelijkheid en vooruitzien. Met Kubernetes los je problemen op voordat ze zich voordoen. Dat vraagt om een totaal andere mindset. Niet alleen moet je alle orkestratieregels van tevoren vastleggen. Dat zijn regels als: het minimum aantal actieve instanties per container, responstijden en drempelwaarden, of het bijplaatsen en herstarten van instanties in geval van problemen. Je moet bijvoorbeeld ook heel goed nadenken waar je je data opslaat, want die opslagplaatsen moeten door de diverse containers gelijktijdig benaderd en bevraagd kunnen worden.
Ook moet je van tevoren een draaiboek hebben voor de omgang met gevoelige gegevens, het zogenaamde ‘secret management’. Identiteiten en inloggegevens (bijvoorbeeld usernames en wachtwoorden voor websites) mogen zich nooit als tekst in je containers bevinden; die moeten elders opgeslagen en opgevraagd worden. In een hybride omgeving met een mix van container- en andere infrastructuur moeten alle servers benaderbaar blijven. Dat vergt een integrale, bijna symbiotische manier van ontwikkelen, werken en denken.
En dat is meteen het enige nadeel van Kubernetes: met zóveel opties, variabelen en mogelijkheden moet je kunnen omgaan. Zonder de nodige technische kennis kan Kubernetes al snel een ondoordringbare jungle worden. Het is daarom belangrijk dat je met goede Kubernetesspecialisten werkt, die precies weten waarop je moet letten bij het plannen, ontwerpen, schalen, beveiligen en inrichten van je clusters. Dan weet je zeker dat je ook uit jouw Kubernetes omgeving alle genoemde voordelen kunt halen!