kubectl Quick Reference
The Kubernetes commands you reach for during deploys, debugging and 2am incidents — organized by situation.
kubectl talks to the Kubernetes API server. You declare the state you want — say, a Deployment running three replicas of an image — and controllers keep converging the cluster toward it. So most debugging means comparing the desired spec with the actual status, and reading the events the controllers leave behind.
Commands follow kubectl <verb> <type>/<name> and act on your current context: a cluster, a user and a default namespace. Check it before anything destructive with kubectl config current-context.
Contexts & namespaces
- kubectl config get-contexts
- every cluster/user pair in your kubeconfig;
*marks the current one - kubectl config use-context prod
- switch clusters — where most “oops, wrong cluster” incidents begin
- kubectl config current-context
- print the active context — worth showing in your shell prompt
- kubectl config set-context --current --namespace=app
- change the default namespace for this context
- kubectl -n app get pods
- one namespace for one command;
-Ameans all namespaces - KUBECONFIG=a.yaml:b.yaml
- merge several kubeconfig files for one shell session
- kubectl api-resources
- every resource type, its short name (
po,deploy,svc) and whether it is namespaced
Look around
- kubectl get pods -A
- all pods, all namespaces;
-o wideadds nodes/IPs - kubectl get all -n app
- workloads in one namespace — not ConfigMaps, Secrets, Ingresses or PVCs
- kubectl describe pod X
- THE debugging command — events at the bottom tell the story
- kubectl get events --sort-by=.lastTimestamp
- what just happened in this namespace; add
-Afor the whole cluster - kubectl explain deploy.spec
- built-in schema docs for any field
- -o yaml / -o jsonpath
- full object dump / surgical field extraction
- kubectl get pods -l app=api
- filter by label;
-L appadds that label as a column - kubectl get pods -w
- watch: print changes as they happen
- --field-selector=status.phase!=Running
- filter on fields, e.g. pods that are not Running, or
spec.nodeName=node-1 - -o custom-columns=NAME:.metadata.name
- your own table: comma-separate more
HEADER:.pathpairs
Debug a pod
- kubectl logs X -f
- follow logs;
--previous= the crashed container’s logs (crashloop gold) - kubectl exec -it X -- sh
- shell inside the container
- kubectl debug X -it --image=busybox
- ephemeral debug container for distroless pods
- kubectl port-forward svc/api 8080:80
- poke a cluster service from localhost
- CrashLoopBackOff?
- logs --previous → describe (events) → check probes, memory limits, config
- Pending?
- describe → usually unschedulable: resources, taints, or PVC binding
- kubectl logs -l app=api --tail=100
- logs from every pod with that label — a selector defaults to just 10 lines per pod
- kubectl logs X -c sidecar
- one container of a multi-container pod (otherwise kubectl picks the default one)
- kubectl cp X:/tmp/heap.out ./heap.out
- copy files out of (or into) a container — needs
tarin the image - kubectl run tmp --rm -it --image=busybox -- sh
- throwaway pod to test DNS and connectivity from inside; deleted on exit
- OOMKilled?
describeshows Last State: OOMKilled, exit code 137 — raise the memory limit or fix the leak- ImagePullBackOff?
- wrong image name or tag, or missing
imagePullSecrets— the event message says which
Deploy & rollback
- kubectl apply -f dir/
- declarative apply;
--dry-run=server -o yamlto preview - kubectl rollout status deploy/api
- watch the deploy converge
- kubectl rollout undo deploy/api
- instant rollback to the previous ReplicaSet
- kubectl rollout restart deploy/api
- rolling restart (new pods, same spec) — the config-reload hammer
- kubectl scale deploy/api --replicas=5
- manual scale; HPA does it automatically
- kubectl set image deploy/api api=img:v2
- quick image bump (prefer apply in real life)
- kubectl diff -f dir/
- show what
applywould change in the live objects - kubectl rollout history deploy/api
- list revisions;
rollout undo --to-revision=3returns to a specific one - kubectl apply -k overlays/prod
- apply a kustomize directory — kustomize is built into kubectl
- --dry-run=client -o yaml
- add to any
kubectl create …to print starter YAML instead of creating it - kubectl create secret generic db
- with
--from-literal=key=valor--from-file; values are base64-encoded, not encrypted - kubectl wait --for=condition=Ready pod/X
- block until ready or
--timeout— for scripts and CI; accepts-lselectors
Resources & nodes
- kubectl top pods / nodes
- live CPU/memory (needs metrics-server)
- kubectl cordon / drain node
- stop scheduling / evict for maintenance
- requests vs limits
- requests = scheduling claim · limits = kill threshold (OOMKilled = over memory limit)
- kubectl get pod X -o yaml | grep -A5 resources
- what a pod actually asked for
- kubectl auth can-i delete pods
- RBAC check before the incident, not during
- kubectl top pods --sort-by=memory
- heaviest pods first;
--sort-by=cpuworks too - kubectl describe node N
- “Allocated resources” shows requests vs capacity — why new pods stay Pending
- drain --ignore-daemonsets
- the flag drain almost always needs; add
--delete-emptydir-datafor pods using emptyDir - kubectl uncordon N
- allow scheduling on the node again after maintenance
- kubectl taint nodes N gpu=true:NoSchedule
- only pods tolerating the taint land here; the same command ending in
-removes it - kubectl auth can-i --list
- everything you may do here;
--as=system:serviceaccount:ns:namechecks a service account
Recipes
Debug a CrashLoopBackOff pod
kubectl get pods -n app # STATUS CrashLoopBackOff, RESTARTS climbing
kubectl logs api-7d9f8-x2k4q -n app --previous # output of the container that just died
kubectl describe pod api-7d9f8-x2k4q -n app # Events, and Last State with the exit code
kubectl get events -n app --sort-by=.lastTimestamp | tail -20Exit code 137 with reason OOMKilled is the memory limit; exit 1 with a stack trace is the app itself; no logs at all usually means a bad command or entrypoint, or a failing liveness probe.
Roll out a new image, roll back if it fails
kubectl set image deploy/api api=registry.example.com/api:v2 -n app
kubectl rollout status deploy/api -n app --timeout=120s \
|| kubectl rollout undo deploy/api -n app
kubectl rollout history deploy/api -n approllout status exits non-zero when the timeout passes, which makes it a cheap CI gate. Keep manifests in git as the source of truth — set image drifts from them until the next apply.
Test DNS and connectivity from inside the cluster
kubectl run tmp --rm -it --image=busybox:1.36 --restart=Never -- sh
# inside the pod:
nslookup api.app.svc.cluster.local
wget -qO- http://api.app.svc.cluster.local/healthz
exit # the pod is deleted on exitService names resolve as <service>.<namespace>.svc.cluster.local by default. If DNS works but requests hang, check NetworkPolicies and whether the Service selects any pods: kubectl get endpointslices -n app -l kubernetes.io/service-name=api.
Pull out exactly the fields you need
# pods with the node they run on
kubectl get pods -o custom-columns=NAME:.metadata.name,NODE:.spec.nodeName,PHASE:.status.phase
# one line per deployment: namespace/name: image
kubectl get deploy -A -o jsonpath='{range .items[*]}{.metadata.namespace}/{.metadata.name}: {.spec.template.spec.containers[0].image}{"\n"}{end}'
# decode one secret value
kubectl get secret db -n app -o jsonpath='{.data.password}' | base64 -d{range}…{end} loops with a separator you choose; plain {.items[*].metadata.name} prints everything on one line. Anyone allowed to read a Secret can decode it this way.
Drain a node for maintenance
kubectl cordon node-7 # no new pods land here
kubectl drain node-7 --ignore-daemonsets --delete-emptydir-data
# patch or reboot the node, then:
kubectl uncordon node-7
kubectl get pods -A -o wide --field-selector spec.nodeName=node-7Drain honors PodDisruptionBudgets, so it can stall when a PDB allows no disruption (kubectl get pdb -A). Bare pods with no controller block it unless you add --force — and then they are deleted, not rescheduled.
Questions about kubectl Cheat Sheet
How do I switch namespace in kubectl?
kubectl has no cd command; the default namespace is a field of your current context. Run kubectl config set-context --current --namespace=app and every later command uses app until you change it again. For a single command, pass -n app instead, or -A to cover all namespaces. kubectl config view --minify shows the namespace your context points at. Many people install the small kubens and kubectx helpers, which switch namespaces and clusters with one word, and show the current context in their shell prompt to avoid running commands against the wrong one.
What is the difference between kubectl apply and kubectl create?
kubectl create is imperative: it makes the object and fails if one with that name already exists. kubectl apply is declarative: it creates the object if it is missing and otherwise updates it to match your file, merging with fields that controllers or other tools manage. That is why apply belongs in CI pipelines and GitOps, where the same manifests are applied again and again. Use create for one-off objects and generators, such as create secret, create job from a CronJob, or create with --dry-run=client -o yaml to draft a manifest you then apply.
How do I restart a pod in Kubernetes?
There is no restart verb for pods. For anything managed by a Deployment, StatefulSet or DaemonSet, run kubectl rollout restart on it: Kubernetes replaces the pods gradually, respecting the rollout strategy, so there is no downtime if you have more than one replica. To restart a single pod, delete it with kubectl delete pod and its controller creates a fresh one with a new name. A bare pod with no controller is simply gone once deleted, so recreate it from its manifest. Scaling to zero and back also works, but it causes downtime.
What does CrashLoopBackOff mean?
It means a container keeps starting and then exiting, so the kubelet restarts it with an exponentially growing delay that is capped at five minutes. The status is a symptom, not the cause. Run kubectl logs with --previous to read the output of the run that just crashed, then kubectl describe pod to see the exit code and recent events. Common causes are an application error at startup, a missing environment variable, ConfigMap or Secret, a wrong command, a liveness probe failing too early, and exit code 137, which means the container was killed for exceeding its memory limit.