Zum Hauptinhalt springen

Kubernetes Cluster mit Proxmox VMs

K3s erlaubt mit geringem Aufwand einen hochverfügbaren Kubernetes-Cluster auf Proxmox Virtual Environment (oder vergleichbar) einzurichten. K3s ist eine schlanke Kubernetes-Distribution von Rancher, die sich besonders für Edge-Computing, IoT und Homelab-Umgebungen eignet. Durch den Einsatz von drei Master Nodes in einem HA-Setup mit embedded etcd, einem HAProxy als Load Balancer und mehreren Worker Nodes entsteht eine produktionsnahe Cluster-Architektur, die Ausfallsicherheit bietet.

Es ist ratsam direkt zu Beginn HA für die Master Nodes einzurichten --cluster-init, nachträglich kann dieses Feature nur über ein Backup/Restore hinzugefügt werden.

VM-Anforderungen (Minimum):

  • HAProxy: 1 vCPU, 1 GB RAM, 10 GB Disk
  • Master Nodes: 2 vCPUs, 4 GB RAM, 20 GB Disk
  • Worker Nodes: 2 vCPUs, 2 GB RAM, 20 GB Disk
  • OS: Debian 10 (oder vergleichbar)

Netzwerk:

  • Statische IPs für alle Nodes
  • Offene Ports zwischen den Nodes

Schritt 1: VMs in Proxmox erstellen

  1. VMs erstellen (HAProxy, 3 Master, 3 Worker)
  2. Cloud Init erleichtert das Zuweisen von statischen IPs
  3. Debian installieren
  4. Updates:
sudo apt update && sudo apt upgrade -y

Schritt 2: HAProxy installieren Mittels HAProxy verteilen wir die Zugriffe auf die Master Nodes. Diese werden dank der Einrichtung als Cluster Node gleichwertig, da die ==Embedded etcd== automatisch synchronisiert wird. Das ist die einfachste unterstützte HA-Architektur, alternativ könnte eine externe Datenbank (PostgreSQL/MySQL) Verwendung finden.

sudo apt install -y haproxy
MASTER1_IP="192.168.201.1"
MASTER2_IP="192.168.201.2"
MASTER3_IP="192.168.201.3"

cat <<EOF >> /etc/haproxy/haproxy.cfg

frontend k3s-api
    bind *:6443
    mode tcp
    default_backend k3s-masters
backend k3s-masters
    mode tcp
    balance roundrobin
    server master1 ${MASTER1_IP}:6443 check
    server master2 ${MASTER2_IP}:6443 check
    server master3 ${MASTER3_IP}:6443 check

EOF

Konfiguration auf Syntax-Fehler prüfen, ==WARNING option httplog== kann ignoriert werden:

haproxy -c -f /etc/haproxy/haproxy.cfg

Konfiguration anwenden:

sudo systemctl reload haproxy

Schritt 3: Master Node installieren Auf dem ersten Master Node K3s als Master installieren:

HAPROXY_IP="192.168.201.0"

curl -sfL https://get.k3s.io | sh -s - server \
  --cluster-init \
  --tls-san=${HAPROXY_IP}

Node-Token für weitere Nodes abrufen:

sudo cat /var/lib/rancher/k3s/server/node-token

Ebenfalls Master2 und Master3 als Master Node installieren:

MASTER1_IP="192.168.201.1"
NODE_TOKEN="K10cf9d2625abcde0a83a53bc4f02192f3fcb4cc8d730ef4e248e023251bbd08139::server:7ba73ceb7480ee96763c43554819976b"

curl -sfL https://get.k3s.io | sh -s - server \
  --server https://${MASTER1_IP}:6443 \
  --token ${NODE_TOKEN}

Schritt 4: Worker Nodes hinzufügen Auf jedem Worker Node wie folgt installieren:

HAPROXY_IP="192.168.201.0"
NODE_TOKEN="K10cf9d2625abcde0a83a53bc4f02192f3fcb4cc8d730ef4e248e023251bbd08139::server:7ba73ceb7480ee96763c43554819976b"

curl -sfL https://get.k3s.io | K3S_URL=https://${HAPROXY_IP}:6443 K3S_TOKEN=${NODE_TOKEN} sh -

Schritt 5: Cluster verifizieren Auf dem Master:

sudo kubectl get nodes

Der Cluster ist nun einsatzbereit.


Zur Verwaltung wird kubectl benötigt, nachfolgend die Einrichtung auf MacOS:

MASTER1_IP="192.168.201.1"
brew install kubectl

mkdir ~/.kube

scp root@${MASTER1_IP}:/etc/rancher/k3s/k3s.yaml ~/.kube/config

# Berechtigungen setzen
sudo chown $USER:$USER ~/.kube/config
chmod 600 ~/.kube/config

# IP anpassen, HAProxy IP eintragen
code ~/.kube/config

kubectl get pods --all-namespaces

Load Balancer

  1. MetalLB ausrollen
METALLB_VERSION=$(curl -s https://api.github.com/repos/metallb/metallb/releases/latest | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/')

kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/"${METALLB_VERSION}"/config/manifests/metallb-native.yaml
  1. Warten bis Pods laufen
kubectl wait --namespace metallb-system --for=condition=ready pod -l app=metallb
  1. IP-Pool konfigurieren
IP_POOL="192.168.202.1-192.168.202.254"

cat <<EOF | kubectl apply -f -
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: default-pool
  namespace: metallb-system
spec:
  addresses:
  - ${IP_POOL}
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
  name: default
  namespace: metallb-system
spec:
  ipAddressPools:
  - default-pool
EOF

Test Anwendung ausrollen:

# 1. Nginx Deployment erstellen
kubectl create deployment nginx-test --image=nginx --replicas=2

# 2. Als Service verfügbar machen
kubectl expose deployment nginx-test --port=80 --type=LoadBalancer

# 3. Status prüfen
kubectl get deployments
kubectl get pods -o wide
kubectl get svc nginx-test

Testen via Browser oder curl

EXTERNAL_IP="192.168.202.2"

curl http://"${EXTERNAL_IP}"

Außerdem (by Design) ist die Anwendung auf allen IPs der Master und Agents erreichbar, dort aber nur via NODEPORT.

Test Anwendung entfernen:

kubectl delete service nginx-test
kubectl delete deployment nginx-test