Kubernetes

Containers (zie ook mijn pagina over Docker) zijn populair in het gebruik omdat ze minder resources gebruiken dan complete Virtuele Machines. Voor elke applicatie kunnen één of meerdere containers gemaakt worden en samen vormen zij de complete applicatie. Denk bijvoorbeeld aan een WordPress website container die samenwerkt met een mariaDB database container.

Mocht het complexer worden dan kan ‘Docker Swarm‘ gebruikt worden. Een alternatief is de container-orchestrator ‘Kubernetes‘. Het verschil tussen de twee is niet eenduidig aan te wijzen, alhoewel Kubernetes uitgereider is en meer mogelijkheden geeft om de containers te beheren. Beiden maken gebruik van clusters om hierin de containers te laten ‘draaien’ en managen de schaalbaarheid (en beschikbaarheid) van de applicatie. In dit artikel kijken we naar Kubernetes.

Kubernetes werkt met ‘Environments‘. Elke environment kun je zien als een applicatie met alle bijbehorende onderdelen. In de environment worden de containers gedefinieerd en die worden ‘pods’ genoemd. Er kunnen dus meerdere pods binnen één environment aanwezig zijn, minimaal is één pod de basis. Pods worden onderscheiden met een ‘label‘ ter herkenning. Vervolgens kunnen er TCP-poorten gekoppeld worden naar de ‘buitenkant’ zodat de environment (applicatie) bereikbaar is. Deze poorten worden aangegeven met ‘services‘.

De ‘loadbalancer‘ is een belangrijk onderdeel van Kubernetes en deze heeft als taak om de efficientie van de nodes binnen een cluster te sturen. Dat kan zijn om meerdere nodes bij te schakelen bij hoge belasting van het systeem, of nodes op verschillende (cloud) systemen te groeperen voor een hogere (geografische) bereikbaarheid. Zelfs verschillende cloud- en on-premise systemen kunnen hiermee samenwerken voor hoge beschikbaarheid.

Om kubernetes te kunnen gebruiken op bv. een Mac computer zijn twee componenten noodzakelijk: MiniKube en KubeCTL. Daarnaast heb een hypervisor nodig, bijvoorbeeld VirtualBox.

Installeer KubeCTL met het volgende commando (MacOS):

$brew install kubernetes-cli

Installeer MiniKube (v0.31.0) met het volgende commando (MacOS):

$curl -Lo minikube https://storage.googleapis.com/minikube/releases/v0.31.0/minikube-darwin-amd64
$chmod +x minikube
$sudo cp minikube /usr/local/bin/
$rm minikube

Om nu een Kubernetes cluster te starten, geef het volgende commando:

$minikube start

Dit zal een VM aanmaken in bv. VirtualBox en de status hiervan kan opgevraagd worden met:

$minikube status

Mocht dit een foutmelding geven, omdat er bv. al een ‘oude’ installatie van minikube aanwezig was, dan kun je deze ‘oude’ omgeving verwijderen door de VM van VirtualBox en de lokale directory ~/.minikube te verwijderen.

Om nu docker te laten connecten met de minikube VM dienen de variabelen bekend gemaakt te worden:

$eval $(minikube docker-env)

en hierna kunnen de docker containers getoond worden met:

$docker ps

Pods

Nu kunnen ‘environments’ met ‘pods’ gemaakt worden! Laten we een TomCat webservers starten met behulp van Kubernetes. Eerst maken we een directory genaamd tomcat met hierin een pod-definition.yml bestand.

$mkdir tomcat
$cd tomcat
$vi pod-definition.yml

De inhoud van pod-definition.yml:

apiVersion: v1
kind: Pod
metadata:  
  name: tomcat-app
  labels:
    app: tomcat
spec:
  containers:
    - name: tomcat
      image: tomcat:9.0
      ports:
        - containerPort: 8080

Meer details over de commando’s kan hier gevonden worden: https://kubernetes.io/docs/reference/kubectl/cheatsheet/

Om nu dit definition-bestand te gebruiken en te starten zodat de TomCat server bereikbaar is op de aangegeven port 8080, dienen twee commando’s gegeven te worden. De eerste zal het definition-bestand inlezen en pods aanmaken (kubelet) en het tweede commando ‘exposed‘ de TCP port van de node naar de buitenwereld. MiniKube (kube-proxy) zal een lokale poort ‘mappen’ naar deze poort 8080 en we vinden de URL hiervoor met het derde commando.

$kubectl apply -f ./pod-definition.yml
$kubectl expose pods tomcat-app --type=NodePort
$minikube service tomcat-app --url

De TCP-port kan ook gevonden worden met:
$kubectl get services

Nu kan TomCat server op mijn systeem bereikt worden op http://192.168.99.100:32741

Om de running pod te stoppen (verwijderen), dient het volgende commando:

$kubectl delete pods <pod-name>
$kubectl delete service <service-name>

Andere commando’s

$kubectl get pods
$kubectl port-forward tomcat-app-56ff5c79c5-7gjwg 8080:8080
$kubectl attach tomcat-app-56ff5c79c5-7gjwg
$kubectl exec -ti tomcat-app-56ff5c79c5-7gjwg bash

ReplicaSet

Mocht nu de applicatie te langzaam worden omdat er bv. meer gebruikers toegang proberen te krijgen, dan kan een replica uitkomst bieden. Op deze manier kunnen replica’s zorgen voor meer gelijke pods en de ‘load’ verdelen. We maken hiervoor een replica-controller via het bestand rs-definition.yml met de volgende inhoud:

apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: tomcat-rs
labels:
app: tomcat
type: frontend
spec:
template:
metadata:
name: tomcat-app
labels:
app: tomcat
type: frontend
spec:
containers:
- name: tomcat
image: tomcat:9.0
ports:
- containerPort: 8080
replicas: 3

selector:
matchLabels:
type: frontend

Let op dat de apps/v1 api nu aangeroepen dient te worden! De inhoud is, m.u.v. de ‘kind‘, nagenoeg hetzelfde als de pod-definitie maar nu wordt een template gebruikt dat de inhoud van de pod-definitie bevat. Met ‘replicas: 3‘ geven we aan dat we drie pods willen runnen. De ‘selector‘ geeft aan welke pods de ReplicaSet ‘in de gaten’ moet houden, pods met dit type label (frontend) dienen dus aanwezig te zijn.

$kubectl apply -f rs-definition.yml
$kubectl get replicationset

De output van het tweede commando is:

NAME        DESIRED   CURRENT   READY   AGE
tomcat-rs 3 3 3 40s

Met het ‘kubectl get pods‘ commando zien we nu 3 pods ‘draaien’:

NAME              READY   STATUS    RESTARTS   AGE
tomcat-rs-7mdgq 1/1 Running 0 47s
tomcat-rs-bpf7j 1/1 Running 0 47s
tomcat-rs-pndxl 1/1 Running 0 47s

De service-poort (TCP-port) die we voorheen op de pod lieten binnenkomen, gaat nu naar de ReplicaSet met:

$kubectl expose replicaset tomcat-rs --type=NodePort
$kubectl get services
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)          AGE
kubernetes ClusterIP 10.96.0.1 443/TCP 2h
tomcat-rs NodePort 10.100.0.5 8080:32189/TCP 6s

Op de MacBook draait ‘minikube’ en de URL voor de Tomcat replica’s vinden we met:

$minikube service tomcat-rs --url

In dit geval is de URL dan http://192.168.99.100:32189

Mocht nu één, of meer pods wegvallen, dan zal de ReplicaSet er automatisch voor zorgen dat er een nieuwe pod gestart wordt tot het aantal dat aangegeven is via ‘replicas:’