kubectl Cheatsheet

kubectl CheatsheetAlle Kapitel

kubectl Cheatsheet im Volltext

Stand kubectl 1.37 · Edition 2026.11

Cheatsheet im Volltext

Derselbe Inhalt wie im PDF, zum Mitlesen, Durchsuchen und direkten Kopieren der Snippets. Stand: Kubernetes/kubectl v1.37 (Edition 2026.11).

Kontexte & kubeconfig

Kontext = Cluster + User + Namespace

kubectl config get-contexts zeigt alle, use-context wechselt, set-context --current setzt den Default-Namespace.

Merge: KUBECONFIG nimmt eine Pfad-Liste (:-getrennt), erste Definition gewinnt. config view --flatten schreibt daraus eine Datei. --kubeconfig pinnt pro Aufruf.

Version-Skew

kubectl ist innerhalb einer Minor-Version (älter oder neuer) zum kube-apiserver supported: ein v1.37-Client deckt v1.36 bis v1.38 ab. Bei HA-Clustern mit gemischten API-Server-Versionen wird das Fenster enger. kubectl version zeigt beide Seiten, bei Cluster-Flotten mit Versions-Spread den Client bewusst wählen.

kuberc: CLI-Verhalten, nicht Cluster-Zugriff

~/.kube/kuberc (Beta seit v1.34, Pfad per KUBERC oder --kuberc) hält Aliase und Default-Flags getrennt von der kubeconfig. credentialPluginPolicy: Allowlist begrenzt, welche exec-Credential-Plugins laufen dürfen. KUBERC=off schaltet die Datei ab, etwa in CI.

kubectl config get-contexts
kubectl config use-context prod-admin
kubectl config set-context --current --namespace=payments
export KUBECONFIG=~/.kube/prod.yaml:~/.kube/lab.yaml
kubectl config view --flatten > ~/.kube/merged.yaml
kubectl version   # Client- vs. Server-Version (Skew)
kubectl kuberc set --section defaults --command delete \
  --option interactive=true

Output-Formate

-o: von wide bis go-template

-o wide|yaml|json|name für den Alltag.

kyaml (stable seit v1.37): strikte YAML-Teilmenge, nicht whitespace-sensitiv, String-Werte immer quotiert (kein no → false), Maps und Listen in {}/[].

jsonpath: Feld-Extraktion mit range/Filter, Script-Futter statt grep-Kaskaden. custom-columns: eigene Tabellen direkt aus dem API-Objekt. go-template: volle Template-Logik inkl. base64decode für Secrets.

Sortieren & Filtern

--sort-by nimmt einen JSONPath. -l filtert nach Labels (app=web,tier!=cache), --field-selector nach Objektfeldern (status.phase=Running). -A = alle Namespaces.

kubectl get pods -o jsonpath='{.items[*].spec.containers[*].image}'
kubectl get pods -o jsonpath='{range .items[*]}{.metadata.name} {.status.podIP}{"\n"}{end}'
cols='NAME:.metadata.name,TAINT:.spec.taints[*].key'
kubectl get nodes -o custom-columns="$cols"
kubectl get secret db -o go-template='{{index .data "ca.crt" | base64decode}}'
kubectl get pods -A --sort-by=.metadata.creationTimestamp
kubectl get deploy web -o kyaml

Apply, Diff & Server-Side Apply

diff & dry-run

kubectl diff -f zeigt den Diff gegen den Live-Stand vor dem Apply (Exit-Code 1 = Unterschiede, CI-tauglich).

--dry-run=client sendet keinen Schreib-Request und fängt deshalb keine falschen Feldnamen ab, die Feldvalidierung macht der API-Server; --dry-run=server lässt Admission-Webhooks + Defaulting am API-Server laufen, ohne zu persistieren, das ehrlichere Preflight.

Server-Side Apply, Field-Ownership

apply --server-side (GA seit v1.22) merged am API-Server. Ownership steht pro Feld in metadata.managedFields, jeder Writer trägt einen --field-manager.

Conflict (HTTP 409), wenn ein anderer Manager das Feld hält: --force-conflicts übernimmt die Ownership, bewusst einsetzen, das entzieht dem anderen Controller das Feld.

kubectl diff -f deploy.yaml
kubectl apply -f deploy.yaml --dry-run=server
kubectl apply --server-side --field-manager=ci -f deploy.yaml
kubectl apply --server-side --force-conflicts -f deploy.yaml
kubectl get deploy web --show-managed-fields -o yaml

Patch-Strategien

strategic, merge, json

strategic (Default): kennt Merge-Keys aus dem Schema, patcht z.B. containers per name statt die Liste zu ersetzen.

--type=merge (RFC 7386): simpel, aber Listen werden komplett ersetzt. --type=json (RFC 6902): Op-Liste (add/replace/remove) mit präzisen Pfaden.

CRDs: kein strategic-Support, merge oder json verwenden.

--subresource (stable seit v1.33) mit status, scale oder resize bei get/patch/edit/replace und apply --server-side; resize ändert Pod-Ressourcen in place (GA seit v1.35).

kubectl patch deploy web -p '{"spec":{"replicas":4}}'
kubectl patch deploy web --type=merge \
  -p '{"metadata":{"labels":{"team":"pay"}}}'
kubectl patch deploy web --type=json -p '[{"op": "replace",
  "path": "/spec/template/spec/containers/0/image",
  "value": "web:2.0"}]'
kubectl patch pod api --subresource=resize -p \
  '{"spec":{"containers":[{"name":"api",
  "resources":{"requests":{"cpu":"500m"}}}]}}'

Debug & Ephemeral Containers

Pod-Debug, distroless-tauglich

kubectl debug -it pod/x --image=... hängt einen Ephemeral Container an (stable seit v1.25), Debug-Tools für Images ohne Shell. --target teilt den Prozess-Namespace des Ziel-Containers.

Ephemeral Containers sind nicht entfernbar; aufräumen heißt Pod löschen. Alternativ --copy-to=dbg (teilt den Prozess-Namespace per Default): Kopie debuggen, Original bleibt unangetastet.

Node-Debug & Profile

kubectl debug node/<n> startet einen Pod auf dem Node, Host-Dateisystem unter /host. Der Pod bleibt danach stehen, von Hand löschen.

--profile steuert die Rechte: general (Default seit v1.36), baseline, restricted, netadmin, sysadmin; legacy ist deprecated (Removal geplant für v1.39).

kubectl debug -it pod/api --image=nicolaka/netshoot --target=api
kubectl debug pod/api --copy-to=api-dbg -it --image=busybox
kubectl debug node/worker-3 -it --image=busybox --profile=sysadmin
chroot /host   # im Node-Debug-Pod

Rollout

status, history, undo

rollout status blockt bis Ready bzw. progressDeadline, das Gate für Pipelines. history listet Revisionen (--revision=N zeigt Details; CHANGE-CAUSE kommt aus der Annotation kubernetes.io/change-cause).

undo --to-revision=N rollt gezielt zurück. restart erzwingt ein neues Rollout (z.B. nach ConfigMap-Änderung). Gilt für Deployments, DaemonSets, StatefulSets; pause/resume nur für Deployments.

kubectl rollout status deploy/web --timeout=120s
kubectl rollout history deploy/web --revision=3
kubectl rollout undo deploy/web --to-revision=2
kubectl rollout restart deploy/web
kubectl rollout pause deploy/web   # und: resume

Auth, Events & Wait

can-i, whoami

auth can-i prüft RBAC vor dem Incident; --as / --as-group testet fremde Identitäten (ServiceAccounts als system:serviceaccount:<ns>:<sa>). --list zeigt alle Rechte im Namespace.

auth whoami (GA seit v1.28, SelfSubjectReview-API): UserInfo inkl. Gruppen, wie der API-Server sie nach Authentifizierung sieht.

events, top, wait

kubectl events --for pod/x --types=Warning: chronologisch, gefiltert, ergonomischer als get events + --sort-by. top pod|node braucht den metrics-server.

wait --for=condition=..., =create, =delete oder =jsonpath=...: deklaratives Warten mit --timeout statt sleep-Schleifen. Mehrere --for werden seit v1.36 UND-verknüpft.

kubectl auth can-i create deploy -n prod
kubectl auth can-i --list -n prod
kubectl auth can-i get secrets --as system:serviceaccount:ci:builder
kubectl auth whoami
kubectl events --for pod/api --types=Warning
kubectl top pods --containers -n prod
kubectl wait --for=condition=Ready pod -l app=web --timeout=90s
kubectl wait --for=create --for=condition=Ready pod/web-0

Port-Forward, Exec & cp

port-forward, exec, proxy, cp

port-forward tunnelt über den API-Server, kein Ingress, kein NodePort nötig; svc/x pinnt beim Start einen Pod dahinter, kein Load-Balancing, der Tunnel endet mit diesem Pod. --address ist per Default localhost; 0.0.0.0 öffnet den Tunnel fürs Netz.

proxy legt die REST-API authentifiziert auf 127.0.0.1:8001, zum Explorieren und für curl-Debugging. cp braucht ein tar-Binary im Container, bei distroless nicht vorhanden. Unter Windows schreibt cp aus einem manipulierten Container beliebige lokale Pfade (CVE-2026-19444), behoben ab v1.34.12, v1.35.9 und v1.36.5, v1.37 ist nicht betroffen.

exec verlangt seit v1.35 -- vor dem Kommando, die alte Form bricht mit Fehler ab.

kubectl port-forward svc/web 8080:80
kubectl port-forward pod/db 15432:5432   # lokal:remote
kubectl proxy --port=8001 &
curl localhost:8001/api/v1/namespaces/prod/pods
kubectl cp prod/api-6d5f7:/var/log/app.log ./app.log
kubectl exec -it deploy/web -c app -- sh

Explain, Kustomize & Plugins

explain & API-Discovery

explain deploy.spec.strategy: Feld-Doku aus dem OpenAPI-Schema des Clusters, inkl. CRDs. --recursive zeigt den ganzen Teilbaum, --max-depth=N (seit v1.37) kappt ihn, --api-version pinnt die Version.

api-resources / api-versions: was der Cluster kann, inkl. Shortnames.

Kustomize (-k)

Kustomize ist in kubectl integriert: apply|diff|delete -k <dir> rendert Base + Overlay und wendet an; kubectl kustomize <dir> rendert nur. Eingebettete Version: kubectl version --client (v1.37: Kustomize v5.8.1); GitOps-Controller rendern mit ihrer eigenen.

Plugins & Krew

Jedes Binary kubectl-<name> im PATH wird Subcommand; kubectl plugin list zeigt sie.

Plugin-Manager: Krew (kubernetes-sigs) mit krew search|install|upgrade, über 400 Plugins im Index. Die Plugins sind nicht auf Sicherheit geprüft, eingebaute Kommandos überschreiben können sie nicht.

kubectl explain deploy.spec --recursive --max-depth=2
kubectl api-resources --namespaced=false
kubectl kustomize overlays/prod | kubectl diff -f -
kubectl apply -k overlays/prod
kubectl krew install ctx ns tree

Completion & Alias

kubectl completion bash|zsh|fish|powershell erzeugt das Completion-Skript, unter bash mit dem Paket bash-completion. Unter zsh greift es auch für einen Alias, unter bash braucht der Alias eine eigene complete-Zeile.

source <(kubectl completion bash)
alias k=kubectl
complete -o default -F __start_kubectl k

Fehlerbilder & erste Kommandos

STATUS ist nicht Phase

Die STATUS-Spalte von get pods ist eine Anzeige: CrashLoopBackOff oder Terminating sind keine Phase, status.phase bleibt etwa Running. Erster Blick: describe pod. describe zeigt Events seit v1.36 nur beim Einzelobjekt, für mehrere --show-events.

CrashLoopBackOff: Neustart mit Backoff 10 s, 20 s, 40 s bis 5 min; logs --previous zeigt den Absturz. OOMKilled steht nach dem Neustart in lastState.terminated.reason. ImagePullBackOff: das Event nennt die Registry-Antwort. Pending: ist der Pod noch nicht eingeplant, nennt FailedScheduling den Grund.

kubectl get pods -A --field-selector=status.phase=Pending
kubectl describe pod api-7c9f
kubectl events -n prod --types=Warning
kubectl get pod api-7c9f -o jsonpath=\
'{.status.containerStatuses[*].lastState.terminated.reason}'
kubectl debug pod/api-7c9f -it --copy-to=api-dbg \
  --container=app -- sh

Logs

Was logs liefert

--previous: die zuletzt beendete Instanz, der kubelet hält per Default eine vor. Nach Eviction oder Pod-Löschung sind die Logs weg; nach Rotation liefert logs nur die jüngste Datei.

deploy/web liest einen Pod, --all-pods alle (setzt --prefix). Mit -l ist --tail per Default 10, ohne Selektor alles. -f über mehr als 5 Container-Streams bricht ab, --max-log-requests hebt das Limit.

kubectl logs api-7c9f -c app --previous
kubectl logs deploy/web --all-pods --since=15m
kubectl logs -l app=web --tail=200 --prefix
kubectl logs -f -l app=web --max-log-requests=10
kubectl logs api-7c9f --timestamps \
  --since-time=2026-10-30T06:00:00Z

Node-Wartung

cordon, drain, uncordon

cordon sperrt den Node für neue Pods, laufende bleiben. drain = cordon + Eviction aller Pods außer Mirror- und DaemonSet-Pods. Abbruch, wenn --ignore-daemonsets (DaemonSet-Pods), --delete-emptydir-data (emptyDir-Daten gehen verloren) oder --force (Pods ohne Controller kommen nicht wieder) fehlt.

Eviction respektiert PodDisruptionBudgets: die API antwortet 429, drain versucht es weiter. --timeout ist per Default 0, also unbegrenzt, in Pipelines setzen. --disable-eviction löscht per DELETE und umgeht PDBs.

taint: NoSchedule wirkt nur auf neue Pods, NoExecute evictet laufende ohne Toleration, key- entfernt alle Taints mit diesem Key.

kubectl cordon worker-3
kubectl drain worker-3 --ignore-daemonsets \
  --delete-emptydir-data --timeout=15m
kubectl get pdb -A   # ALLOWED DISRUPTIONS 0 blockt
kubectl uncordon worker-3
kubectl taint nodes worker-3 maint=true:NoSchedule
kubectl taint nodes worker-3 maint-

Manifeste erzeugen & ändern

Generator statt Handarbeit

create … --dry-run=client -o yaml erzeugt ein Gerüst ohne Cluster-Kontakt. Ein Secret steht darin nur base64-kodiert, nicht verschlüsselt. Per Pipe an kubectl apply -f - wiederholbar anlegen oder aktualisieren.

create job --from=cronjob/x startet einen CronJob sofort. create token holt ein kurzlebiges ServiceAccount-Token, der Server darf die Laufzeit abweichend setzen.

set image/set env ändern das Pod-Template eines Workloads und lösen ein Rollout aus. label/annotate brauchen --overwrite für bestehende Keys, key- löscht.

kubectl create deploy web --image=web:2.0 --replicas=2 \
  --dry-run=client -o yaml > deploy.yaml
kubectl create secret generic db --from-env-file=db.env \
  --dry-run=client -o yaml | kubectl apply -f -
kubectl create job backup-now --from=cronjob/backup
kubectl create token ci-deployer --duration=10m
kubectl set image deploy/web app=web:2.1
kubectl label pod api-7c9f team=pay --overwrite

API-Zugriff & Credential-Plugins

Verbosity & Rohzugriff

-v=6 zeigt Methode, URL, Status und Latenz jedes Requests, -v=7 die Header, -v=8 und -v=9 auch die Bodies, gekürzt auf 1 bzw. 10 KiB. Ab -v=8 können Secret-Inhalte in der Ausgabe stehen, nicht in Tickets kopieren.

get --raw ruft beliebige API-Pfade mit der Auth aus der kubeconfig auf. --request-timeout ist per Default 0, also ohne Timeout.

exec-Credential-Plugins

users[].user.exec startet ein Binary, das ein ExecCredential liefert (OIDC, Cloud-Anbieter). Mit client.authentication.k8s.io/v1 ist interactiveMode Pflicht: Never, IfAvailable oder Always. Welche Plugins laufen dürfen, begrenzt kuberc.

kubectl get pods -v=6
kubectl get --raw='/readyz?verbose' --request-timeout=5s
kubectl config set-credentials sso \
  --exec-api-version=client.authentication.k8s.io/v1 \
  --exec-command=cred-helper --exec-interactive-mode=Never

Anti-Patterns

Was du nicht tun solltest

edit in Prod: unversionierter Live-Drift; der nächste Apply/GitOps-Sync überschreibt still. Änderung ins Repo, dann apply.

delete --force --grace-period=0: entfernt nur das API-Objekt, der Prozess kann am Node weiterlaufen, bei StatefulSets Risiko doppelter Identitäten.

Apply-Modi mischen: der Wechsel client-side → server-side ist nur mit dem Default-Manager kubectl konfliktfrei. Felder, die per scale/edit statt Apply gesetzt wurden, und ein eigener --field-manager laufen bei abweichenden Werten in Conflicts. Pro Objekt einen Modus und einen Manager festlegen.

:latest + rollout restart als Deployment-Ersatz: nicht reproduzierbar, kein Rollback-Ziel; stattdessen unveränderliche Tags oder Digests.

Blind im falschen Kontext: destruktive Kommandos ohne config current-context-Check; Prod-Kontexte explizit benennen und im Prompt markieren.

scale gegen HPA: der Autoscaler setzt den Wert zurück, Min/Max am HPA ändern statt manuell zu skalieren.