Cheatsheet

kubectl grouped by what you are trying to do

Inspecting what is running, debugging what is broken, deploying and rolling back, moving between clusters, and squeezing exactly one field out of the API with jsonpath. Every entry is a command you can paste, with the gotcha that bites at the end of each group.

Checked against Kubernetes 1.35, August 2026. Not sure you need a cluster at all? Read the honest sizing note below.

Inspect: what is actually running

Command What it does
kubectl get pods Pods in the current namespace, with restarts and age. The first command every time.
kubectl get pods -o wide Adds pod IP and the node each one landed on. What you want during an incident.
kubectl get pods -A Every namespace at once, including kube-system.
kubectl get pods -w Stream state changes instead of re-running the command in a loop.
kubectl get pods -l app=web Filter by label. Labels are how everything in Kubernetes finds everything else.
kubectl get pods --field-selector status.phase=Pending Filter on server-side fields. Pending usually means unschedulable.
kubectl get all -n prod Common workload types in one namespace. Deliberately not literally everything.
kubectl get deploy,svc,ing Several resource types in one call, comma separated, no spaces.
kubectl describe pod web-abc123 Spec, status, mounts, conditions, and recent events. Read the events at the bottom first.
kubectl get pod web-abc123 -o yaml The full object as the API server holds it, defaults and all.
kubectl explain deployment.spec.strategy Field documentation straight from the cluster. Faster than opening the docs site.
kubectl api-resources Every resource type this cluster knows, with short names and whether it is namespaced.
kubectl get nodes -o wide Node status, kubelet version, OS image, and container runtime.
kubectl top pods --sort-by=memory Live CPU and memory per pod. Requires metrics-server in the cluster.

Gotcha: almost every get is namespace-scoped and silently shows only your current namespace, so "the pod is gone" usually means you are looking in the wrong place. Add -A before you panic. And kubectl get all does not include ConfigMaps, Secrets, Ingresses, or PVCs despite the name.

Debug: logs, shells, and events

Command What it does
kubectl logs web-abc123 Stdout and stderr of the pod's single container.
kubectl logs web-abc123 -c sidecar Pick a container when the pod has more than one.
kubectl logs -f web-abc123 --tail=100 Follow from the last hundred lines instead of replaying the whole history.
kubectl logs web-abc123 --previous Logs from the container instance that just crashed. The CrashLoopBackOff command.
kubectl logs -l app=web --prefix --tail=50 Aggregate across every pod matching a label, prefixed with the pod name.
kubectl logs --since=15m deploy/web Time-bounded logs, and you can target a Deployment rather than a pod name.
kubectl exec -it web-abc123 -- sh Interactive shell inside a running container. The double dash is mandatory.
kubectl exec web-abc123 -- env Run one command without a TTY. Fastest way to confirm what config a pod really got.
kubectl port-forward svc/api 8080:80 Tunnel a cluster service to localhost. Works on pod/, svc/, and deploy/ targets.
kubectl debug -it web-abc123 --image=busybox --target=app --profile=general Attach an ephemeral debug container that shares the process namespace of a distroless pod.
kubectl debug node/node-1 -it --image=ubuntu --profile=general A privileged pod on one node with its filesystem mounted, for host-level problems.
kubectl run tmp --rm -it --image=alpine --restart=Never -- sh Throwaway pod for testing DNS and connectivity from inside the cluster network.
kubectl cp web-abc123:/app/dump.txt ./dump.txt Copy files out of (or into) a container. Needs tar present in the image.
kubectl get events --sort-by=.lastTimestamp Cluster events oldest to newest. Unsorted event output is nearly useless.
kubectl get events --field-selector involvedObject.name=web-abc123 Only the events about one object. Scheduling and image-pull failures show up here.
kubectl auth can-i create deployments --as=system:serviceaccount:ci:deployer Test RBAC as another identity before spending an hour on a permission mystery.

Gotcha: --previous is the only way to read the logs of a container that already restarted, and it is gone after the next restart - grab it first. On 1.35 kubectl debug still defaults to the deprecated legacy profile and prints a warning; pass --profile=general explicitly so your commands keep working when the default flips.

Deploy, roll out, and roll back

Command What it does
kubectl apply -f k8s/ Declaratively create or update everything in a directory of manifests.
kubectl apply -k overlays/prod Apply a Kustomize overlay. Kustomize is built into kubectl, no extra binary.
kubectl diff -f k8s/ Show what apply would change. Run it before every apply against production.
kubectl apply --dry-run=server -f k8s/ Validate against the real API including admission webhooks, without persisting.
kubectl rollout status deploy/web --timeout=120s Block until the rollout completes or the timeout expires. The CI gate command.
kubectl rollout history deploy/web Revision list with change-cause annotations, if anyone set them.
kubectl rollout undo deploy/web Back to the previous revision. The fastest rollback available.
kubectl rollout undo deploy/web --to-revision=3 Jump to a specific revision from the history listing.
kubectl rollout restart deploy/web Rolling restart with no spec change. How you pick up a rotated Secret or ConfigMap.
kubectl rollout pause deploy/web Freeze a rollout mid-flight so you can batch several edits. Resume with rollout resume.
kubectl scale deploy/web --replicas=5 Change replica count immediately. Reverted by the next apply unless the manifest agrees.
kubectl autoscale deploy/web --min=2 --max=10 --cpu-percent=70 Create a HorizontalPodAutoscaler without writing the manifest.
kubectl set image deploy/web app=ghcr.io/acme/app:abc123 Swap one container image and trigger a rollout. Handy in a deploy script.
kubectl create job manual-1 --from=cronjob/nightly Run a CronJob right now, once, without touching its schedule.
kubectl delete -f k8s/ Remove exactly what those manifests created. Safer than deleting by name.
kubectl delete pod web-abc123 --grace-period=0 --force Evict a stuck pod immediately. Last resort - it can leave orphaned resources behind.

Gotcha: a ConfigMap or Secret change does not restart anything. Pods keep the values they started with until you run rollout restart, which is why "I updated the config and nothing happened" is the most common false alarm in Kubernetes. Also note scale and set image are imperative: the next apply from git will quietly undo them.

Contexts, namespaces, and kubeconfig

Command What it does
kubectl config current-context Which cluster you are about to change. Run it before anything destructive.
kubectl config get-contexts Every context in your kubeconfig, with the active one marked.
kubectl config use-context staging Switch clusters for every subsequent command in this shell and every other one.
kubectl config set-context --current --namespace=payments Change the default namespace so you stop typing -n on every command.
kubectl --context=staging get pods -n web One-off against another cluster without switching. Much safer than switching back and forth.
kubectl config view --minify Just the active context's cluster, user, and namespace.
kubectl config rename-context old-name prod Give a cloud-generated context name something you can read at 3am.
KUBECONFIG=a.yaml:b.yaml kubectl config view --flatten Merge several kubeconfig files into one you can save.
kubectl get ns List namespaces and their status.
kubectl create ns feature-x New namespace. The cheapest isolation boundary the cluster offers.

Gotcha: the active context is global state shared by every terminal you have open, which is how production incidents start. Put the current context and namespace in your shell prompt, or use --context per command. Also keep kubectl within one minor version of the cluster - the supported skew is one minor either way, and unusual errors are often just an old client.

Output recipes: jsonpath and custom columns

For scripts, for pulling one field, and for the reports nobody wants to build a tool for.

Command What it does
kubectl get pods -o name Just resource identifiers, ready to pipe into another kubectl call with xargs.
kubectl get pods --no-headers Drop the header row so awk and cut behave.
kubectl get pods -o jsonpath='{.items[*].metadata.name}' Space-separated pod names. The simplest jsonpath you will use daily.
kubectl get pods -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.status.podIP}{"\n"}{end}' Loop with a range block to emit one line per item.
kubectl get pods -o jsonpath='{.items[?(@.status.phase!="Running")].metadata.name}' Filter expression: every pod that is not Running.
kubectl get pods -o custom-columns=NAME:.metadata.name,NODE:.spec.nodeName Build exactly the table you want. Far more readable than jsonpath for humans.
kubectl get pods --sort-by=.metadata.creationTimestamp Oldest first. Combine with custom-columns for a readable age report.
kubectl get secret app -o jsonpath='{.data.PASSWORD}' | base64 -d Read one secret value. Secret data is base64, never encrypted, at rest in etcd unless configured.
kubectl get deploy web -o json | jq '.spec.template.spec.containers[0].image' When jsonpath gets painful, hand it to jq instead.
kubectl get pods -o go-template='{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}' Full Go templates when you need conditionals in the output.

Gotcha: kubectl's jsonpath is not standard JSONPath. Every expression needs braces, escape sequences such as {"\n"} only work inside double quotes within the template, and a missing field yields empty output rather than an error - so a script can silently do nothing. When the expression stops being obvious, use -o json and jq.

Config, secrets, and node maintenance

Command What it does
kubectl create secret generic app --from-literal=API_KEY=abc Create a Secret inline. Use --from-file for certificates and larger values.
kubectl create configmap app --from-file=./config/ Every file in a directory becomes a key in the ConfigMap.
kubectl create secret generic app --from-literal=K=v --dry-run=client -o yaml Generate the manifest instead of applying it. The standard way to author one.
kubectl label pod web-abc123 tier=backend --overwrite Add or change a label on a live object. Overwrite is required if it already exists.
kubectl annotate deploy/web kubernetes.io/change-cause="release 1.4.0" Populates the CHANGE-CAUSE column in rollout history. Worth doing in CI.
kubectl top nodes CPU and memory usage per node against capacity.
kubectl describe node node-1 Allocated requests and limits per node - the numbers the scheduler actually uses.
kubectl cordon node-1 Stop new pods scheduling there. Existing pods keep running.
kubectl drain node-1 --ignore-daemonsets --delete-emptydir-data Evict everything so the node can be patched or replaced.
kubectl uncordon node-1 Put the node back into service after maintenance.
kubectl taint nodes node-1 gpu=true:NoSchedule Reserve a node for workloads that carry the matching toleration.
kubectl api-versions Every API group and version served. First stop when a manifest is rejected.

Gotcha: drain honours PodDisruptionBudgets and will hang indefinitely rather than break one. That is correct behaviour, not a bug - if it stalls, the budget is telling you the workload cannot lose another replica. Fix the replica count instead of reaching for --force.

Honest sizing note

When your team does not need Kubernetes

The commands above are worth knowing because you will meet a cluster eventually. That is not the same as needing one. The 2026 consensus is unusually consistent: below roughly fifteen engineers, without hundreds of services, Kubernetes is a complexity tax that buys nothing you could not get more cheaply. Three to five services on one server is a Docker Compose problem. Outgrowing one server usually means a serverless container platform - Cloud Run, ECS Fargate, App Runner, Fly.io - not a control plane.

Kubernetes is the right answer when eight or more services deploy independently, when two or more teams need to ship without coordinating, or when your uptime commitment has to survive a single machine failing. It is also a system that requires a person: not someone who read the documentation, someone who has debugged an eviction at 2am. A managed control plane removes some of that work and none of the rest.

The full ladder - Compose, then serverless containers, then k3s, then managed Kubernetes - and the honest cost of each rung is in container tools.

Keep going

Everything in a cluster starts as an image, so the Docker cheatsheet covers the build side these manifests consume. Provisioning the cluster itself belongs in infrastructure as code, and driving kubectl apply from a pipeline is covered in the CI/CD pipeline guide.

If the ladder above suggests you are one rung too high, the self-hosting guide covers running the same containers on a single VPS with backups, HTTPS, and monitoring.