🌐 Detecting your location…

So richten Sie Kubernetes 2026 lokal mit kind und k3d ein: Vollständiger Leitfaden

⏱️6 min read  ·  1,228 words

Der lokale Betrieb von Kubernetes bedeutete früher eine große virtuelle Maschine und lange Wartezeiten. kind undk3d Dies hat sich geändert, indem Cluster als Container ausgeführt wurden, die in Sekundenschnelle starten und im Leerlauf fast nichts kosten. In diesem Leitfaden wird ein funktionierender lokaler Cluster mit Ingress, lokalem Laden von Bildern und einer Entwicklungsschleife eingerichtet, bei der nicht bei jeder Änderung eine Push-Übermittlung an eine Registrierung erforderlich ist.

kind oder k3d: Was soll ich wählen

Beide führen Kubernetes in Docker aus. Sie unterscheiden sich darin, was sie ausführen und wofür sie optimieren.

freundlich k3d
Kubernetes Upstream, unverändert k3s – leichtgewichtig, einige Komponenten ausgetauscht
Startzeit Schnell Schneller
Speichernutzung Höher Unteres
Am besten für Testen gegen echtes Upstream-Verhalten, CI Schnelle Iteration, eingeschränkte Laptops

Wählen Siefreundlich wenn Sie ein Verhalten benötigen, das mit dem Produktions-Upstream-Kubernetes identisch ist, insbesondere zum Testen von Operatoren oder Zulassungscontrollern. Wählen Siek3d wenn Sie die schnellste und leichteste Schleife für die Anwendungsentwicklung wünschen. Beide sind ausgezeichnet; Dieser Leitfaden deckt jedes davon ab.

Voraussetzungen

# Docker must be running
docker version

# kubectl
brew install kubectl        # macOS
# or: curl -LO "https://dl.k8s.io/release/$(curl -Ls https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"

# kind
brew install kind

# k3d
brew install k3d

Option A: Art

Ein Einzelknoten-Cluster ist ein Befehl, aber es lohnt sich, sofort eine Konfigurationsdatei zu schreiben, da der Eingang Portzuordnungen erfordert, die später nicht hinzugefügt werden können, ohne den Cluster neu zu erstellen.

# kind-config.yaml
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: 80
        protocol: TCP
      - containerPort: 443
        hostPort: 443
        protocol: TCP
  - role: worker
  - role: worker
kind create cluster --name dev --config kind-config.yaml

# kubectl context is switched automatically
kubectl cluster-info --context kind-dev
kubectl get nodes

DasextraPortMappings Der Block leitet die Host-Ports 80 und 443 an den Cluster-Knoten weiter, wodurchhttp://localhostentsteht Erreichen Sie Ihren Ingress-Controller. Fügen Sie es im Voraus hinzu – eine Nachrüstung bedeutet, den Cluster zu löschen und neu zu erstellen.

Ingress auf Art

kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/ingress-nginx/main/deploy/static/provider/kind/deploy.yaml

kubectl wait --namespace ingress-nginx \
  --for=condition=ready pod \
  --selector=app.kubernetes.io/component=controller \
  --timeout=90s

Option B: k3d

k3d übernimmt die Portzuordnung und den Eingang mit Flags, sodass die Einrichtung kürzer ist. k3s enthält standardmäßig Traefik als Eingangscontroller.

k3d cluster create dev \
  --agents 2 \
  --port "80:80@loadbalancer" \
  --port "443:443@loadbalancer"

kubectl get nodes

Um ingress-nginx anstelle von Traefik zu verwenden, deaktivieren Sie das gebündelte Paket zum Zeitpunkt der Erstellung.

k3d cluster create dev \
  --agents 2 \
  --port "80:80@loadbalancer" \
  --k3s-arg "--disable=traefik@server:0"

Bereitstellen einer Anwendung

# app.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
spec:
  replicas: 2
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
        - name: web
          image: my-app:dev
          imagePullPolicy: IfNotPresent
          ports:
            - containerPort: 3000
          readinessProbe:
            httpGet:
              path: /healthz
              port: 3000
            initialDelaySeconds: 2
          resources:
            requests:
              cpu: 100m
              memory: 128Mi
            limits:
              memory: 512Mi
---
apiVersion: v1
kind: Service
metadata:
  name: web
spec:
  selector:
    app: web
  ports:
    - port: 80
      targetPort: 3000
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: web
spec:
  ingressClassName: nginx
  rules:
    - host: app.localhost
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: web
                port:
                  number: 80

imagePullPolicy: IfNotPresent ist für die lokale Entwicklung von entscheidender Bedeutung. Der StandardAlways lässt Kubernetes versuchen,my-app:devzu ziehen aus einer Registry, die nicht existiert, und der Pod schlägt mitErrImagePull.

fehl Lokale Bilder laden – der Schritt, den jeder verpasst

Ihr Cluster wird in eigenen Containern mit eigenem Image-Speicher ausgeführt. Ein auf Ihrem Host erstelltes Image ist für ihn unsichtbar, bis Sie es explizit laden.

# Build normally
docker build -t my-app:dev .

# kind
kind load docker-image my-app:dev --name dev

# k3d
k3d image import my-app:dev -c dev

Dann bewerben und prüfen.

kubectl apply -f app.yaml
kubectl get pods -w
curl -H "Host: app.localhost" http://localhost/

Wenn Hülsen inImagePullBackOffsitzen , haben Sie mit ziemlicher Sicherheit den Ladeschritt übersprungen oderimagePullPolicyverlassen in der Standardeinstellung.

Eine schnelle innere Schleife

Das manuelle Neuaufbauen, Laden und erneute Bereitstellen bei jeder Änderung ist zu langsam, um es aufrechtzuerhalten. Zwei Ansätze beheben das Problem.

Neigung oder Gerüst Beobachten Sie Ihre Quelle, erstellen Sie sie neu, laden Sie das Image und aktualisieren Sie die Bereitstellung automatisch.

# Tiltfile
docker_build('my-app', '.')
k8s_yaml('app.yaml')
k8s_resource('web', port_forwards='3000:3000')
tilt up

Portweiterleitung reicht aus, wenn Sie nur einen Dienst ohne Ingress erreichen müssen.

kubectl port-forward svc/web 3000:80
# now http://localhost:3000

Persistente Volumes

Beide Tools liefern eine Standardspeicherklasse aus, sodass ein PersistentVolumeClaim ohne Konfiguration funktioniert.

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: data
spec:
  accessModes: [ReadWriteOnce]
  resources:
    requests:
      storage: 1Gi

Um die Daten auf Ihrem Host zu behalten, damit sie das Löschen des Clusters überstehen, mounten Sie zum Zeitpunkt der Erstellung ein Hostverzeichnis.

# kind-config.yaml
nodes:
  - role: control-plane
    extraMounts:
      - hostPath: /Users/me/k8s-data
        containerPath: /data

Debuggen

# Why is a pod not starting? Events are at the bottom.
kubectl describe pod <pod-name>

# Logs, including from a crashed previous container
kubectl logs <pod-name>
kubectl logs <pod-name> --previous

# Shell into a running container
kubectl exec -it <pod-name> -- sh

# Debug a container with no shell using an ephemeral container
kubectl debug -it <pod-name> --image=busybox --target=web

# Cluster-wide recent events, newest last
kubectl get events --sort-by=.metadata.creationTimestamp

kubectl describe pod ist der erste Befehl, der bei fast jedem Problem ausgeführt wird. Im Abschnitt „Ereignisse“ unten wird deutlich angezeigt, ob das Bild nicht abgerufen werden konnte, dem Knoten Ressourcen fehlten oder eine Prüfung fehlgeschlagen ist.

Aufräumen

# kind
kind delete cluster --name dev

# k3d
k3d cluster delete dev

# k3d can also stop and restart without losing state
k3d cluster stop dev
k3d cluster start dev

Häufige Fehler

Ich habe vergessen, das Bild zu laden. Der Cluster kann die Docker-Images Ihres Hosts nicht sehen. Laden Sie sie explizit.

VerlassenimagePullPolicy in der Standardeinstellung. Mit einem:latest Tag ist der StandardwertAlways, was bei rein lokalen Bildern fehlschlägt.

Portzuordnungen nach der Erstellung hinzufügen. Sie werden bei der Clustererstellung festgelegt. Planen Sie Eingangsports, bevor Sie sie erstellen.

Weglassen von Ressourcenanfragen. Ohne sie kann der Planer keine Überlegungen zur Kapazität anstellen, und lokale Cluster überlasten sich, bis Pods entfernt werden.

Unter der Annahme, dass lokal gleichbedeutend mit Produktion ist. Lokale Cluster verfügen standardmäßig über keinen echten Lastenausgleich, keine Cloud-Speicherklassen und keine Durchsetzung von Netzwerkrichtlinien. Behandeln Sie sie als Entwicklungstool und nicht als Produktionssimulator.

Fazit

Für ein produktives lokales Kubernetes-Setup müssen vier Dinge richtig sein:Erstellen Sie den Cluster mit den Portzuordnungen, die Sie für den Eingang benötigen, laden Sie lokale Bilder explizit in den Cluster und legen SieimagePullPolicy: IfNotPresentfest Daher verfolgt Kubernetes keine Registrierung und automatisiert die Wiederherstellungsschleife mit Tilt oder Skaffold. Verwenden Sie kind, wenn Sie Upstream-identisches Verhalten benötigen, und k3d, wenn Sie die leichteste und schnellste Schleife wünschen. Mit beiden können Sie einen Cluster in Sekundenschnelle löschen und neu erstellen. Das ist der eigentliche Vorteil: Ein defekter lokaler Cluster ist kein Problem mehr, das es wert ist, debuggt zu werden.

MD Rafikul Islam

Written by

MD Rafikul Islam is a software developer and the editor of TechPulse. He writes about developer tooling, hardware, and the practical decisions that come up in day-to-day engineering work — which laptop to buy, which framework to commit to, why a build broke at 2am. He tests the tools he writes about and says plainly when something is not worth the money. Corrections and corrections requests are welcome at rony.yf25@gmail.com.

✍️ Leave a Comment

Your email address will not be published. Required fields are marked *

🌐 Read in:🇬🇧 English🇩🇪 Deutsch🇧🇷 Português🇸🇦 العربية🇮🇳 हिन्दी🇧🇩 বাংলা