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.
📋 Table of Contents
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.
🔗 Share this article
✍️ Leave a Comment