# Kubernetes auf podman mit kind

Über das Tool [`kind`](https://kind.sigs.k8s.io/) ist es möglich schnell einen [Kubernetes](..) Cluster innerhalb einer `podman` Umgebung aufzusetzen.

## Vorbereitung

Dazu muss das Tool [heruntergeladen](https://kind.sigs.k8s.io/docs/user/quick-start/#installing-from-release-binaries) oder über das [Paketmanagement installiert](https://kind.sigs.k8s.io/docs/user/quick-start/#installing-with-a-package-manager).

[podman](https://podman.io/) und auch [kubectl](https://kubernetes.io/de/docs/tasks/tools/install-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.

```bash
$ 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.

```bash
$ 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:

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

```yaml
# 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.

```bash
$ 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](https://kind.sigs.k8s.io/docs/user/quick-start/#advanced) Konfiguration zu finden.

## Cluster entfernen

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

```bash
$ 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.

```bash
$ 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
```
