Kubernetes auf podman mit kind

Über das Tool kind ist es möglich schnell einen Kubernetes Cluster innerhalb einer podman Umgebung aufzusetzen.

Vorbereitung

Dazu muss das Tool heruntergeladen oder über das Paketmanagement installiert.

podman und auch kubectl müssen ebenfalls installiert und konfiguriert sein.

Einrichtung des Clusters

Der einfachste Weg den Cluster einzurichten geht über das systemctl-run Kommando. Hierbei übernimmt der systemd die Kontrolle über die Umgebung für Umgebung in der der podman Befehl läuft.

$ systemd-run -p Delegate=yes --setenv=KIND_EXPERIMENTAL_PROVIDER=podman \
              --scope --user kind create cluster
Running as unit: run-rc08baccf7a724130a9284623ccd2ddf9.scope; invocation ID: 0fb8f6ec97a94f5782bbfc3f0f78a3ae
using podman due to KIND_EXPERIMENTAL_PROVIDER
enabling experimental podman provider
Creating cluster "kind" ...
 ✓ Ensuring node image (kindest/node:v1.27.3) 🖼 
 ✓ Preparing nodes 📦  
 ✓ Writing configuration 📜 
 ✓ Starting control-plane 🕹️ 
 ✓ Installing CNI 🔌 
 ✓ Installing StorageClass 💾 
Set kubectl context to "kind-kind"
You can now use your cluster with:

kubectl cluster-info --context kind-kind

Thanks for using kind! 😊

Nach dieser Installation kann direkt über das kubectl Kommando ein Zugriff auf die Kubernetes Node erfolgen.

$ kubectl cluster-info
Kubernetes control plane is running at https://127.0.0.1:34125
CoreDNS is running at https://127.0.0.1:34125/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy

Dazu wurde die Datei $HOME/.kube/config um den Context kind-kind erweitert oder eine neue Datei erzeugt.

Genauere Informationen über den laufenden Cluster Node lassen sich über kubectl cluster-info dump abrufen.

Cluster Konfiguration

Statt den Cluster mit einer Default Konfiguration zu starten, kann man eine yaml Datei mit passenden Werten zur Erzeugung nutzen.

Beispiele:

# three node (two workers) cluster config
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
- role: worker
- role: worker
# six node (three workers) full cluster config
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
- role: control-plane
- role: control-plane
- role: worker
- role: worker
- role: worker

Die erstellten yaml Dateien sind bei der Erstellung des Clusters anzugeben.

$ systemd-run -p Delegate=yes --setenv=KIND_EXPERIMENTAL_PROVIDER=podman \
              --scope --user kind create cluster --config multinode.yaml \
              --name multinode

Weitere Beispiele und Parameter sind in der kind Konfiguration zu finden.

Cluster entfernen

Der Befehl kind kann ebenfalls zum entfernen eines Clusters genutzt werden.

$ systemd-run -p Delegate=yes --setenv=KIND_EXPERIMENTAL_PROVIDER=podman \                                                                       
              --scope --user kind delete cluster --name kind
Running as unit: run-rba10793fe745483eb50981e5b0d3417b.scope; invocation ID: ce7a140694494618a843f3a01687e619
using podman due to KIND_EXPERIMENTAL_PROVIDER
enabling experimental podman provider
Deleting cluster "kind" ...
Deleted nodes: ["kind-control-plane"]

Erweitertes Beispiel

Installation eines einfachen Clusters mit einer Node. nginx-ingress über die Ports 8000 und 8443 auf dem Host zu erreichen.

$ cat >/tmp/cluster.yaml <<EOF
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
  kubeadmConfigPatches:
  - |
    kind: InitConfiguration
    nodeRegistration:
      kubeletExtraArgs:
        node-labels: "ingress-ready=true"
  extraPortMappings:
  - containerPort: 80
    hostPort: 8000
    protocol: TCP
  - containerPort: 443
    hostPort: 8443
    protocol: TCP
EOF
$ systemd-run -p Delegate=yes --setenv=KIND_EXPERIMENTAL_PROVIDER=podman \
              --scope --user kind create cluster --config=/tmp/cluster.yaml
$ kubectl --context kind-kind apply -f \
    https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/kind/deploy.yaml
$ cat >/tmp/ingress.yaml <<EOF
kind: Pod
apiVersion: v1
metadata:
  name: foo-app
  labels:
    app: foo
spec:
  containers:
  - command:
    - /agnhost
    - netexec
    - --http-port
    - "8080"
    image: registry.k8s.io/e2e-test-images/agnhost:2.39
    name: foo-app
---
kind: Service
apiVersion: v1
metadata:
  name: foo-service
spec:
  selector:
    app: foo
  ports:
  # Default port used by the image
  - port: 8080
---
kind: Pod
apiVersion: v1
metadata:
  name: bar-app
  labels:
    app: bar
spec:
  containers:
  - command:
    - /agnhost
    - netexec
    - --http-port
    - "8080"
    image: registry.k8s.io/e2e-test-images/agnhost:2.39
    name: bar-app
---
kind: Service
apiVersion: v1
metadata:
  name: bar-service
spec:
  selector:
    app: bar
  ports:
  # Default port used by the image
  - port: 8080
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: example-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /\$2
spec:
  rules:
  - http:
      paths:
      - pathType: ImplementationSpecific
        path: /foo(/|$)(.*)
        backend:
          service:
            name: foo-service
            port:
              number: 8080
      - pathType: ImplementationSpecific
        path: /bar(/|$)(.*)
        backend:
          service:
            name: bar-service
            port:
              number: 8080
---
EOF
$ kubectl --context patch configmap/ingress-nginx-controller \
          -n ingress-nginx --type merge \
          -p '{"data":{"worker-processes": "2"}}'
$ kubectl --context kind-kind apply -f /tmp/ingress.yaml