Gendi Notes

kubectl Cheat Sheet

Grouped by what you are trying to find out, not alphabetically — because at 3am you know the question, not the flag.

Level 1 cheat-sheet kuberneteskubectlcheatsheet

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=production

What is running?#

CommandShows
kubectl get podsPods in the current namespace
kubectl get pods -AEvery namespace — use when you can't find something
kubectl get pods -o wideAdds pod IP and node
kubectl get pods -wWatch live as statuses change
kubectl get pods -l app=webOnly pods with that label
kubectl get allMost object types here
kubectl get nodesThe machines. All should be Ready
kubectl api-resourcesEvery 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 -A

Why 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=Warning

Getting 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 -- sh

Reaching 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:80

port-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 save

Extracting 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 yaml

Contexts 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 namespaces

Config 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; echo

Cleaning 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 -A

The ten you will actually use#

Last updated 2026-09-08