kubectl Cheat Sheet
Grouped by what you are trying to find out, not alphabetically — because at 3am you know the question, not the flag.
Which command do I want?#
What do I need to know?
│
├─ "what is running?" → kubectl get
├─ "why is it broken?" → kubectl describe → kubectl logs
├─ "what is it using?" → kubectl top
├─ "what changed?" → kubectl get events / rollout history
├─ "can I get inside it?" → kubectl exec / debug
└─ "can I reach it locally?" → kubectl port-forward
Setup — do these once#
# Shorten it. Everyone does this.
alias k=kubectl
# Tab completion (bash — use ~/.zshrc and zsh for zsh)
echo 'source <(kubectl completion bash)' >> ~/.bashrc
echo 'complete -o default -F __start_kubectl k' >> ~/.bashrc
# Stop typing -n every time
kubectl config set-context --current --namespace=productionWhat is running?#
| Command | Shows |
|---|---|
kubectl get pods | Pods in the current namespace |
kubectl get pods -A | Every namespace — use when you can't find something |
kubectl get pods -o wide | Adds pod IP and node |
kubectl get pods -w | Watch live as statuses change |
kubectl get pods -l app=web | Only pods with that label |
kubectl get all | Most object types here |
kubectl get nodes | The machines. All should be Ready |
kubectl api-resources | Every object type available, with short names |
# Sort by restarts — finds the unstable pod instantly
kubectl get pods --sort-by='.status.containerStatuses[0].restartCount'
# Sort by age, newest last
kubectl get pods --sort-by=.metadata.creationTimestamp
# Only pods that are NOT running
kubectl get pods --field-selector=status.phase!=Running -AWhy is it broken?#
kubectl describe pod <pod> # THE first command. Read the Events at the bottom
kubectl logs <pod> # what the app printed
kubectl logs <pod> -f # follow
kubectl logs <pod> --previous # the CRASHED container — essential for CrashLoopBackOff
kubectl logs <pod> -c <container> # multi-container pods
kubectl logs <pod> --tail=100
kubectl logs -l app=web --all-containers --tail=50 # across every matching pod# Cluster-wide events, newest last. When several things break at once,
# this often reveals the single cause.
kubectl get events -A --sort-by=.lastTimestamp | tail -30
# Only warnings
kubectl get events -A --field-selector type=WarningGetting inside#
kubectl exec -it <pod> -- sh # or bash, if the image has it
kubectl exec -it <pod> -c <container> -- sh
kubectl exec <pod> -- env # run one command, no shell
kubectl exec <pod> -- cat /etc/config/app.yaml
# Distroless / scratch image with no shell? Attach a debug container that
# shares the target's namespaces and brings its own tools.
kubectl debug -it <pod> --image=busybox --target=<container>
# Container crashes too fast to exec into? Copy it with the entrypoint replaced.
kubectl debug <pod> -it --copy-to=debug --container=<name> -- sh
# A throwaway pod for network testing
kubectl run tmp --rm -it --image=busybox --restart=Never -- shReaching things from your laptop#
kubectl port-forward svc/web 8080:80 # then http://localhost:8080
kubectl port-forward pod/<pod> 5432:5432 # straight to one pod
kubectl port-forward deploy/web 8080:80port-forward is how you test an internal Service without exposing it.
Resource usage#
kubectl top nodes # needs metrics-server installed
kubectl top pods -A --sort-by=memory
kubectl top pods -A --sort-by=cpu
kubectl top pod <pod> --containers # per-container
# What is actually requested vs available on a node
kubectl describe node <node> | grep -A10 "Allocated resources"Changing things#
kubectl apply -f manifest.yaml # create OR update. Always use this
kubectl apply -f ./manifests/ # a whole directory
kubectl delete -f manifest.yaml
kubectl diff -f manifest.yaml # what WOULD change. Run before apply
kubectl scale deploy/web --replicas=5
kubectl set image deploy/web web=myapp:2.0
kubectl rollout status deploy/web # wait for the rollout
kubectl rollout restart deploy/web # recreate pods, pick up new config
kubectl rollout undo deploy/web # roll back
kubectl rollout history deploy/web
kubectl edit deploy/web # opens your editor, applies on saveExtracting specific values#
# One field
kubectl get pod <pod> -o jsonpath='{.status.podIP}{"\n"}'
# All images in a namespace
kubectl get pods -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.containers[*].image}{"\n"}{end}'
# Custom columns — much more readable than jsonpath for tables
kubectl get pods -o custom-columns=\
NAME:.metadata.name,STATUS:.status.phase,NODE:.spec.nodeName,IP:.status.podIP
# Full object, for reading or copying
kubectl get pod <pod> -o yamlContexts and namespaces#
kubectl config get-contexts # every cluster you can reach
kubectl config current-context # WHICH CLUSTER AM I ON?
kubectl config use-context staging
kubectl config set-context --current --namespace=production
kubectl get ns # list namespacesConfig and secrets#
kubectl get configmap
kubectl get configmap app-config -o yaml
kubectl create secret generic db-creds \
--from-literal=username=admin --from-literal=password='s3cret'
# Secrets are base64-encoded, NOT encrypted. This decodes one:
kubectl get secret db-creds -o jsonpath='{.data.password}' | base64 -d; echoCleaning up#
kubectl delete pod <pod> # a Deployment will recreate it
kubectl delete pod -l app=web # by label
kubectl delete pod <pod> --grace-period=0 --force # stuck Terminating. Stateless only
# Everything created by a file
kubectl delete -f manifest.yaml
# Completed / failed pods left behind by Jobs
kubectl delete pod --field-selector=status.phase==Succeeded -AThe ten you will actually use#
Last updated 2026-09-08