kubectl grouped by task — inspect, change, debug, and the output flags that make it scriptable instead of something you read.
get tells you what exists, describe tells you why it is unhappy. Events at the bottom of describe answer most questions on their own.
| Command | What it does | Typical use |
|---|---|---|
| kubectl get po -o wide | Pods with node, IP and nominated node | kubectl get po -o wide |
| kubectl get po -A | Across every namespace | kubectl get po -A | grep -v Running |
| kubectl get po --field-selector status.phase!=Running | Only what is not healthy | kubectl get po -A --field-selector status.phase!=Running |
| kubectl get po -l app=api | By label — the way controllers select | kubectl get po -l 'app in (api,web)' |
| kubectl get po --sort-by=.status.containerStatuses[0].restartCount | Worst restart offenders first | kubectl get po --sort-by=.status.containerStatuses[0].restartCount |
| kubectl get ev --sort-by=.lastTimestamp | Events in time order, not the default jumble | kubectl get ev -A --sort-by=.lastTimestamp | tail -30 |
| kubectl describe po NAME | Full state plus the events for that object | kubectl describe po api-7d4f-x9k2 |
| kubectl get all -n NS | The common workload kinds in one namespace | kubectl get all -n payments |
| kubectl api-resources | Every kind the cluster knows, with short names | kubectl api-resources --namespaced=true |
| kubectl explain po.spec.containers | Field documentation straight from the API server | kubectl explain deploy.spec.strategy --recursive |
| kubectl top po --sort-by=memory | Live usage — needs metrics-server | kubectl top po -A --sort-by=memory |
apply is declarative and records intent in an annotation; create is imperative and fails if the object exists. Use apply.
| Command | What it does | Typical use |
|---|---|---|
| kubectl apply -f dir/ -R | Apply a directory tree | kubectl apply -f k8s/ -R |
| kubectl apply --dry-run=server | Ask the API server what would happen, admission and all | kubectl apply -f d.yaml --dry-run=server |
| kubectl diff -f | Diff your manifest against the live object before applying | kubectl diff -f deploy.yaml |
| kubectl create … --dry-run=client -o yaml | Generate a manifest skeleton to edit | kubectl create deploy api --image=nginx --dry-run=client -o yaml |
| kubectl patch -p | Change one field without sending the whole object | kubectl patch deploy api -p '{"spec":{"replicas":5}}' |
| kubectl set image | Change an image and trigger a rollout | kubectl set image deploy/api api=repo/api:v2 |
| kubectl edit | Open the live object in $EDITOR. Fine for triage, bad as a habit | kubectl edit deploy api |
| kubectl delete --grace-period=0 --force | Last resort for a stuck pod; it can orphan resources | kubectl delete po stuck --grace-period=0 --force |
| kubectl replace --force | Delete and recreate — for immutable field changes | kubectl replace --force -f job.yaml |
| kubectl label / annotate --overwrite | Add or change metadata in place | kubectl label no worker-3 tier=spot --overwrite |
The order that finds it fastest: logs, then previous logs, then events, then exec. If the container will not start, exec is not available — use debug.
| Command | What it does | Typical use |
|---|---|---|
| kubectl logs -f --tail=100 | Follow the last 100 lines | kubectl logs -f --tail=100 api-7d4f |
| kubectl logs --previous | Logs from the container that just crashed. The important one | kubectl logs api-7d4f --previous |
| kubectl logs -l app=api --max-log-requests=10 | Aggregate logs across pods by label | kubectl logs -l app=api --tail=50 --prefix |
| kubectl logs --since=15m --timestamps | Time-bounded, with timestamps | kubectl logs api-7d4f --since=15m --timestamps |
| kubectl exec -it -- sh | Shell in a running container | kubectl exec -it api-7d4f -c api -- sh |
| kubectl debug -it --image=nicolaka/netshoot | Attach an ephemeral container with real tools | kubectl debug -it api-7d4f --image=nicolaka/netshoot --target=api |
| kubectl debug node/NAME -it --image=ubuntu | A privileged pod on a node, with its root at /host | kubectl debug node/worker-3 -it --image=ubuntu |
| kubectl run tmp --rm -it --image=busybox -- sh | Throwaway pod for a quick test | kubectl run tmp --rm -it --image=busybox --restart=Never -- sh |
| kubectl port-forward | Reach a pod or service from your laptop | kubectl port-forward svc/api 8080:80 |
| kubectl cp | Copy files in or out of a container | kubectl cp api-7d4f:/tmp/heap.hprof ./heap.hprof |
| kubectl attach -it | Attach to PID 1's stdio, rather than starting a new process | kubectl attach -it api-7d4f |
A rollout is a new ReplicaSet gradually taking over from the old one. rollout status blocks until it settles, which makes it usable in CI.
| Command | What it does | Typical use |
|---|---|---|
| kubectl rollout status --timeout=5m | Wait for a rollout, fail the pipeline if it stalls | kubectl rollout status deploy/api --timeout=5m |
| kubectl rollout history | Revisions, with the change-cause annotation | kubectl rollout history deploy/api |
| kubectl rollout undo --to-revision=3 | Roll back to a specific revision | kubectl rollout undo deploy/api --to-revision=3 |
| kubectl rollout restart | Restart every pod without changing the spec — picks up new secrets | kubectl rollout restart deploy/api |
| kubectl rollout pause / resume | Hold a rollout mid-flight to inspect it | kubectl rollout pause deploy/api |
| kubectl scale --replicas=0 | Scale to zero and back — the crudest restart | kubectl scale deploy/api --replicas=0 |
| kubectl autoscale --min --max --cpu-percent | Create an HPA imperatively | kubectl autoscale deploy/api --min=2 --max=10 --cpu-percent=70 |
| kubectl wait --for=condition=Ready | Block until a condition holds — for scripts | kubectl wait --for=condition=Ready po -l app=api --timeout=120s |
Draining is two steps: cordon stops new pods, drain evicts the existing ones respecting PodDisruptionBudgets.
| Command | What it does | Typical use |
|---|---|---|
| kubectl get no -o wide | Nodes with version, OS image and kernel | kubectl get no -o wide |
| kubectl describe no NAME | Conditions, allocatable, and what is already on it | kubectl describe no worker-3 |
| kubectl cordon / uncordon | Stop / resume scheduling onto a node | kubectl cordon worker-3 |
| kubectl drain --ignore-daemonsets --delete-emptydir-data | Evict everything before maintenance | kubectl drain worker-3 --ignore-daemonsets --delete-emptydir-data |
| kubectl taint no key=value:NoSchedule | Repel pods that lack the matching toleration | kubectl taint no worker-3 gpu=true:NoSchedule |
| kubectl get po --field-selector spec.nodeName=X | What is running on one node | kubectl get po -A --field-selector spec.nodeName=worker-3 |
| kubectl describe no | grep -A5 Allocated | How much of the node is already requested | kubectl describe no worker-3 | grep -A6 'Allocated resources' |
kubectl config edits your kubeconfig; auth can-i answers RBAC questions without trial and error.
| Command | What it does | Typical use |
|---|---|---|
| kubectl config get-contexts | Every cluster you can reach, and which is current | kubectl config get-contexts |
| kubectl config use-context | Switch cluster | kubectl config use-context prod-eu |
| kubectl config set-context --current --namespace= | Stop typing -n on every command | kubectl config set-context --current --namespace=payments |
| kubectl auth can-i --list | Everything the current identity may do here | kubectl auth can-i --list -n payments |
| kubectl auth can-i delete po --as= | Check another user's or service account's rights | kubectl auth can-i delete po --as=system:serviceaccount:ci:deployer |
| kubectl auth whoami | Which identity the API server sees | kubectl auth whoami |
| kubectl get secret NAME -o jsonpath='{.data.k}' | base64 -d | Read one key out of a secret | kubectl get secret db -o jsonpath='{.data.password}' | base64 -d |
Everything above becomes automatable with the right -o. jsonpath for one value, -o json | jq for anything complex.
| Command | What it does | Typical use |
|---|---|---|
| -o jsonpath='{.items[*].metadata.name}' | Pull specific fields | kubectl get po -o jsonpath='{.items[*].spec.nodeName}' |
| -o custom-columns= | Build your own table | kubectl get po -o custom-columns=NAME:.metadata.name,NODE:.spec.nodeName |
| -o yaml / -o json | The full object as the API server holds it | kubectl get deploy api -o yaml |
| --no-headers | Machine-readable output for a pipeline | kubectl get po --no-headers | wc -l |
| -w / --watch | Stream changes as they happen | kubectl get po -w |
| kubectl get --raw /metrics | Hit an API server endpoint directly | kubectl get --raw /readyz?verbose |
| kubectl kustomize dir/ | Render a kustomization without applying it | kubectl kustomize overlays/prod | less |
| kubectl … --v=8 | Log every HTTP request kubectl makes — the debugging escape hatch | kubectl get po --v=8 |