Neuigkeiten von trion.
Immer gut informiert.

Kubernetes in Docker mit k3s

Kubernetes

Von Rancher Labs stammt eine abgespeckte Version von Kubernetes mit dem Namen k3s. Kubernetes wird oft als k8s abgekürzt, so dass eine reduzierte Version passenderweise als k3s bezeichnet werden kann.

Das Ziel von k3s ist, eine Kubernetes Umgebung anbieten zu können, wenn begrenzte Resourcen in der Betriebsumgebung den Einsatz einer regulären Kubernetes Installation erschweren oder unmöglich machen.

Im Gegensatz zum vollen Kubernetes Stack benötigt k3s kein etcd als Datenspeicher, sondern setzt auf SQLite. Hier macht sich die Architektur von Kubernetes natürlich besonders bezahlt: Da lediglich der Kubernetes API Server auf die Persistenz zugreifen darf, merken alle weiteren Komponenten von der Umstellung nichts. Um weiteren Hauptspeicher zu sparen wurden auch viele Controller Manager entfernt, die in der Zielumgebung jedoch sowieso nicht sinnvoll zum Einsatz kommen würden.

Im folgenden schauen wir uns an, wie mit Docker und k3s ein Kubernetes Cluster als Docker Container aufgesetzt werden kann. Das ist besonders praktisch, wenn es darum geht, Tests zu machen oder mit Kubernetes zu entwickeln. So spart man sich Minikube oder einen Testcluster.
Übringens arbeitet man auch bei Kubernetes selbst daran, Docker als Umgebung nutzen zu können: Das kind-Projekt (Kubernetes in Docker) verfolgt einen vergleichbaren Ansatz: https://kind.sigs.k8s.io/

Natürlich kann k3s auch ganz ohne Docker eingesetzt werden und ist sogar der Regelfall, denn k3s soll z.B. in Kombination mit Raspberry Pi und vergleichbaren Single Board Computer (SBC) gut verwendet werden können.
Mehr zu k3s gibt es auf der offiziellen Homepage: https://k3s.io/

Am einfachsten ist k3s in Docker mit docker-compose zu verwenden. Eine Konfiguration als docker-compose.yml ist im folgenden Code-Beispiel gezeigt.

docker-compose.yaml für k3s
version: '3'
services:
  server:
    image: rancher/k3s:v0.8.1
    command: server --disable-agent
    environment:
    - K3S_CLUSTER_SECRET=somethingtotallyrandom
    - K3S_KUBECONFIG_OUTPUT=/output/kubeconfig.yaml
    - K3S_KUBECONFIG_MODE=666
    volumes:
    - k3s-server:/var/lib/rancher/k3s
    # get the kubeconfig file
    - .:/output
    ports:
    - 6443:6443

  node:
    image: rancher/k3s:v0.8.1
    tmpfs:
    - /run
    - /var/run
    privileged: true
    environment:
    - K3S_URL=https://server:6443
    - K3S_CLUSTER_SECRET=somethingtotallyrandom
    ports:
      - 31000-32000:31000-32000

  worker:
    image: rancher/k3s:v0.8.1
    tmpfs:
    - /run
    - /var/run
    privileged: true
    environment:
    - K3S_URL=https://server:6443
    - K3S_CLUSTER_SECRET=somethingtotallyrandom

volumes:
  k3s-server: {}

Das Setup unterscheidet zwischen master, worker und einer node. Die node verfügt über Portmappings, so dass Kubernetes Services als NodePort bereitgestellt werden können. Der worker hat diese nicht, so dass hier eine Skalierung auf mehrere Instanzen ohne Portkonflikte möglich ist.

Nachdem das k3s Setup durch ein docker-compose up gestartet ist, wird der Kubernetes Cluster gebootet. Zum Zugriff auf den API Server wird im aktuellen Verzeichsnis die Konfiguration für kubectl als Datei kubeconfig.yaml bereitgestellt.

Diese Datei wird durch den Schalter --kubeconfig bei kubectl aktivier, wie im folgenden Beispiel zu sehen.

Zugriff auf den k3s Kubernetes Cluster in Docker
$ kubectl --kubeconfig kubeconfig.yaml get pods -A
NAMESPACE     NAME                         READY   STATUS      RESTARTS   AGE
kube-system   coredns-b7464766c-zc8xw      1/1     Running     0          9m41s
kube-system   helm-install-traefik-44v5r   0/1     Completed   0          9m41s
kube-system   svclb-traefik-g6lch          2/2     Running     0          9m24s
kube-system   traefik-5c79b789c5-tkpp4     1/1     Running     0          9m24s

Bei der Abfrage der Cluster Nodes im Docker basierten Kubernetes Setup sind die Worker Nodes zu sehen.

Abfrage der Nodes - umgesetzt durch Docker Container
$ kubectl --kubeconfig kubeconfig.yaml get nodes
NAME           STATUS   ROLES    AGE   VERSION
5f24d45bc295   Ready    worker   5m    v1.14.6-k3s.1
be629ccaa40f   Ready    worker   5m    v1.14.6-k3s.1

Wenn man von dem k3s Kubernetes den Component-Status abfragt, fällt direkt auf, dass hier keine etcd Instanzen zu sehen sind. Das erklärt sich daraus, dass k3s statt etcd auf eine SQLite Datenbank setzt.

Abfrage des Kubernetes Component Status
$ kubectl --kubeconfig kubeconfig.yaml get cs
NAME                 STATUS    MESSAGE   ERROR
scheduler            Healthy   ok
controller-manager   Healthy   ok

Zur Demonstration kann ein einfacher Pod dienen, zum Beispiel mit dem nginx Webserver. Damit später ein Service einfach erzeugt werden kann, bietet es sich an, direkt den Port 80 zu deklarieren.

Erzeugung eines simplen Pod in k3s
$ kubectl --kubeconfig kubeconfig.yaml run --restart=Never nginx --port 80 --image nginx
pod/nginx created

Der erzeugte Pod kann direkt abgefragt werden.

Abfrage des erzeugten Kubernetes Pod in k3s
$ kubectl --kubeconfig kubeconfig.yaml get pods
NAME    READY   STATUS    RESTARTS   AGE
nginx   1/1     Running   0          24s

Um auf den Pod zuzugreifen wird als nächstes ein Service vom Typ NodePort erzeugt, indem kubectl expose verwendet wird. Ein Zugriff ist dann direkt auf localhost mit dem entsprechenden Port, der in der Service Liste abgerufen werden kann, möglich.

Bereistellung der Anwendung in Kubernetes als NodePort Service
$ kubectl --kubeconfig kubeconfig.yaml expose pod/nginx --type=NodePort
service/nginx exposed
$ kubectl --kubeconfig kubeconfig.yaml get svc
NAME         TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)        AGE
kubernetes   ClusterIP   10.43.0.1      <none>        443/TCP        38m
nginx        NodePort    10.43.26.158   <none>        80:31580/TCP   25m
$  curl http://localhost:31580
<!DOCTYPE html>
<html>
<head>
...

Möchte man den Demo Cluster skalieren, so kann dies ebenfalls durch docker-compose erfolgen, indem die Anzahl der Worker spezifiziert wird: --scale worker=3

Zu beachten gilt noch, dass k3s ein eigenes Volume deklariert, in dem die Konfigurationsdaten des Kubernetes Clusters gehalten werden. Möchte man diese löschen, z.B. um noch einmal mit einem sauberen Setup zu starten, muss das Volume gelöscht werden.

Abbau des k3s Kubernetes Clusters
$ docker-compose down
$ docker volume ls -q -f "label=com.docker.compose.volume=k3s-server"
$ docker volume rm $(docker volume ls -q -f "label=com.docker.compose.volume=k3s-server")

Dies Setup mit k3s in Docker ist derzeit ein praktischer Weg, um ein schnelles, isoliertes Setup für Experimente zu ermöglichen. Sicherlich wird das anfangs erwähnte kind-Projekt von Kubernetes eine interessante Alternative.




Zu den Themen Kubernetes, Docker und Cloud Architektur bieten wir sowohl Beratung, Entwicklungsunterstützung als auch passende Schulungen an:

Auch für Ihren individuellen Bedarf können wir Workshops und Schulungen anbieten. Sprechen Sie uns gerne an.

Auch für Ihren individuellen Bedarf können wir Workshops und Schulungen anbieten. Sprechen Sie uns gerne an.

Feedback oder Fragen zu einem Artikel - per Twitter @triondevelop oder E-Mail freuen wir uns auf eine Kontaktaufnahme!

Los geht's!

Bitte teilen Sie uns mit, wie wir Sie am besten erreichen können.