Mr.PlanB Logo

    Newsletter

    Newsletter abonnieren

    Neue Infrastruktur-Guides, Vergleichsberichte und Migrationshinweise direkt ins Postfach.

    Infrastruktur-Notizen, Guides und neue Tools. Jederzeit abbestellbar.

    Zurück zum Blog
    Kubernetes
    K3s
    Tutorial

    Einen Kubernetes-Cluster im eigenen Homelab einrichten

    10. Januar 2024
    12 Min. Lesezeit

    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

    1. Von der Ubuntu-Server-ISO booten
    2. Den Installationsassistenten durchlaufen
    3. OpenSSH-Server installieren
    4. 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.

    Ressourcen