
Einen Kubernetes-Cluster im eigenen Homelab einrichten
Kubernetes im eigenen Homelab zu betreiben, ist eine hervorragende Möglichkeit, Container-Orchestrierung zu lernen, Anwendungen zu testen und produktionsreife Fähigkeiten aufzubauen. In diesem Leitfaden stellen wir einen K3s-Cluster auf Proxmox mit mehreren Nodes und Hochverfügbarkeit bereit.
Warum K3s?
K3s ist eine leichtgewichtige Kubernetes-Distribution und passt damit gut ins Homelab. Sie verbraucht nur 512 MB RAM, kommt als einzelne Binärdatei ohne komplexe Abhängigkeiten, ist zu 100 % kompatibel mit Upstream-Kubernetes und bringt Traefik, CoreDNS und lokalen Storage schon mit.
Architekturübersicht
Wir erstellen einen 3-Node-Cluster: 1 Control-Plane-Node verwaltet den Cluster, und 2 Worker-Nodes führen die Anwendungs-Workloads aus.
┌─────────────────┐
│ Control Plane │
│ 192.168.1.10 │
└────────┬────────┘
│
┌────┴────┐
│ │
┌───▼───┐ ┌──▼────┐
│Worker1│ │Worker2│
│ .11 │ │ .12 │
└───────┘ └───────┘
Voraussetzungen
- Proxmox VE installiert und konfiguriert
- 3 VMs oder LXC-Container (Ubuntu 22.04 empfohlen)
- Mindestens 2 GB RAM pro Node (4 GB empfohlen)
- 2 CPU-Kerne pro Node
- 20 GB Storage pro Node
Die Nodes vorbereiten
VMs in Proxmox erstellen
Erstellen Sie für jeden Node eine VM mit diesen Einstellungen in Proxmox:
# CPU: 2 cores
# RAM: 4GB
# Disk: 20GB
# Network: Bridge to vmbr0
Ubuntu Server installieren
- Von der Ubuntu-Server-ISO booten
- Den Installationsassistenten durchlaufen
- OpenSSH-Server installieren
- Das System aktualisieren:
sudo apt update && sudo apt upgrade -y
Statische IP-Adressen konfigurieren
Bearbeiten Sie die Datei /etc/netplan/00-installer-config.yaml wie folgt:
network:
version: 2
ethernets:
ens18:
addresses:
- 192.168.1.10/24 # Change for each node
gateway4: 192.168.1.1
nameservers:
addresses: [192.168.1.1, 8.8.8.8]
Danach wenden Sie die neue Netzwerkkonfiguration auf dem jeweiligen Node an:
sudo netplan apply
Swap deaktivieren
Kubernetes erfordert, dass Swap deaktiviert ist:
sudo swapoff -a
sudo sed -i '/ swap / s/^/#/' /etc/fstab
Hostnamen konfigurieren
Setzen Sie anschließend für jeden Node einen eindeutigen Hostnamen:
# Control plane
sudo hostnamectl set-hostname k3s-master
# Worker nodes
sudo hostnamectl set-hostname k3s-worker1
sudo hostnamectl set-hostname k3s-worker2
Aktualisieren Sie danach die Datei /etc/hosts auf allen drei Nodes:
192.168.1.10 k3s-master
192.168.1.11 k3s-worker1
192.168.1.12 k3s-worker2
K3s installieren
Control Plane installieren
Führen Sie auf dem Master-Node den folgenden Installationsbefehl aus:
curl -sfL https://get.k3s.io | sh -s - server \
--write-kubeconfig-mode 644 \
--disable traefik \
--node-name k3s-master
Hinweis: Wir deaktivieren Traefik hier, um es später manuell mit eigener Konfiguration zu installieren.
Prüfen Sie anschließend auf dem Master-Node, ob die Installation sauber durchgelaufen ist:
sudo kubectl get nodes
Holen Sie sich dann das Node-Token, das die Worker zum Beitritt brauchen:
sudo cat /var/lib/rancher/k3s/server/node-token
Speichern Sie dieses Token; Sie benötigen es für die Worker-Nodes.
Worker-Nodes installieren
Führen Sie auf jedem Worker-Node den folgenden Befehl aus:
curl -sfL https://get.k3s.io | K3S_URL=https://192.168.1.10:6443 \
K3S_TOKEN=YOUR_NODE_TOKEN \
sh -s - agent \
--node-name k3s-worker1 # Change for each node
Ersetzen Sie dabei YOUR_NODE_TOKEN durch das Token, das Sie vom Master-Node kopiert haben.
Cluster überprüfen
Fragen Sie auf dem Master-Node den Zustand des Clusters ab:
kubectl get nodes
Sie sollten alle drei Nodes im Zustand „Ready" sehen:
NAME STATUS ROLES AGE VERSION
k3s-master Ready control-plane,master 5m v1.27.3+k3s1
k3s-worker1 Ready <none> 2m v1.27.3+k3s1
k3s-worker2 Ready <none> 2m v1.27.3+k3s1
kubectl-Zugriff konfigurieren
Zugriff von der lokalen Maschine
Kopieren Sie zuerst die kubeconfig vom Master-Node auf Ihre Arbeitsmaschine:
# On master node
sudo cat /etc/rancher/k3s/k3s.yaml
Legen Sie den Inhalt danach auf Ihrer lokalen Maschine ab:
mkdir -p ~/.kube
# Paste the content and update the server IP
nano ~/.kube/config
Ändern Sie dabei den Eintrag server: https://127.0.0.1:6443 in server: https://192.168.1.10:6443, damit der Zugriff über das Netzwerk läuft.
Testen Sie die Verbindung anschließend von Ihrer lokalen Maschine aus:
kubectl get nodes
Wichtige Komponenten installieren
Helm-Paketmanager
Installieren Sie Helm auf der lokalen Maschine, von der aus Sie den Cluster verwalten:
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
MetalLB Load Balancer
MetalLB liefert die LoadBalancer-Unterstützung, die auf Bare Metal sonst fehlt:
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml
Erstellen Sie danach die Konfiguration für den IP-Pool, aus dem MetalLB Adressen vergibt:
# metallb-config.yaml
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: default
namespace: metallb-system
spec:
addresses:
- 192.168.1.200-192.168.1.250
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
name: default
namespace: metallb-system
spec:
ipAddressPools:
- default
Wenden Sie die Datei anschließend auf den Cluster an:
kubectl apply -f metallb-config.yaml
Traefik Ingress Controller
Traefik übernimmt das Ingress-Routing und kommt hier per Helm in den Cluster:
helm repo add traefik https://traefik.github.io/charts
helm repo update
helm install traefik traefik/traefik \
--namespace traefik \
--create-namespace \
--set service.type=LoadBalancer
Fragen Sie danach die LoadBalancer-IP ab, die Traefik zugewiesen bekommen hat:
kubectl get svc -n traefik
Cert-Manager
Cert-Manager kümmert sich um die automatische Ausstellung von TLS-Zertifikaten:
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.13.3/cert-manager.yaml
Longhorn Storage
Longhorn liefert verteilten Block-Storage für die Workloads im Cluster:
helm repo add longhorn https://charts.longhorn.io
helm repo update
helm install longhorn longhorn/longhorn \
--namespace longhorn-system \
--create-namespace
Die Longhorn-UI erreichen Sie über einen Port-Forward auf Ihre lokale Maschine:
kubectl -n longhorn-system port-forward svc/longhorn-frontend 8080:80
Öffnen Sie danach im Browser die Adresse http://localhost:8080, um die Oberfläche zu sehen.
Eine Testanwendung bereitstellen
Erstellen Sie zum Prüfen des Clusters ein kleines Test-Deployment mit Service:
# nginx-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-demo
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
type: LoadBalancer
selector:
app: nginx
ports:
- port: 80
targetPort: 80
Bringen Sie das Deployment danach auf den Cluster und prüfen Sie den Service:
kubectl apply -f nginx-deployment.yaml
kubectl get svc nginx-service
Greifen Sie über die LoadBalancer-IP auf die Anwendung zu.
Monitoring mit Prometheus
Für Metriken und fertige Dashboards installieren Sie anschließend den kube-prometheus-stack:
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update
helm install prometheus prometheus-community/kube-prometheus-stack \
--namespace monitoring \
--create-namespace
Grafana erreichen Sie danach ebenfalls über einen Port-Forward auf Ihre lokale Maschine:
kubectl port-forward -n monitoring svc/prometheus-grafana 3000:80
Die Standard-Zugangsdaten für die Anmeldung lauten admin und prom-operator.
Best Practices
Resource Limits
Setzen Sie für jeden Container immer Resource Requests und Limits:
resources:
requests:
memory: "64Mi"
cpu: "250m"
limits:
memory: "128Mi"
cpu: "500m"
Namespace-Organisation
Verwenden Sie Namespaces, um die Workloads im Cluster sauber zu trennen:
kubectl create namespace production
kubectl create namespace development
Backup-Strategie
Für regelmäßige Backups des Clusters richten Sie Velero ein:
helm repo add vmware-tanzu https://vmware-tanzu.github.io/helm-charts
helm install velero vmware-tanzu/velero \
--namespace velero \
--create-namespace
Troubleshooting
Pod startet nicht
kubectl describe pod POD_NAME
kubectl logs POD_NAME
Node nicht bereit
kubectl describe node NODE_NAME
sudo systemctl status k3s
sudo journalctl -u k3s -f
Netzwerkprobleme
kubectl get pods -n kube-system
kubectl logs -n kube-system COREDNS_POD
Nächste Schritte
- GitOps mit ArgoCD implementieren
- CI/CD-Pipelines einrichten
- Horizontales Pod-Autoscaling konfigurieren
- Network Policies implementieren
- Service Mesh bereitstellen (Istio/Linkerd)
Fazit
Damit läuft ein voll funktionsfähiger Kubernetes-Cluster in Ihrem Homelab, mit Load Balancer, Ingress, Zertifikaten, Storage und Monitoring. Das ist eine solide Grundlage, um mit Cloud-native-Technologien zu lernen und zu experimentieren.