Andreas Bruns

Softwareentwicklung für Oldenburg und Bremen

k3s – 5 weniger als k8s (Kubernetes)

Kubernetes (k8s) hat das Betreiben von Software in der Cloud revolutioniert. Anwendungen werden in Containern, wie Docker, bereitgestellt und Kubernetes führt sie performant auf mehreren Servern aus und sorgt bei Last automatisch für eine entsprechende Skalierung.

Will man Kubernetes produktiv einsetzen, sollte man die Dienste der großen Cloud-Anbieter (Google GKE, Amazon EKS, Microsoft AKS) nutzen, da der eigene Betrieb eines ausfallsicheren Kubernetes-Clusters viel Hardware, Wissen und Aufwand erfordert. Für den Einstieg bietet Kubernetes Minikube, das man auf seinem lokalen Rechner installieren kann. Will man jedoch einen Kubernetes-Cluster mit mehreren Rechner aufsetzen, dann sind günstige Raspberry Pis und das ressourcensparende k3s von Ranger eine gute Alternative.

Installation als Master-Node und Worker-Node

Also schnell den stärksten Raspberry Pi (mein Modell 1 funktionierte nicht, aber Modell 2-4 schon) schnappen und als K3s-Master-Node aufsetzen:

curl -sfL https://get.k3s.io | sh -
kubectl --all-namespaces=true get all

Falls wir einen weiteren Raspberry Pi haben, können wir den als K3s-Worker-Node aufsetzen und mit dem Master verbinden. Dazu benötigen wir zunächst ein Master-Token:

cat /var/lib/rancher/k3s/server/node-token
K104b.....::server:8089f.....

Auf den Worker-Nodes erfolgt die K3s-Installation auf gleiche Weise, wobei wir zunächst die URL der Master-Node und das Master-Token als Umgebungsvariable angeben:

export  K3S_URL=https://merkur:6443
export  K3S_TOKEN=K104b.....::server:8089f.....
curl -sfL https://get.k3s.io | sh -

Wenn wir jetzt die Nodes auf dem Master abrufen, dann sollten alle auf Ready stehen. Das ist bei Verwendung unterschiedlicher K3s-Versionen übrigens nicht der Fall.

pi@merkur:~ $ kubectl get nodes
NAME     STATUS   ROLES    AGE   VERSION
uranus   Ready    <none>   33d   v1.17.0+k3s.1
merkur   Ready    master   33d   v1.17.0+k3s.1

Grundlegendes zu K3s

Wollen wir K3s neu starten, kann das mit einem der folgenden Befehle erfolgen:

sudo systemctl restart k3s
sudo service k3s restart

Für das Deinstallieren von K3s gibt es entsprechende Uninstall-Skripte auf Master- und Worker-Nodes:

/usr/local/bin/k3s-uninstall.sh
/usr/local/bin/k3s-agent-uninstall.sh 

Falls wir Kubernetes von einem anderen Rechner steuern möchten, können wir folgendermaßen vorgehen:

  • kubectl installieren (z.B. auf einem MAC):
    brew install kubectl
  • K3s-Konfiguration auf lokalen Rechner kopieren:
    scp pi@merkur:/etc/rancher/k3s/k3s.yaml ~/.kube/config-merkur
  • in der Konfigurationsdatei, die Adresse 127.0.0.1 mit der IP-Adresse des Masters ersetzen
  • bei kubectl-Aufrufe die Konfigurationsdatei angeben:
    kubectl --kubeconfig ~/.kube/config-merkur get pods
  • Übrigens: wenn wir die Konfigurationsdatei unter ~/.kube/config abspeichern, benötigen wir den kubeconfig-Parameter nicht

Sobald etwas nicht funktioniert, sollten wir uns die K3s-Meldungen im Log anschauen:

tail /var/log/syslog | grep -i k3s
tail /var/lib/rancher/k3s/agent/containerd/containerd.log

K3s verwendet nicht die komplette Docker-Laufzeitumgebung, sondern nutzt die Container-Laufzeitumgebung containerd. Statt docker benutzen wir den Befehl crictl, um entsprechende Befehle auszuführen:

sudo crictl ps -all

Anwendung mit K3s ausführen – der schnelle Weg: kubectl run

Wollen wir eine Anwendung mit Kubernetes ausführen, können wir das auf zwei Arten machen:

  • per kubectl run
  • per Manifest-Datei

Der einfache und schnelle Weg geschieht mit: kubectl run. Das angegebene Container-Image wird entsprechend den Parametern gestartet:

kubectl run tomcat-reps --image=arm32v7/tomcat --replicas=2 --port=8080 --expose=true 
kubectl get all
NAME                               READY   STATUS        RESTARTS   AGE
pod/tomcat-reps-74b5dd955f-8tz9l   1/1     Running       0          59s
pod/tomcat-reps-74b5dd955f-l7zwx   1/1     Running       0          59s

NAME                  TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
service/tomcat-reps   ClusterIP   10.43.238.192   <none>        8080/TCP   59s

NAME                          READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/tomcat-reps   2/2     2            2           59s

NAME                                     DESIRED   CURRENT   READY   AGE
replicaset.apps/tomcat-reps-74b5dd955f   2         2         2       59s

Durch den Befehl werden folgende Dinge ausgeführt:

  • lädt ein Tomcat-Image (ARM) von Docker für Raspberry Pi (–image=arm32v7/tomcat)
  • ein Deployment wird erstellt
  • das Deployment sorgt für ein Replicaset
  • das Replicaset startet zwei Pods (–replicas=2)
  • bei den Pods wird Port 8080 exponiert (–port 8080)
  • Service wird erstellt, der Anfrage an die Pods weiterreicht (–expose=true)
  • Tomcat-Server ist aufrufbar: curl 10.43.238.192:8080

Den Port des Services könnte man per zwischengeschalteten Nginx herausreichen. Eine einfachere Lösung bietet der Kubernetes-Befehl kubectl port-forward, bei dem man die IP-Adresse der Netzwerk-Schnittstelle des Hosts angeben kann:

kubectl port-forward --address 192.168.178.102 service/tomcat-reps  8080

Anwendung mit K3s ausführen – der nachhaltige Weg mit Manifest-Dateien

Falls man Änderungen an dem Deployment vornehmen möchte, muss man bei dem Run-Befehl das bestehende Deployment löschen und wieder neuanlegen. Der bessere Weg ist die Erstellung von Manifest-Dateien, da vorgenommene Datei-Anpassungen von Kubernetes erkannt und entsprechend umgesetzt werden.

Dazu erstellen wir eine Manifest-Datei für das Deployment tomcat-manifest-dep.yaml und eine Manifest-Datei für den Service tomcat-manifest-svc.yaml. Sobald wir die beiden Konfigurationen auf Kubernetes angewendet haben, erhalten wir das gleich Ergebnis wie zuvor. Jetzt können wir jedoch einfach Anpassungen durchführen, indem wir beispielsweise die Anzahl der Pods erhöhen.

Datei für das Deployment: tomcat-manifest-dep.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: tomcat-mani
  labels:
   app: tomcat-mani
spec:
  replicas: 2
  selector:
    matchLabels:
      app: tomcat-mani
  template:
    metadata:
      labels:
        app: tomcat-mani
    spec:
      containers:
      - name: tomcat-mani
        image: arm32v7/tomcat
        imagePullPolicy: Always
        ports:
        - containerPort: 8080
          protocol: TCP

Datei für den Service: tomcat-mani-svc.yaml

apiVersion: v1
kind: Service
metadata:
  name: tomcat-mani
  labels:
    app: tomcat-mani
spec:
  type: ClusterIP
  ports:
    - port: 8080
      protocol: TCP
      targetPort: 8080
  selector:
    app: tomcat-mani
kubectl apply -f tomcat-mani-dep.yaml,tomcat-mani-svc.yaml
kubectl rollout status deploy/tomcat-mani

Wie geht es weiter?

Zunächst einmal können wir die erstellten Deployments, Services, Replicasets und Pods löschen:

kubectl delete service/tomcat-reps
kubectl delete deployment.apps/tomcat-reps
 
kubectl delete service/tomcat-mani
kubectl delete deployment.apps/tomcat-mani

Damit haben wir unseren kleinen K3s-Cluster wieder bereinigt und steht bereit für weitere Kubernetes-Übungen – es gibt noch viel zu lernen 🙂 . Das ist ein guter Zeitpunkt, mit dem hervorragenden Kubernetes-Tutorial anzufangen. Und falls mal dauerhaft Anwendungen installiert werden sollen, dann lohnt sich die Verwendung des Paketmanagers Helm.

Kommentare sind geschlossen.