Vibe Engines
YouTube

Vibe Engines is free, interactive AI engineering & system design — runs in your browser. Pick a learning path

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; -A means 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 wide adds 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 -A for 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 app adds 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:.path pairs

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 tar in the image
kubectl run tmp --rm -it --image=busybox -- sh
throwaway pod to test DNS and connectivity from inside; deleted on exit
OOMKilled?
describe shows 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 yaml to 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 apply would change in the live objects
kubectl rollout history deploy/api
list revisions; rollout undo --to-revision=3 returns 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=val or --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 -l selectors

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=cpu works 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-data for 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:name checks 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 -20

Exit 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 app

rollout 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 exit

Service 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-7

Drain 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.