Skip to main content

kubectl Cheatsheet — 100+ Kubernetes Commands with Pitfalls and YAML Templates

kubectl cheat sheet — 100+ Kubernetes commands with real examples, common pitfalls, and YAML snippets.

  • Runs locally
  • Category Developer & DevOps
  • Best for Formatting, validating, shrinking, or inspecting code-adjacent text.
176 commands
Cluster (22)
kubectl cluster-info

Print the API server URL and the cluster service endpoints (DNS, dashboard if installed).

Common pitfall: If this hangs, kubeconfig is pointing at a server you cannot reach (VPN down, wrong context). Check `kubectl config current-context` first.

Examples
kubectl cluster-info
kubectl cluster-info dump
kubectl get nodes

List all nodes with status, roles, age, version. Add -o wide to see internal/external IP and OS.

Examples
kubectl get nodes
kubectl get nodes -o wide
kubectl get nodes --show-labels
kubectl top nodes

Show CPU and memory usage per node (real numbers from metrics-server, not limits).

Common pitfall: Needs metrics-server installed and Ready. On bare clusters you get `error: Metrics API not available` until you helm install it.

Examples
kubectl top nodes
kubectl top nodes --sort-by=memory
kubectl describe node <node>

Deep view of a node: labels, taints, allocatable resources, conditions, running pods, events.

Examples
kubectl describe node ip-10-0-1-23
kubectl describe node | grep -A3 Taints
kubectl cordon <node>

Mark a node unschedulable — no new pods land there, existing ones keep running.

Common pitfall: Cordon alone does NOT move workloads off — pair with `drain` before maintenance, then `uncordon` after.

Examples
kubectl cordon ip-10-0-1-23
kubectl uncordon ip-10-0-1-23
kubectl drain <node>

Evict all pods from a node before maintenance. Respects PodDisruptionBudgets.

Common pitfall: Daemonsets block drain by default — pass `--ignore-daemonsets`. Local-storage pods need `--delete-emptydir-data` and that DATA IS GONE.

Examples
kubectl drain ip-10-0-1-23 --ignore-daemonsets
kubectl drain ip-10-0-1-23 --ignore-daemonsets --delete-emptydir-data --force
kubectl config current-context

Print the kubeconfig context you are currently pointing at (cluster + namespace + user).

Common pitfall: After a wrong `kubectl delete`, the first question is "which cluster did I just hit?" — wire this into your shell prompt with kubectx or starship.

Examples
kubectl config current-context
kubectl config get-contexts
kubectl config use-context <name>

Switch to a different context defined in kubeconfig.

Common pitfall: For frequent switching, install `kubectx` — `kubectx prod` is shorter than the full command and shows interactive fzf list.

Examples
kubectl config use-context prod
kubectx prod
kubectl config set-context --current --namespace=<ns>

Change the default namespace of the current context so you stop typing -n everywhere.

Common pitfall: Use `kubens <ns>` for one-line interactive switching. The raw command is annoying to type and easy to forget the `--current`.

Examples
kubectl config set-context --current --namespace=staging
kubens staging
kubectl version

Print client and server version. Skew of >1 minor is unsupported.

Examples
kubectl version
kubectl version -o json
kubectl api-resources

List every resource type known to the API server with its short name, group, and namespaced flag.

Examples
kubectl api-resources
kubectl api-resources --namespaced=true
kubectl api-resources --api-group=apps
kubectl explain <resource>

Inline docs for any resource and its fields. Drill down with dotted paths.

Examples
kubectl explain pod
kubectl explain pod.spec.containers
kubectl explain deployment --recursive
kubectl get componentstatuses

Legacy command showing control-plane component health. Deprecated since 1.19 — replaced by `kubectl get --raw=/livez`.

Common pitfall: On managed Kubernetes (EKS, GKE, AKS) you cannot see control-plane state — the cloud provider handles it. This will return errors or empty.

Examples
kubectl get componentstatuses
kubectl get --raw=/livez?verbose
kubectl get --raw=/readyz?verbose
kubectl config view

Print the merged kubeconfig. Add --minify to show only the current context, --flatten to inline cert data.

Common pitfall: By default certs/tokens are redacted. Add --raw to dump real credentials. Never paste --raw output into a chat or issue.

Examples
kubectl config view --minify
kubectl config view --flatten -o yaml
kubectl config view --raw
kubectl config get-contexts

List every context in kubeconfig with a * marking the active one, plus its cluster, user, and namespace.

Examples
kubectl config get-contexts
kubectl config get-contexts -o name
kubectl config delete-context <name>

Remove a context entry from kubeconfig. Does not touch the cluster or user entries it referenced.

Common pitfall: Leaves orphaned cluster/user blocks behind. Run `kubectl config delete-cluster` and `delete-user` too if you want a clean file.

Examples
kubectl config delete-context old-prod
kubectl config delete-cluster old-prod
kubectl config delete-user old-prod-admin
kubectl uncordon <node>

Mark a node schedulable again after maintenance. The inverse of cordon.

Examples
kubectl uncordon ip-10-0-1-23
kubectl get nodes | grep SchedulingDisabled
kubectl taint nodes <node> <key>=<val>:<effect>

Add a taint so only pods with a matching toleration land on the node. Effects: NoSchedule, PreferNoSchedule, NoExecute.

Common pitfall: NoExecute also evicts already-running pods that lack the toleration. Remove a taint by appending a minus: `key=val:NoSchedule-`.

Examples
kubectl taint nodes ip-10-0-1-23 gpu=true:NoSchedule
kubectl taint nodes ip-10-0-1-23 gpu=true:NoSchedule-
kubectl describe node ip-10-0-1-23 | grep Taints
kubectl label nodes <node> <key>=<val>

Label a node so pods can target it with nodeSelector or nodeAffinity (e.g. disk=ssd, zone=us-east-1a).

Examples
kubectl label nodes ip-10-0-1-23 disk=ssd
kubectl label nodes ip-10-0-1-23 disk-
kubectl get nodes -L disk,zone
kubectl get nodes -o wide

List nodes with extra columns: internal/external IP, OS image, kernel version, container runtime.

Examples
kubectl get nodes -o wide
kubectl get nodes -o custom-columns=NAME:.metadata.name,RUNTIME:.status.nodeInfo.containerRuntimeVersion
kubectl get --raw=/readyz?verbose

Hit the API server readiness endpoint directly, listing each health check and its status. The modern componentstatuses.

Examples
kubectl get --raw=/readyz?verbose
kubectl get --raw=/livez?verbose
kubectl get --raw=/healthz
kubectl api-versions

List every API group/version the server serves (e.g. apps/v1, batch/v1, networking.k8s.io/v1).

Common pitfall: Use this to confirm whether a deprecated apiVersion (extensions/v1beta1) still exists before an upgrade breaks your manifests.

Examples
kubectl api-versions
kubectl api-versions | grep networking
Pod (25)
kubectl get pods

List pods in the current namespace. Most common kubectl command.

Examples
kubectl get pods
kubectl get pods -A
kubectl get pods -o wide
kubectl get pods -w
kubectl get pods -l app=web
kubectl get pod <name>

Get a single pod. Add -o yaml/json for the full spec, or -o jsonpath= for surgical extraction.

Examples
kubectl get pod web-7d5 -o yaml
kubectl get pod web-7d5 -o jsonpath="{.status.phase}"
kubectl get pod web-7d5 -o json | jq .status
kubectl describe pod <name>

Human-readable deep view: spec, status, containers, volumes, events. First stop for any pod issue.

Common pitfall: Events at the bottom are the actual debugging gold — ImagePull errors, FailedScheduling reasons, OOMKilled, liveness/readiness failures all live there.

Examples
kubectl describe pod web-7d5
kubectl describe pod web-7d5 | tail -30
kubectl logs <pod>

Print stdout/stderr of a pod's main container.

Common pitfall: Multi-container pod? Add `-c <container>` or you get an error. App writing to a file in the container? `logs` is empty. Make 12-factor apps log to stdout.

Examples
kubectl logs web-7d5
kubectl logs web-7d5 -c sidecar
kubectl logs -l app=web --tail=50
kubectl logs -f <pod>

Stream new log lines as they appear. Like tail -f, but for the container.

Examples
kubectl logs -f web-7d5
kubectl logs -f web-7d5 --since=10m
kubectl logs -f deployment/web
kubectl logs --previous <pod>

Show logs from the previous container instance — the run that just crashed.

Common pitfall: For CrashLoopBackOff debugging, this is THE command. Without --previous you see the current restart's logs which are empty until it crashes again.

Examples
kubectl logs --previous web-7d5
kubectl logs -p -c app web-7d5
kubectl exec -it <pod> -- <cmd>

Open an interactive shell or run a command inside a running pod.

Common pitfall: Try `bash` first, fall back to `sh` — alpine has no bash, distroless has no shell at all (use `kubectl debug`). The `--` separates kubectl flags from container args.

Examples
kubectl exec -it web-7d5 -- bash
kubectl exec -it web-7d5 -- sh
kubectl exec web-7d5 -- ls /app
kubectl exec -it web-7d5 -c sidecar -- sh
kubectl port-forward <pod> <local>:<pod>

Tunnel a local port to a port inside a pod (or service). Great for poking at a private service from your laptop.

Common pitfall: Tunnel dies on idle, network flap, or pod restart. For long-running access use a proper bastion or `telepresence`, not port-forward.

Examples
kubectl port-forward pod/web-7d5 8080:80
kubectl port-forward svc/web 8080:80
kubectl port-forward deployment/web 8080:80
kubectl cp <pod>:<path> <local>

Copy files between a pod and your local machine. Either side can be the pod.

Common pitfall: Needs `tar` in the container. Many distroless images have none — bake one in or use a debug ephemeral container.

Examples
kubectl cp web-7d5:/var/log/app.log ./app.log
kubectl cp ./fix.patch web-7d5:/tmp/
kubectl cp web-7d5:/data ./data -c sidecar
kubectl attach <pod>

Attach your terminal to the main process of a running pod. Ctrl-C may kill the container.

Common pitfall: `attach` is NOT a shell — it joins the existing process. Unless you really need the original TTY, `exec -it ... -- sh` is what you want.

Examples
kubectl attach web-7d5
kubectl attach -it web-7d5 -c app
kubectl delete pod <name>

Delete one or more pods. If owned by a controller (Deployment etc.) a replacement spins up.

Common pitfall: For restarting a deployment, use `rollout restart` — it is the supported primitive. `delete pod` on a stuck Terminating pod needs `--grace-period=0 --force` (and may leak network endpoints).

Examples
kubectl delete pod web-7d5
kubectl delete pod web-7d5 --grace-period=0 --force
kubectl delete pods -l app=web
kubectl debug <pod> --image=<dbg>

Attach an ephemeral debug container (with curl, ps, tcpdump, whatever) to a running pod — even distroless.

Common pitfall: Needs Kubernetes ≥1.23 with EphemeralContainers stable. The debug container shares network and PID namespace, NOT the filesystem.

Examples
kubectl debug web-7d5 --image=busybox -it
kubectl debug web-7d5 --image=nicolaka/netshoot --target=app
kubectl debug node/ip-10-0-1-23 -it --image=busybox
kubectl run <name> --image=<img>

Create a bare pod from an image. Mostly used as a quick `--rm -it` debug runner.

Common pitfall: Bare pods are not managed by any controller — they do NOT restart on node failure. Use deployments for anything that should stay up.

Examples
kubectl run tmp --rm -it --image=busybox -- sh
kubectl run curl --rm -it --image=curlimages/curl -- curl http://web
kubectl run nginx --image=nginx
kubectl logs --since=<duration> <pod>

Logs from the last duration. Combines well with -f and --tail.

Examples
kubectl logs --since=15m web-7d5
kubectl logs --since=1h -f web-7d5
kubectl logs --since-time=2026-05-25T08:00:00Z web-7d5
kubectl logs --tail=<n> <pod>

Show the last N lines. Use --tail=-1 to print all (the default sometimes hides old logs).

Examples
kubectl logs --tail=100 web-7d5
kubectl logs --tail=-1 web-7d5 > app.log
kubectl logs --all-containers <pod>

Stream logs from every container in the pod at once (app + sidecars), instead of picking one with -c.

Common pitfall: Lines from different containers interleave with no prefix by default. Add `--prefix` to tag each line with its pod/container name.

Examples
kubectl logs --all-containers web-7d5
kubectl logs --all-containers --prefix -l app=web
kubectl logs --timestamps <pod>

Prefix every log line with an RFC3339 timestamp from when the container emitted it.

Examples
kubectl logs --timestamps web-7d5
kubectl logs --timestamps --since=10m -f web-7d5
kubectl get pod <name> -o jsonpath=...

Extract exactly the field you want from a pod with a JSONPath expression. Scriptable, no jq needed.

Common pitfall: Wrap the expression in single quotes and add `range`/`end` to iterate over arrays like containers. A trailing `{"\n"}` adds a newline.

Examples
kubectl get pod web-7d5 -o jsonpath='{.status.podIP}'
kubectl get pod web-7d5 -o jsonpath='{range .spec.containers[*]}{.name}{"\t"}{.image}{"\n"}{end}'
kubectl get pods -o jsonpath='{.items[*].metadata.name}'
kubectl exec <pod> -- env

Dump the environment variables visible inside a running container. Fast way to verify injected config/secrets.

Common pitfall: This prints decoded secret values in plain text to your terminal/scrollback. Avoid on shared screens or recorded sessions.

Examples
kubectl exec web-7d5 -- env
kubectl exec web-7d5 -- env | grep DATABASE
kubectl exec web-7d5 -c app -- printenv LOG_LEVEL
kubectl exec <pod> -- cat /etc/resolv.conf

Read the DNS config a pod actually sees. First stop when in-cluster name resolution misbehaves.

Common pitfall: A wrong `ndots:5` (the default) makes every short name try 5 search-domain suffixes first, causing slow lookups. Compare nameserver against the kube-dns ClusterIP.

Examples
kubectl exec web-7d5 -- cat /etc/resolv.conf
kubectl exec web-7d5 -- nslookup kubernetes.default
kubectl get svc -n kube-system kube-dns
kubectl debug node/<node> -it --image=<img>

Launch a debug pod with host namespaces on a specific node — inspect the node filesystem at /host, run tcpdump, etc.

Common pitfall: The node root filesystem is mounted at `/host`, not `/`. To chroot into it: `chroot /host`. This needs privileges your RBAC may not grant.

Examples
kubectl debug node/ip-10-0-1-23 -it --image=busybox
kubectl debug node/ip-10-0-1-23 -it --image=ubuntu -- chroot /host
kubectl debug <pod> --copy-to=<new> --set-image=*=<img>

Clone a crashing pod into a debuggable copy with a swapped image/command, leaving the original untouched.

Common pitfall: The copy is a bare pod, not managed by the original controller. Delete it yourself when done or it lingers.

Examples
kubectl debug web-7d5 --copy-to=web-debug --set-image=app=busybox -it -- sh
kubectl debug web-7d5 --copy-to=web-debug --container=app -- sleep 1d
kubectl get pods --sort-by=.status.startTime

List pods ordered by start time — the newest restarts float to the bottom. Spot flapping pods fast.

Examples
kubectl get pods --sort-by=.status.startTime
kubectl get pods --sort-by=.status.containerStatuses[0].restartCount
kubectl get pods -o custom-columns=...

Build a custom table from any fields — name, node, restart count, image — instead of the default columns.

Examples
kubectl get pods -o custom-columns=NAME:.metadata.name,NODE:.spec.nodeName,RESTARTS:.status.containerStatuses[0].restartCount
kubectl get pods -o custom-columns=POD:.metadata.name,IMAGE:.spec.containers[*].image
kubectl get pod <name> -o yaml | kubectl neat

Strip the server-injected noise (managedFields, status, default annotations) so the YAML is re-appliable. Needs the krew `neat` plugin.

Common pitfall: A raw `get -o yaml` is NOT re-appliable as-is — it carries status and managedFields that `apply` rejects or fights. `neat` (or manual trimming) fixes that.

Examples
kubectl get pod web-7d5 -o yaml | kubectl neat
kubectl krew install neat
Workload (25)
kubectl create deployment <name> --image=<img>

Imperative one-liner to create a Deployment. Fine for demos; use YAML + apply for real systems.

Examples
kubectl create deployment web --image=nginx
kubectl create deployment web --image=nginx --replicas=3 --port=80
kubectl get deployments

List Deployments with desired / current / ready / age. Short name: `deploy`.

Examples
kubectl get deployments
kubectl get deploy -A
kubectl get deploy web -o yaml
kubectl scale deployment <name> --replicas=<n>

Change the replica count of a Deployment (or ReplicaSet / StatefulSet). Takes effect immediately.

Common pitfall: Scaling to 0 is the supported "pause" — pods are gone but the spec is preserved. Scaling back up is instant.

Examples
kubectl scale deployment web --replicas=3
kubectl scale deployment web --replicas=0
kubectl scale --replicas=5 -f deployment.yaml
kubectl rollout status deployment/<name>

Block and watch a rollout until it succeeds, fails, or times out.

Examples
kubectl rollout status deployment/web
kubectl rollout status deployment/web --timeout=2m
kubectl rollout history deployment/<name>

Show past revisions of a Deployment. Add --revision=N for the diff of a specific one.

Examples
kubectl rollout history deployment/web
kubectl rollout history deployment/web --revision=3
kubectl rollout undo deployment/<name>

Roll back to the previous revision (or to a specific one with --to-revision).

Common pitfall: History depth defaults to 10. Once it scrolls off you cannot undo to it — pin critical revisions in git.

Examples
kubectl rollout undo deployment/web
kubectl rollout undo deployment/web --to-revision=3
kubectl rollout restart deployment/<name>

Trigger a rolling restart by bumping a template annotation. The right way to restart a Deployment.

Common pitfall: Use this instead of `delete pod` — proper rolling update, maxUnavailable honored, zero downtime, undo works. Available for Deployments, StatefulSets, DaemonSets since 1.15.

Examples
kubectl rollout restart deployment/web
kubectl rollout restart statefulset/db
kubectl rollout restart daemonset/log-agent
kubectl autoscale deployment <name> --min=N --max=M --cpu-percent=P

Create a HorizontalPodAutoscaler that scales the Deployment between min and max based on CPU.

Common pitfall: HPA needs metrics-server. Custom-metric HPA needs an adapter (prometheus-adapter etc.). Without metrics HPA shows `unknown` and never scales.

Examples
kubectl autoscale deployment web --min=2 --max=10 --cpu-percent=70
kubectl get hpa
kubectl describe hpa web
kubectl get replicaset

List ReplicaSets. Each Deployment revision creates a new ReplicaSet under the hood.

Examples
kubectl get rs
kubectl get rs -l app=web
kubectl describe rs web-7d5f44
kubectl get statefulset

List StatefulSets — for ordered, stable-network-ID workloads like databases.

Common pitfall: PVCs created by a StatefulSet are NOT deleted when the STS is deleted — explicit cleanup needed or your data persists forever.

Examples
kubectl get sts
kubectl describe sts db
kubectl delete sts db --cascade=orphan
kubectl get daemonset

List DaemonSets — pods that run one copy per matching node (log shippers, CNI agents, node exporters).

Examples
kubectl get ds
kubectl get ds -A
kubectl rollout restart ds/log-agent
kubectl get job

List Jobs (run-to-completion workloads). Add `cronjob` for scheduled ones.

Examples
kubectl get jobs
kubectl get cronjobs
kubectl create job manual-job --from=cronjob/backup
kubectl expose deployment <name> --port=<p>

Create a Service in front of an existing Deployment (or Pod / RS). One-liner for ClusterIP.

Examples
kubectl expose deployment web --port=80 --target-port=8080
kubectl expose deployment web --type=NodePort --port=80
kubectl expose deployment web --type=LoadBalancer --port=80
kubectl get hpa

List HorizontalPodAutoscalers with current / target metric, min, max, age.

Examples
kubectl get hpa
kubectl describe hpa web
kubectl delete hpa web
kubectl get pdb

List PodDisruptionBudgets. They cap voluntary disruptions (drains, rolling updates) so SLO is preserved.

Common pitfall: A PDB with minAvailable=N where current replicas=N causes `drain` to hang forever. Set realistic numbers or scale up before maintenance.

Examples
kubectl get pdb
kubectl create pdb web-pdb --selector=app=web --min-available=2
kubectl describe deployment <name>

Deep dive on a Deployment: replicas, strategy, current ReplicaSet, events.

Examples
kubectl describe deployment web
kubectl describe deploy web | grep -A5 Conditions
kubectl set env deployment/<name> KEY=VAL

Add or change an environment variable on a Deployment, triggering a rolling update. Use KEY- to remove one.

Common pitfall: Like `set image`, this edits the live spec and drifts from your git YAML. Use `--from=configmap/<cm>` to pull all keys from a ConfigMap at once.

Examples
kubectl set env deployment/web LOG_LEVEL=debug
kubectl set env deployment/web LOG_LEVEL-
kubectl set env deployment/web --from=configmap/app-config
kubectl set resources deployment/<name> --limits=cpu=1,memory=512Mi

Patch CPU/memory requests and limits on a Deployment without editing YAML. Triggers a rolling update.

Examples
kubectl set resources deployment/web --limits=cpu=1,memory=512Mi --requests=cpu=200m,memory=256Mi
kubectl set resources deployment/web -c=app --limits=memory=1Gi
kubectl create cronjob <name> --image=<img> --schedule="<cron>"

Imperatively create a CronJob with a cron schedule. The command after -- becomes the container command.

Common pitfall: CronJob times are in the kube-controller-manager timezone (usually UTC), not yours, unless you set `spec.timeZone` (stable since 1.27).

Examples
kubectl create cronjob backup --image=backup:latest --schedule="0 2 * * *" -- /backup.sh
kubectl create cronjob ping --image=busybox --schedule="*/5 * * * *" -- echo hello
kubectl create job <name> --from=cronjob/<cj>

Trigger a CronJob immediately by spawning a one-off Job from its template. Test a backup without waiting for the schedule.

Examples
kubectl create job manual-backup --from=cronjob/backup
kubectl get jobs -l job-name=manual-backup
kubectl rollout status statefulset/<name>

Watch a StatefulSet rollout. Pods update one at a time in reverse ordinal order by default.

Common pitfall: A StatefulSet with `updateStrategy: OnDelete` will NOT roll out on spec change — you must delete each pod manually for it to recreate with the new spec.

Examples
kubectl rollout status statefulset/db
kubectl rollout status sts/db --timeout=5m
kubectl scale statefulset <name> --replicas=<n>

Scale a StatefulSet. Pods are added/removed one at a time, in order, respecting readiness.

Common pitfall: Scaling down does NOT delete the PVCs of removed pods (unless persistentVolumeClaimRetentionPolicy is set, 1.27+). Data sticks around.

Examples
kubectl scale statefulset db --replicas=5
kubectl scale sts db --replicas=1
kubectl get cronjob

List CronJobs with their schedule, suspend flag, last-scheduled time, and active job count.

Common pitfall: A CronJob with SUSPEND=True never fires. Resume with `kubectl patch cronjob <cj> -p '{"spec":{"suspend":false}}'`.

Examples
kubectl get cronjob
kubectl patch cronjob backup -p '{"spec":{"suspend":true}}'
kubectl get cronjob backup -o jsonpath='{.status.lastScheduleTime}'
kubectl describe hpa <name>

Show HPA decision-making: current vs target metrics, recent scaling events, and any "unable to fetch metrics" errors.

Common pitfall: The Events at the bottom explain WHY the HPA is or is not scaling. `FailedGetResourceMetric` there almost always means metrics-server is down.

Examples
kubectl describe hpa web
kubectl get hpa web -o yaml | grep -A10 conditions
kubectl rollout undo statefulset/<name>

Roll a StatefulSet back to its previous revision. Like Deployments, it keeps a revision history.

Examples
kubectl rollout undo statefulset/db
kubectl rollout history statefulset/db
Service & Ingress (11)
kubectl get services

List Services with type, cluster IP, external IP, ports, age. Short name: `svc`.

Examples
kubectl get svc
kubectl get svc -A
kubectl get svc -o wide
kubectl get endpoints <svc>

List the actual pod IPs behind a Service. Empty endpoints == broken selector or no ready pods.

Common pitfall: Service has clusterIP but `curl svc` hangs? `kubectl get endpoints <svc>` is the answer 90% of the time. Empty means the selector matched nothing or readinessProbe is failing.

Examples
kubectl get endpoints web
kubectl get endpointslices -l kubernetes.io/service-name=web
kubectl port-forward svc/<name> <local>:<svc>

Tunnel a local port to a Service. Goes through endpoints, not directly to a pod.

Examples
kubectl port-forward svc/web 8080:80
kubectl port-forward svc/db 5432:5432 -n staging
kubectl get ingress

List Ingress resources with hosts, paths, address, ports.

Common pitfall: An Ingress without an IngressClass annotation (`ingressClassName: nginx`) is invisible to controllers — looks created but nothing serves it.

Examples
kubectl get ingress
kubectl describe ingress web
kubectl get ingressclass
kubectl get networkpolicy

List NetworkPolicies that restrict pod-to-pod traffic. No policy = all traffic allowed (default).

Common pitfall: NetworkPolicy is enforced by the CNI plugin (Calico, Cilium, ...). On a CNI without policy support, NetworkPolicies are silently ignored — verify with `kubectl get ds -n kube-system`.

Examples
kubectl get netpol
kubectl describe netpol deny-all
kubectl get netpol -A
kubectl proxy

Start a local API server proxy on 127.0.0.1:8001 — use to access dashboard / API without auth handling.

Examples
kubectl proxy
kubectl proxy --port=9090
curl http://127.0.0.1:8001/api/v1/namespaces
kubectl describe ingress <name>

Show an Ingress with its rules, backend services, TLS, and controller-synced events at the bottom.

Common pitfall: If the ADDRESS column stays empty, no controller has claimed this Ingress — check ingressClassName and that the controller pod is running.

Examples
kubectl describe ingress web
kubectl get ingress web -o jsonpath='{.status.loadBalancer.ingress[0].ip}'
kubectl get endpointslices

List EndpointSlices — the scalable successor to Endpoints (default since 1.21). Each slice holds up to ~100 endpoints.

Examples
kubectl get endpointslices
kubectl get endpointslices -l kubernetes.io/service-name=web
kubectl describe endpointslice web-abc12
kubectl get svc <name> -o jsonpath=...

Pull a single field from a Service — the LoadBalancer external IP/hostname, the NodePort, or the ClusterIP.

Common pitfall: AWS NLBs publish a hostname, not an IP — read `.status.loadBalancer.ingress[0].hostname`, not `.ip`, or you get an empty string.

Examples
kubectl get svc web -o jsonpath='{.status.loadBalancer.ingress[0].hostname}'
kubectl get svc web -o jsonpath='{.spec.clusterIP}'
kubectl get svc web -o jsonpath='{.spec.ports[0].nodePort}'
kubectl create service clusterip <name> --tcp=<port>:<target>

Imperatively create a ClusterIP Service. Use --tcp=80:8080 to map service port to target port.

Common pitfall: This creates a Service with NO selector unless you add one afterward — useful for pointing at external endpoints, surprising if you expected pod routing.

Examples
kubectl create service clusterip web --tcp=80:8080
kubectl create service nodeport web --tcp=80:8080 --node-port=30080
kubectl get ingressclass

List installed IngressClasses and which is the default. An Ingress with no class falls back to the default-marked one.

Examples
kubectl get ingressclass
kubectl get ingressclass -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.metadata.annotations.ingressclass\.kubernetes\.io/is-default-class}{"\n"}{end}'
ConfigMap & Secret (16)
kubectl create configmap <name> --from-literal=KEY=VAL

Create a ConfigMap from literal key=value pairs. Multiple --from-literal allowed.

Examples
kubectl create configmap app-config --from-literal=LOG_LEVEL=info --from-literal=DEBUG=1
kubectl create configmap app-config --from-literal=DATABASE_HOST=db.local
kubectl create configmap <name> --from-file=<path>

Create a ConfigMap from one file or a whole directory (each file becomes a key).

Common pitfall: Total size cap is ~1 MB (etcd limit). For larger config use a Secret/ConfigMap projected volume + an init container, or move to a config service.

Examples
kubectl create configmap nginx-conf --from-file=./nginx.conf
kubectl create configmap site-conf --from-file=./conf.d/
kubectl get configmap

List ConfigMaps. Short name: `cm`. Add -o yaml to see the data.

Examples
kubectl get cm
kubectl get cm app-config -o yaml
kubectl get cm -A
kubectl create secret generic <name> --from-literal=KEY=VAL

Create a Secret from literal pairs. Values are base64-encoded at rest (NOT encrypted unless KMS is on).

Common pitfall: Secrets are base64, NOT encryption. Anyone with `get secrets` can decode. Enable encryption-at-rest in apiserver and consider Sealed Secrets / External Secrets for real safety.

Examples
kubectl create secret generic db --from-literal=password=s3cret
kubectl create secret generic api --from-literal=token=abc123
kubectl create secret docker-registry <name>

Create an imagePullSecret for a private registry. Reference it in pod spec with imagePullSecrets.

Examples
kubectl create secret docker-registry ghcr-pull --docker-server=ghcr.io --docker-username=user --docker-password=$TOKEN
kubectl create secret docker-registry ecr-pull --docker-server=123.dkr.ecr.us-east-1.amazonaws.com --docker-username=AWS --docker-password=$(aws ecr get-login-password)
kubectl get secret <name> -o jsonpath="{.data.<key>}" | base64 -d

Decode a single Secret value. The classic "what is the actual password in there" lookup.

Common pitfall: On macOS `base64` needs `-D` (capital), on Linux `-d` (lower). `base64 --decode` works on both.

Examples
kubectl get secret db -o jsonpath="{.data.password}" | base64 -d
kubectl get secret api -o json | jq -r ".data.token | @base64d"
kubectl get secret

List Secrets. Add -o yaml to see (base64-encoded) data.

Examples
kubectl get secret
kubectl get secret -A
kubectl get secret db -o yaml
kubectl create secret tls <name> --cert=<file> --key=<file>

Create a TLS Secret from a cert + key pair. Ingress / webhook configs reference it by name.

Examples
kubectl create secret tls web-tls --cert=tls.crt --key=tls.key
kubectl get secret web-tls -o yaml
kubectl get pvc

List PersistentVolumeClaims with status, capacity, access modes, storage class, age.

Common pitfall: PVC stuck in Pending = no matching PV / StorageClass. `describe pvc` shows the reason. Deleting a PVC may delete the underlying PV depending on reclaim policy.

Examples
kubectl get pvc
kubectl get pv
kubectl describe pvc data-db-0
kubectl create configmap <name> --from-env-file=<file>

Build a ConfigMap from a .env file — each KEY=VALUE line becomes a key. Different from --from-file (whole file as one key).

Common pitfall: Lines must be plain KEY=VALUE — no `export`, no quotes-with-spaces parsing, no inline comments after the value. Shell-style .env files often fail.

Examples
kubectl create configmap app-env --from-env-file=.env
kubectl create secret generic app-env --from-env-file=.env.production
kubectl get configmap <name> -o jsonpath=...

Read one key out of a ConfigMap directly, no -o yaml + manual scan. Great for shell scripts.

Examples
kubectl get configmap app-config -o jsonpath='{.data.LOG_LEVEL}'
kubectl get cm app-config -o jsonpath='{.data}'
kubectl edit secret <name>

Open a Secret in $EDITOR. Values shown are base64 — you must encode new values yourself before saving.

Common pitfall: Paste plaintext here and the value becomes double-mangled garbage. Use `kubectl create secret ... --dry-run=client -o yaml | kubectl apply -f -` instead to avoid manual base64.

Examples
kubectl edit secret db
echo -n "newpass" | base64
kubectl create secret generic <name> --from-file=<key>=<path>

Create a Secret where one key holds a file's contents (e.g. an SSH key or kubeconfig). Repeatable for multiple keys.

Examples
kubectl create secret generic ssh-key --from-file=id_rsa=/home/me/.ssh/id_rsa
kubectl create secret generic kubeconfig --from-file=config=/home/me/.kube/config
kubectl describe pvc <name>

Show a PVC's phase, bound PV, capacity, access mode, and — crucially — the Events explaining why it is Pending.

Common pitfall: Pending with `no persistent volumes available` means no StorageClass can provision, or you set a storageClassName that does not exist.

Examples
kubectl describe pvc data-db-0
kubectl get storageclass
kubectl get pvc -o wide
kubectl get storageclass

List StorageClasses and which is default (marked with (default)). PVCs with no storageClassName use the default.

Common pitfall: No default StorageClass means every PVC without an explicit class stays Pending forever. Many bare clusters ship with none.

Examples
kubectl get storageclass
kubectl get sc
kubectl patch storageclass gp2 -p '{"metadata":{"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'
kubectl get pv

List PersistentVolumes cluster-wide with capacity, access mode, reclaim policy, status, and the claim they are bound to.

Common pitfall: A PV stuck in Released (not Available) after its PVC was deleted will NOT rebind — reclaimPolicy=Retain keeps the data but blocks reuse until you clear `.spec.claimRef`.

Examples
kubectl get pv
kubectl get pv -o custom-columns=NAME:.metadata.name,STATUS:.status.phase,CLAIM:.spec.claimRef.name
kubectl patch pv pv-001 -p '{"spec":{"claimRef":null}}'
RBAC & Namespace (14)
kubectl get namespaces

List all namespaces with status (Active / Terminating) and age. Short name: `ns`.

Examples
kubectl get ns
kubectl create ns staging
kubectl delete ns old-staging
kubectl get serviceaccount

List ServiceAccounts in the current namespace. Every namespace gets a `default` SA.

Examples
kubectl get sa
kubectl create sa ci-bot
kubectl get sa default -o yaml
kubectl create role <name> --verb=get,list --resource=pods

Create a Role granting verbs on resources in the current namespace.

Examples
kubectl create role pod-reader --verb=get,list,watch --resource=pods
kubectl create role app-admin --verb=* --resource=deployments,services
kubectl create rolebinding <name> --role=<role> --serviceaccount=<ns>:<sa>

Bind a Role to a ServiceAccount, User, or Group within a namespace.

Common pitfall: Role + RoleBinding are namespaced. For cluster-wide permissions you need ClusterRole + ClusterRoleBinding. Mixing them is a common silent failure.

Examples
kubectl create rolebinding ci-pods --role=pod-reader --serviceaccount=ci:ci-bot
kubectl create rolebinding admin-binding --clusterrole=admin --user=alice
kubectl create clusterrole <name> --verb=... --resource=...

Create a cluster-scoped Role. Required for non-namespaced resources (nodes, PVs) or cross-namespace access.

Examples
kubectl create clusterrole node-reader --verb=get,list --resource=nodes
kubectl create clusterrolebinding viewer --clusterrole=view --user=alice
kubectl auth can-i <verb> <resource>

Check whether the current user (or --as <name>) is allowed to perform an action. THE RBAC debug command.

Common pitfall: Add `--list` to dump every permission you have in the namespace. Add `--as system:serviceaccount:ns:sa` to test from a pod's perspective.

Examples
kubectl auth can-i delete pods
kubectl auth can-i --list -n staging
kubectl auth can-i get secrets --as system:serviceaccount:default:my-bot
kubectl create token <serviceaccount>

Request a time-bounded bearer token for a ServiceAccount (replaces legacy auto-created Secret tokens since 1.24).

Common pitfall: Since 1.24 SAs no longer auto-create Secret tokens — old scripts that read `kubectl get secret` for the token return nothing. Switch to `kubectl create token` or define a Secret of type kubernetes.io/service-account-token explicitly.

Examples
kubectl create token ci-bot
kubectl create token ci-bot --duration=1h
kubectl create token default -n ci > /tmp/token
kubectl create namespace <name>

Create a new namespace. The minimum unit of isolation in a cluster.

Examples
kubectl create ns staging
kubectl create ns prod --dry-run=client -o yaml > ns.yaml
kubectl auth can-i --list

Dump every action the current identity is allowed to perform in a namespace. The fastest "what can I actually do" audit.

Examples
kubectl auth can-i --list
kubectl auth can-i --list -n kube-system
kubectl auth can-i --list --as=system:serviceaccount:ci:ci-bot
kubectl auth whoami

Print the username, groups, and extra attributes the API server attributes to your current credentials (stable since 1.28).

Common pitfall: Surprisingly useful when an OIDC/IAM token maps you to a different user than expected — RBAC denials often trace back to the wrong identity here.

Examples
kubectl auth whoami
kubectl auth whoami -o yaml
kubectl get clusterrolebinding

List cluster-wide RoleBindings. The place to audit who has cluster-admin or other powerful ClusterRoles.

Common pitfall: A binding to the `system:masters` group or `cluster-admin` ClusterRole is full god mode. Grep for these first in any security review.

Examples
kubectl get clusterrolebinding
kubectl get clusterrolebinding -o jsonpath='{range .items[?(@.roleRef.name=="cluster-admin")]}{.metadata.name}{"\n"}{end}'
kubectl describe clusterrole <name>

Show exactly which verbs on which resources a ClusterRole grants. Read before binding anyone to it.

Examples
kubectl describe clusterrole view
kubectl describe clusterrole edit
kubectl get clusterrole admin -o yaml
kubectl create rolebinding <name> --clusterrole=<cr> --serviceaccount=<ns>:<sa>

Bind a (cluster-scoped) ClusterRole to a ServiceAccount but only within ONE namespace. Common least-privilege pattern.

Common pitfall: Using --clusterrole with a RoleBinding (not ClusterRoleBinding) scopes those permissions to the binding's namespace only — a deliberate and very useful narrowing.

Examples
kubectl create rolebinding ci-edit --clusterrole=edit --serviceaccount=ci:ci-bot -n ci
kubectl create rolebinding read-only --clusterrole=view --user=alice -n staging
kubectl get rolebinding,clusterrolebinding -A -o wide

Wide listing of all bindings across namespaces, with the subjects (users/SAs/groups) shown in the output.

Examples
kubectl get rolebinding,clusterrolebinding -A -o wide
kubectl get clusterrolebinding -o wide | grep alice
Monitoring (13)
kubectl top pods

CPU + memory usage per pod (real numbers from metrics-server, not requests/limits).

Common pitfall: Needs metrics-server installed. Without it: `Metrics API not available`. Container-level breakdown: `top pods --containers`.

Examples
kubectl top pods
kubectl top pods --sort-by=memory
kubectl top pods --containers -A
kubectl get events

List recent cluster events. Add --sort-by to put the newest first.

Common pitfall: Default sort is by ResourceVersion which is meaningless to humans. ALWAYS add `--sort-by=.lastTimestamp` or `.metadata.creationTimestamp`.

Examples
kubectl get events --sort-by=.lastTimestamp
kubectl get events -A --sort-by=.lastTimestamp
kubectl get events --field-selector involvedObject.name=web-7d5
kubectl wait --for=condition=Ready pod/<name>

Block until a resource reaches a condition. Great for CI scripts after `apply`.

Examples
kubectl wait --for=condition=Ready pod/web-7d5 --timeout=60s
kubectl wait --for=condition=Available deployment/web --timeout=2m
kubectl wait --for=delete pod/old-7d5 --timeout=30s
kubectl get pods -w

Watch mode: stream changes to pod state as they happen. Ctrl-C to stop.

Examples
kubectl get pods -w
kubectl get pods -w -l app=web
kubectl get pods -w -o wide
kubectl get pods --field-selector=status.phase=Failed

Filter pods by status. The classic "find every failed / pending pod" search.

Examples
kubectl get pods --field-selector=status.phase=Failed -A
kubectl get pods --field-selector=status.phase=Pending
kubectl get pods --field-selector=spec.nodeName=ip-10-0-1-23
kubectl get all

List pods + svc + deploy + rs + statefulset + daemonset in one shot. Good high-level glance.

Common pitfall: `all` does NOT include configmaps, secrets, ingresses, jobs, PVCs, CRDs — the name is misleading. For "really all", iterate api-resources.

Examples
kubectl get all
kubectl get all -A
kubectl get all -n staging -o wide
kubectl top pod <name> --containers

Break CPU/memory usage down per container within one pod — find which sidecar is the memory hog.

Examples
kubectl top pod web-7d5 --containers
kubectl top pod -l app=web --containers --sort-by=memory
kubectl get events --field-selector type=Warning

Show only Warning-level events (Normal events filtered out) — the actionable problems, not the routine noise.

Examples
kubectl get events --field-selector type=Warning --sort-by=.lastTimestamp
kubectl get events -A --field-selector type=Warning --sort-by=.lastTimestamp
kubectl get events --field-selector involvedObject.name=<name>

Scope events to a single object — see only what happened to this pod/deployment, not the whole namespace.

Examples
kubectl get events --field-selector involvedObject.name=web-7d5
kubectl get events --field-selector involvedObject.kind=Deployment,involvedObject.name=web
kubectl get pods -A -o wide --field-selector spec.nodeName=<node>

List every pod scheduled on a specific node, across all namespaces. Essential before draining a node.

Examples
kubectl get pods -A -o wide --field-selector spec.nodeName=ip-10-0-1-23
kubectl get pods -A --field-selector spec.nodeName=ip-10-0-1-23 -o name | wc -l
kubectl wait --for=jsonpath=<path>=<val> <resource>

Block until any JSONPath field reaches a value — far more flexible than the built-in condition= waits (1.23+).

Examples
kubectl wait --for=jsonpath='{.status.phase}'=Running pod/web-7d5 --timeout=60s
kubectl wait --for=jsonpath='{.status.loadBalancer.ingress}' svc/web --timeout=5m
kubectl get pods --watch-only

Stream only future changes (skip the initial full list). Pairs well with scripts that react to new events.

Examples
kubectl get pods --watch-only
kubectl get pods --watch-only -o json | jq .status.phase
kubectl top node --sort-by=cpu

Rank nodes by CPU (or memory) usage so the hottest node floats to the top. Capacity-planning at a glance.

Examples
kubectl top node --sort-by=cpu
kubectl top node --sort-by=memory
Apply pipeline (23)
kubectl apply -f <file-or-dir>

Declaratively create or update resources from YAML / JSON. The recommended workflow.

Common pitfall: Pass `-` to read from stdin: `helm template ... | kubectl apply -f -`. Apply tracks fields via last-applied-configuration annotation — manual `kubectl edit` of those fields can confuse the next apply.

Examples
kubectl apply -f deployment.yaml
kubectl apply -f ./k8s/
kubectl apply -f - <<EOF
apiVersion: v1
kind: ConfigMap
...
EOF
kubectl apply -k <kustomize-dir>

Apply a Kustomize overlay. Built-in since 1.14, no separate `kustomize` binary needed.

Examples
kubectl apply -k ./overlays/prod
kubectl kustomize ./overlays/prod | kubectl apply -f -
kubectl create -f <file>

Imperatively create resources from YAML. Fails if the resource already exists.

Common pitfall: `create` is one-shot; `apply` is idempotent. For anything you re-run (CI/CD, git ops) use `apply`. Use `create` for things that must NOT silently update (Jobs).

Examples
kubectl create -f job.yaml
kubectl create -f - <<EOF
...
EOF
kubectl replace -f <file>

Replace a resource with the contents of a YAML — must exist already. --force triggers delete+recreate.

Common pitfall: `replace --force` causes a brief outage — pod is deleted, then recreated. Avoid for live traffic — use `apply` and rely on rolling update.

Examples
kubectl replace -f svc.yaml
kubectl replace --force -f pod.yaml
kubectl patch <resource> <name> -p '<json>'

Apply a partial update to a live resource without editing files. Strategic merge by default.

Common pitfall: Three merge types: --type=strategic (default, container-aware), --type=merge (RFC 7396), --type=json (RFC 6902 ops). Strategic only works for known core types — use merge for CRDs.

Examples
kubectl patch deployment web -p '{"spec":{"replicas":5}}'
kubectl patch pod web -p '{"metadata":{"labels":{"env":"prod"}}}'
kubectl patch deployment web --type=json -p='[{"op":"replace","path":"/spec/replicas","value":3}]'
kubectl edit <resource> <name>

Open a resource in $EDITOR; on save, the diff is applied. Quick & dirty — use with care.

Common pitfall: Edits do NOT update your git YAML — production drifts. For anything tracked in git, change the source and apply. Use edit only for quick experiments.

Examples
kubectl edit deployment web
KUBE_EDITOR="code -w" kubectl edit cm app-config
kubectl diff -f <file>

Preview what `apply` would change — server-side diff against the live state.

Examples
kubectl diff -f deployment.yaml
kubectl diff -k ./overlays/prod
kubectl label <resource> <name> KEY=VAL

Add, change, or remove (KEY-) a label on a resource. Used by selectors everywhere.

Examples
kubectl label pods web-7d5 env=prod
kubectl label pods web-7d5 env-
kubectl label nodes ip-10-0-1-23 disk=ssd
kubectl annotate <resource> <name> KEY=VAL

Add / change / remove (KEY-) an annotation. Free-form metadata, not used for selectors.

Examples
kubectl annotate pods web-7d5 owner=team-foo
kubectl annotate svc web service.beta.kubernetes.io/aws-load-balancer-type=nlb
kubectl delete -f <file>

Delete all resources defined in a YAML file or directory.

Common pitfall: `delete -f` of a namespace YAML deletes EVERYTHING in that namespace. Always `diff -f` before delete on prod paths.

Examples
kubectl delete -f deployment.yaml
kubectl delete -k ./overlays/staging
kubectl apply --server-side -f <file>

Apply using server-side apply — fields are owned by managers, conflicts are surfaced explicitly. Modern replacement for client-side apply.

Common pitfall: Conflicts (multiple managers touching the same field) abort the apply unless you pass --force-conflicts. Read the conflict report before forcing.

Examples
kubectl apply --server-side -f deployment.yaml
kubectl apply --server-side --force-conflicts -f deployment.yaml
kubectl rollout pause deployment/<name>

Pause / resume a rollout so multiple `set` / `patch` operations land as a single revision.

Examples
kubectl rollout pause deployment/web
kubectl set image deployment/web app=nginx:1.27 && kubectl set env deployment/web LOG=info && kubectl rollout resume deployment/web
kubectl set image deployment/<name> <ctr>=<img>

Update just the image of a container. Triggers a rolling update without editing YAML.

Common pitfall: `set image` modifies the live spec — drift from your git YAML. For tracked Deployments change the source and apply, not `set`.

Examples
kubectl set image deployment/web app=nginx:1.27
kubectl set image deploy/web app=myorg/app@sha256:abc123
kubectl rollout status deployment/<name> -w

Watch a rollout in real time until done. Exits non-zero on failure — perfect for CI gates.

Examples
kubectl rollout status deployment/web -w
kubectl apply -f deploy.yaml && kubectl rollout status deployment/web --timeout=3m
kubectl apply -f <file> --dry-run=server

Send the manifest to the API server for full validation (admission webhooks, defaulting) without persisting it.

Common pitfall: --dry-run=server catches admission/webhook rejections that --dry-run=client (local only) misses entirely. Use server-side in CI gates.

Examples
kubectl apply -f deployment.yaml --dry-run=server
kubectl apply -f deployment.yaml --dry-run=client -o yaml
kubectl apply -f <file> --prune -l <selector>

Apply a directory AND delete any live object with the matching label that is no longer in the files. GitOps-style sync.

Common pitfall: Prune is powerful and dangerous — a wrong selector can delete unrelated resources. Always `--dry-run=client` first and pin the label tightly.

Examples
kubectl apply -f ./k8s/ --prune -l app=web
kubectl apply -f ./k8s/ --prune -l app=web --dry-run=client
kubectl create -f <file> --dry-run=client -o yaml

Generate clean YAML from imperative flags without creating anything. The "imperative-to-declarative" bridge.

Common pitfall: This is the canonical way to scaffold YAML you do not remember by heart: `kubectl create deployment ... --dry-run=client -o yaml > deploy.yaml`, then edit.

Examples
kubectl create deployment web --image=nginx --dry-run=client -o yaml > deploy.yaml
kubectl create configmap c --from-literal=k=v --dry-run=client -o yaml
kubectl get <resource> <name> -o yaml --show-managed-fields

Reveal the managedFields block (hidden by default since 1.21) — see exactly which manager owns which field under server-side apply.

Common pitfall: When two controllers fight over a field, this block names the culprits. Pair with `kubectl apply --server-side --force-conflicts` to resolve.

Examples
kubectl get deployment web -o yaml --show-managed-fields
kubectl get deployment web -o jsonpath='{.metadata.managedFields[*].manager}'
kubectl delete <resource> --all -n <ns>

Delete every object of a kind in a namespace. e.g. clear all pods so controllers recreate them fresh.

Common pitfall: --all is namespace-scoped, NOT cluster-wide — but it still nukes everything of that kind in the namespace. Double-check `-n` before pressing enter.

Examples
kubectl delete pods --all -n staging
kubectl delete jobs --all -n batch
kubectl delete pods --all --grace-period=0 --force -n staging
kubectl delete <resource> <name> --cascade=orphan

Delete a controller (Deployment/StatefulSet) but leave its child pods running and unmanaged. Rare but handy for migrations.

Common pitfall: Orphaned pods now have NO controller — no self-healing, no rollout. You must adopt them under a new controller or clean up manually.

Examples
kubectl delete deployment web --cascade=orphan
kubectl delete statefulset db --cascade=orphan
kubectl rollout resume deployment/<name>

Resume a paused Deployment, flushing all the changes made while paused into a single new revision.

Examples
kubectl rollout resume deployment/web
kubectl rollout pause deploy/web && kubectl set image deploy/web app=nginx:1.27 && kubectl set resources deploy/web --limits=memory=512Mi && kubectl rollout resume deploy/web
kubectl kustomize <dir>

Render a Kustomize overlay to plain YAML on stdout WITHOUT applying. Inspect exactly what apply -k would send.

Examples
kubectl kustomize ./overlays/prod
kubectl kustomize ./overlays/prod | kubectl diff -f -
kubectl annotate <resource> <name> kubectl.kubernetes.io/last-applied-configuration-

Strip the stale last-applied-configuration annotation so a fresh client-side apply re-establishes field ownership cleanly.

Common pitfall: Useful when a resource was created with `create` (no annotation) then later `apply`-ed and behaves oddly on field deletion. Or migrate to server-side apply instead.

Examples
kubectl annotate deployment web kubectl.kubernetes.io/last-applied-configuration-
kubectl apply --server-side --force-conflicts -f deployment.yaml
Common errors (16)
ImagePullBackOff

Pod cannot pull its image. `describe pod` and read Events — almost always typo in tag, missing imagePullSecret, or registry DNS issue.

Common pitfall: BackOff is exponential — looks idle but is retrying with growing intervals. After fixing the cause, `kubectl delete pod` to reset the backoff timer immediately.

Examples
kubectl describe pod web-7d5 | tail -20
kubectl get events --sort-by=.lastTimestamp -n default
kubectl create secret docker-registry ghcr --docker-server=ghcr.io --docker-username=user --docker-password=$TOKEN
CrashLoopBackOff

Container starts then exits. `kubectl logs <pod> --previous` shows the actual error. Check Exit Code in describe.

Common pitfall: Exit codes: 0 = CMD ran to completion (your "server" is not a server), 1 = app threw, 137 = OOMKilled, 143 = SIGTERM not handled fast enough. Each implies a different fix.

Examples
kubectl logs web-7d5 --previous
kubectl describe pod web-7d5 | grep -A2 "Last State"
kubectl get pod web-7d5 -o jsonpath="{.status.containerStatuses[*].lastState}"
Evicted

Kubelet kicked the pod off the node — usually due to node pressure (disk full, memory pressure). Move to a healthier node and add requests/limits.

Common pitfall: Evicted pods pile up in `kubectl get pods` until cleaned — `kubectl delete pods --field-selector=status.phase=Failed` to bulk reap.

Examples
kubectl get pods --field-selector=status.phase=Failed -A
kubectl delete pods --field-selector=status.phase=Failed -A
kubectl describe node ip-10-0-1-23 | grep -A5 Conditions
OOMKilled (exit 137)

137 = 128 + SIGKILL(9). Kernel OOM killer reaped the container. Either bump memory limit or fix the leak.

Common pitfall: Set requests.memory close to typical use, limits.memory at the ceiling you can afford. JVM apps need `-XX:MaxRAMPercentage` or they ignore limits and eventually OOM.

Examples
kubectl get pod web-7d5 -o jsonpath="{.status.containerStatuses[*].lastState.terminated.reason}"
kubectl describe pod web-7d5 | grep -A2 "Limits:"
kubectl top pod web-7d5 --containers
Pending (unschedulable)

No node can satisfy the pod's requests / nodeSelector / taints. `describe pod` shows `FailedScheduling` with the reason.

Common pitfall: Common reasons: insufficient cpu/memory, no node with the right label, taints not tolerated, no PV available for a PVC. Each needs a different fix.

Examples
kubectl describe pod web-7d5 | grep -A5 Events
kubectl get nodes -o custom-columns=NAME:.metadata.name,CPU:.status.allocatable.cpu,MEM:.status.allocatable.memory
kubectl get nodes --show-labels
Terminating (stuck)

Pod is stuck in Terminating forever — almost always a finalizer that nothing is processing. Force-delete is the escape hatch.

Common pitfall: `kubectl delete pod web --grace-period=0 --force` skips graceful shutdown — endpoints may leak briefly. The right long-term fix is removing the finalizer via `kubectl patch`.

Examples
kubectl delete pod web-7d5 --grace-period=0 --force
kubectl patch pod web-7d5 -p '{"metadata":{"finalizers":null}}' --type=merge
kubectl get pod web-7d5 -o yaml | grep finalizers -A3
Init:0/N (stuck)

A pod's init container is failing or never finishing. `kubectl logs <pod> -c <init-name>` to see why.

Examples
kubectl logs web-7d5 -c wait-for-db
kubectl describe pod web-7d5 | grep -A5 "Init Containers"
ErrImagePull / no such host

A registry DNS variant of ImagePullBackOff. Your cluster DNS cannot resolve the registry hostname.

Common pitfall: Check `kubectl run dnsutils --rm -it --image=busybox -- nslookup ghcr.io`. If it fails, your CoreDNS or upstream is broken. Private registries often need an in-cluster DNS hostAlias.

Examples
kubectl run dnsutils --rm -it --image=busybox -- nslookup ghcr.io
kubectl logs -n kube-system -l k8s-app=kube-dns --tail=50
kubectl get pods -n kube-system -l k8s-app=kube-dns
CreateContainerConfigError

The container cannot start because a referenced ConfigMap/Secret key is missing. `describe pod` names the exact key.

Common pitfall: Different from ImagePullBackOff — the image pulled fine. It is a config wiring error: a `secretKeyRef`/`configMapKeyRef` points at a key that does not exist yet.

Examples
kubectl describe pod web-7d5 | grep -A3 Events
kubectl get secret db -o jsonpath='{.data}'
kubectl get cm app-config -o jsonpath='{.data}'
CreateContainerError

Kubelet failed to create the container — often a bad command, missing mount path, or a read-only root fs conflict.

Common pitfall: Read the message after the reason: "exec: no such file" = wrong command/entrypoint; "mkdir read-only file system" = the container tried to write where it cannot.

Examples
kubectl describe pod web-7d5 | grep -A2 "State:"
kubectl get pod web-7d5 -o jsonpath='{.status.containerStatuses[0].state.waiting.message}'
ContainerCreating (stuck)

Pod sits in ContainerCreating for minutes — usually a volume that will not mount, or an image still pulling.

Common pitfall: `FailedMount` in events = PVC not bound or a CSI driver issue. `FailedAttachVolume` on cloud = the EBS/PD volume is still attached to another (dead) node.

Examples
kubectl describe pod web-7d5 | grep -A5 Events
kubectl get pvc
kubectl get volumeattachment
exec format error

The container image was built for a different CPU architecture than the node (e.g. arm64 image on amd64 node).

Common pitfall: Classic on Apple Silicon — you build locally on arm64 and push to an amd64 cluster. Build multi-arch with `docker buildx build --platform linux/amd64,linux/arm64`.

Examples
kubectl logs web-7d5 --previous
kubectl get pod web-7d5 -o jsonpath='{.spec.nodeName}'
kubectl get node ip-10-0-1-23 -o jsonpath='{.status.nodeInfo.architecture}'
connection refused (probe failing)

Liveness/readiness probe keeps failing so the pod restarts or never gets traffic. The app is not listening on the probe port yet.

Common pitfall: Common cause: probe `port` does not match the actual listen port, or `initialDelaySeconds` is too short for a slow-booting app. Check the probe spec vs the real port.

Examples
kubectl describe pod web-7d5 | grep -A3 -i probe
kubectl get pod web-7d5 -o jsonpath='{.spec.containers[0].readinessProbe}'
kubectl exec web-7d5 -- wget -qO- localhost:8080/healthz
FailedScheduling: untolerated taint

A pod stays Pending because every candidate node has a taint the pod does not tolerate (e.g. a control-plane or GPU node).

Common pitfall: Add a matching `tolerations` block to the pod spec, or target untainted nodes. Control-plane nodes carry `node-role.kubernetes.io/control-plane:NoSchedule` by default.

Examples
kubectl describe pod web-7d5 | grep -A5 Events
kubectl get nodes -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.taints}{"\n"}{end}'
error: unable to upgrade connection (exec/logs)

kubectl exec/logs/port-forward fails to open the streaming connection — usually the kubelet is unreachable from the API server.

Common pitfall: On managed clusters this often means a security-group/firewall blocks apiserver→kubelet (port 10250), or the node is NotReady. Check node status and the SG rules.

Examples
kubectl get node ip-10-0-1-23
kubectl describe node ip-10-0-1-23 | grep -A5 Conditions
kubectl get pods -A --field-selector spec.nodeName=ip-10-0-1-23
NotReady (node)

A node reports NotReady — kubelet stopped posting status. Pods on it get marked Unknown then evicted after the toleration window.

Common pitfall: Common causes: kubelet crashed, disk/PID pressure, network partition, or the container runtime died. `describe node` Conditions and `journalctl -u kubelet` on the box tell the story.

Examples
kubectl get nodes
kubectl describe node ip-10-0-1-23 | grep -A8 Conditions
kubectl get pods -A -o wide --field-selector spec.nodeName=ip-10-0-1-23
YAML templates (11)
Pod YAML (minimal)

Bare Pod skeleton with resources and a single container. Copy and edit name/image.

Common pitfall: Bare pods are NOT managed — node failure drops them forever. Prefer Deployment unless you really need a one-off.

Examples
apiVersion: v1
kind: Pod
metadata:
  name: web
  labels:
    app: web
spec:
  containers:
  - name: app
    image: nginx:1.27-alpine
    ports:
    - containerPort: 80
    resources:
      requests: { cpu: 100m, memory: 128Mi }
      limits:   { cpu: 500m, memory: 256Mi }
Deployment YAML

Standard Deployment template with 3 replicas, rolling update strategy, probes, and resources.

Common pitfall: Missing readinessProbe + a slow-starting app = traffic hits the pod before it is ready = 502s on every rollout. Always add a real readinessProbe.

Examples
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
  labels: { app: web }
spec:
  replicas: 3
  selector:
    matchLabels: { app: web }
  strategy:
    type: RollingUpdate
    rollingUpdate: { maxSurge: 1, maxUnavailable: 0 }
  template:
    metadata:
      labels: { app: web }
    spec:
      containers:
      - name: app
        image: nginx:1.27-alpine
        ports: [{ containerPort: 80 }]
        readinessProbe:
          httpGet: { path: /, port: 80 }
          periodSeconds: 5
        livenessProbe:
          httpGet: { path: /, port: 80 }
          periodSeconds: 30
        resources:
          requests: { cpu: 100m, memory: 128Mi }
          limits:   { cpu: 500m, memory: 256Mi }
Service YAML

ClusterIP Service in front of a Deployment selected by label.

Common pitfall: targetPort can be a name (e.g. "http") matching a containerPort name — safer than a number when ports change between versions.

Examples
apiVersion: v1
kind: Service
metadata:
  name: web
spec:
  type: ClusterIP
  selector: { app: web }
  ports:
  - name: http
    port: 80
    targetPort: 80
ConfigMap + envFrom usage

A ConfigMap plus a Deployment snippet showing how to inject all its keys as env vars.

Common pitfall: ConfigMap changes do NOT auto-restart pods. After editing, `kubectl rollout restart deployment/<name>` to pick up the new values.

Examples
apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
data:
  LOG_LEVEL: info
  DATABASE_HOST: db.local
---
# In your Deployment template.spec.containers[0]:
envFrom:
- configMapRef:
    name: app-config
Ingress YAML (nginx class)

Ingress routing a host + path to a Service. Uses the nginx IngressClass.

Common pitfall: Without `ingressClassName: nginx` (or matching annotation) no controller picks it up — it sits there looking created but does nothing.

Examples
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: web
spec:
  ingressClassName: nginx
  rules:
  - host: web.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: web
            port:
              number: 80
CronJob YAML

A CronJob skeleton with schedule, concurrency policy, history limits, and a single-container job template.

Common pitfall: Without `concurrencyPolicy: Forbid` a slow job can overlap with the next scheduled run. Without history limits, completed Jobs pile up forever.

Examples
apiVersion: batch/v1
kind: CronJob
metadata:
  name: backup
spec:
  schedule: "0 2 * * *"
  concurrencyPolicy: Forbid
  successfulJobsHistoryLimit: 3
  failedJobsHistoryLimit: 1
  jobTemplate:
    spec:
      backoffLimit: 2
      template:
        spec:
          restartPolicy: Never
          containers:
          - name: backup
            image: backup:1.0
            command: ["/backup.sh"]
Job YAML

A run-to-completion Job with parallelism, completions, a backoff limit, and an activeDeadline timeout.

Common pitfall: restartPolicy MUST be Never or OnFailure for a Job (Always is rejected). backoffLimit caps total retries before the Job is marked Failed.

Examples
apiVersion: batch/v1
kind: Job
metadata:
  name: migrate
spec:
  completions: 1
  parallelism: 1
  backoffLimit: 3
  activeDeadlineSeconds: 600
  template:
    spec:
      restartPolicy: Never
      containers:
      - name: migrate
        image: migrate:1.0
        command: ["/run-migration.sh"]
HorizontalPodAutoscaler YAML (v2)

An autoscaling/v2 HPA targeting CPU and memory utilization, with explicit min/max and a scale-down stabilization window.

Common pitfall: autoscaling/v2 (not v2beta2) is stable since 1.23. Multiple metrics mean the HPA scales on whichever demands the MOST replicas. Needs metrics-server.

Examples
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: web
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: web
  minReplicas: 2
  maxReplicas: 10
  behavior:
    scaleDown:
      stabilizationWindowSeconds: 300
  metrics:
  - type: Resource
    resource:
      name: cpu
      target: { type: Utilization, averageUtilization: 70 }
  - type: Resource
    resource:
      name: memory
      target: { type: Utilization, averageUtilization: 80 }
PersistentVolumeClaim YAML

A PVC requesting storage from a named StorageClass with an access mode. Mount it in a pod via volumes + volumeMounts.

Common pitfall: ReadWriteOnce binds to ONE node at a time — two pods on different nodes cannot share it. For shared access you need ReadWriteMany and a backing store that supports it (NFS, EFS, CephFS).

Examples
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: data
spec:
  accessModes: ["ReadWriteOnce"]
  storageClassName: gp3
  resources:
    requests:
      storage: 10Gi
NetworkPolicy YAML (default-deny + allow)

A default-deny-ingress policy plus an allow rule that only lets pods labeled role=frontend reach this app on port 8080.

Common pitfall: NetworkPolicies are additive (allow-only) and require a CNI that enforces them. An empty `podSelector: {}` with no ingress rules = deny ALL ingress to the namespace.

Examples
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-ingress
spec:
  podSelector: {}
  policyTypes: ["Ingress"]
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-frontend
spec:
  podSelector:
    matchLabels: { app: web }
  policyTypes: ["Ingress"]
  ingress:
  - from:
    - podSelector:
        matchLabels: { role: frontend }
    ports:
    - protocol: TCP
      port: 8080
ServiceAccount + RBAC YAML

A ServiceAccount, a namespaced Role granting pod read access, and a RoleBinding wiring them together. Least-privilege starter.

Common pitfall: The RoleBinding subject `kind: ServiceAccount` needs the SA's namespace in `subjects[].namespace`, or the binding silently grants nothing.

Examples
apiVersion: v1
kind: ServiceAccount
metadata:
  name: pod-reader
  namespace: app
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: pod-reader
  namespace: app
rules:
- apiGroups: [""]
  resources: ["pods", "pods/log"]
  verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: pod-reader
  namespace: app
subjects:
- kind: ServiceAccount
  name: pod-reader
  namespace: app
roleRef:
  kind: Role
  name: pod-reader
  apiGroup: rbac.authorization.k8s.io

What this tool does

Searchable kubectl cheat sheet covering the 100+ commands SREs and platform engineers actually run on a real cluster — not the toy "hello-minikube" list. Ten categories: cluster (cluster-info, get nodes, top nodes, config use-context, version, api-resources), pod (get pods, describe, logs -f, exec -it, port-forward, cp, attach, delete, debug ephemeral container), workload (deployment / replicaset / daemonset / statefulset create, scale, rollout status / history / undo / restart, autoscale, expose), service &amp; ingress (expose, get svc, endpoints, port-forward, ingress class hint), config (configmap and secret create from-file / from-literal, get, decode), RBAC (get sa, create role / rolebinding / clusterrole / clusterrolebinding, auth can-i, namespaces), monitoring (top pods, events --sort-by, wait --for=condition), apply pipeline (apply, create, replace, patch strategic / json / merge, edit, diff, kustomize, label, annotate), pitfall fixes for the eight states that actually break your day (ImagePullBackOff, ErrImagePull, CrashLoopBackOff, Evicted, OOMKilled, Pending unschedulable, Terminating stuck, Init:0/N stuck), and 5 ready-to-paste YAML templates (Pod, Deployment, Service, ConfigMap, Ingress). Every entry shows full syntax, bilingual EN/ZH description, the trap people actually hit ("--grace-period=0 leaves dangling endpoints", "exec defaults to sh — alpine has no bash", "rollout restart is preferred over delete pod", "kubectl apply -f - reads from stdin"), and one to three copy-ready examples. Search filters across command + description + pitfall + example simultaneously, category chips scope the list, one-click copy on every command. Fully client-side, no cluster access, no upload, no telemetry. Pair with our Docker and Git Cheatsheets, and reach for kubectx / kubens / k9s / helm / stern when the raw CLI feels heavy.

Tool details

Input
Files + Text
The page exposes text boxes, numeric controls, file pickers, or structured inputs depending on the tool.
Output
Live result + Copy + Preview
The result area focuses on usable output, with copy, download, or preview actions when supported.
Privacy
Browser-side processing
The main tool logic does not call an external API, so inputs normally stay in the current tab.
Save / share
No account required
Open the page and use it; whether results survive refresh depends on the tool.
Performance budget
Initial JS <= 30 KB
No WASM budget is declared, keeping the tool quick to open on mobile.
Best fit
Developer & DevOps · Developer
Category and role tags drive related tools, internal links, and quick fit checks.

How to use

  1. 1. Input

    Paste or drop your content into the tool panel.

  2. 2. Process

    Click the button. All processing is local in your browser.

  3. 3. Copy / Download

    Copy the result or download to disk in one click.

How kubectl Cheatsheet fits into your work

Use it in the small gaps between coding, reviewing, debugging, and shipping.

Developer jobs

  • Formatting, validating, shrinking, or inspecting code-adjacent text.
  • Preparing snippets for documentation, tickets, commits, or handoff.
  • Checking a small payload quickly without switching tools.

Developer checks

  • Run irreversible transforms like minify or obfuscate on a copy.
  • Keep secrets out of pasted snippets unless the tool explicitly stays local.
  • Use your normal tests or linter before shipping transformed code.

Good next steps

These links move the current task into a more complete workflow.

  1. 1 YAML Formatter & Validator Format and beautify YAML — re-indent, validate, minify, sort keys. Open
  2. 2 Docker Cheatsheet Docker command cheat sheet — 80+ commands with real examples, common mistakes, and Compose section. Open
  3. 3 Git Cheatsheet Git command cheat sheet — searchable, with explanations, common mistakes, and real examples. Open

Real-world use cases

  • A pod went CrashLoopBackOff at 2am and you need the exit code fast

    On-call, no time to think. Search "137" to jump straight to the OOMKilled entry, copy `kubectl logs <pod> --previous` to read the last run before the crash, then copy `describe pod` to read the Exit Code line. Three clicks, no man-page detour, and you know whether to bump the memory limit or fix your CMD.

  • Onboarding a junior who has never touched a cluster

    Filter to Pod and Workload, hand them the fifteen day-one commands top to bottom: get pods, describe, logs -f, exec -it, port-forward, rollout restart, rollout status. Each carries the pitfall inline, so they learn "exec defaults to sh, alpine has no bash" before they hit a 127 in front of the whole team.

  • Piping a Helm template straight into apply on a locked-down jump host

    You cannot install helm on the bastion but you can render locally. Grab the `apply -f -` entry, read the "reads from STDIN" note, and run `helm template release ./chart | kubectl apply -f -`. The cheat sheet confirms the dash means stdin so you do not waste a round trip guessing whether kubectl wants a real file path.

  • Restarting a single-replica deployment without dropping to zero

    A teammate is about to `kubectl delete pod` on a 1-replica service in prod. Search "restart", copy `rollout restart deployment/<name>`, and the entry explains why: delete briefly hits 0 replicas and leaves no rollout history, while restart honors maxUnavailable and keeps `rollout undo` available.

Common pitfalls

  • Running `kubectl logs <pod>` on a crashed pod shows the new container, not the crash; add `--previous` to see the run that actually failed.

  • Using `kubectl exec -it pod -- bash` on alpine or distroless returns exit 127; try `sh` first, or `kubectl debug` for images with no shell at all.

  • Forcing `delete pod --grace-period=0 --force` to unstick Terminating leaves dangling endpoints; fix the finalizer or stuck volume instead of force-killing.

Privacy

This cheat sheet is a single static page. Your search terms, the commands you copy, and any YAML you read stay in the browser tab and run against an in-memory array. Nothing touches your kubeconfig, no cluster is contacted, and no search text enters the URL. Open DevTools Network while you type and you will see zero requests, so it is safe on air-gapped jump hosts and bastion-only clusters.

FAQ

Tool combos

Folks in your role tend to reach for these alongside this tool.

Made by Toolora · 100% client-side · Updated 2026-06-13