The exact kubectl command and flag for each task, grouped the way you work at a terminal, for
kubectl v1.37. What the objects are and why they behave as they do is in
Kubernetes; chart releases are driven with
Helm commands.
Setup
Platform
Install
macOS
brew install kubectl
Windows
winget install -e --id Kubernetes.kubectl
Debian, Ubuntu, Fedora
the pkgs.k8s.io package repository, one per minor version (see the install guide)
Swap amd64 for arm64 on ARM, or $v for a fixed version such as v1.37.2.
Command
Shows
kubectl version
client and server versions; warns when they are more than one minor apart
kubectl version --client
client only, no cluster needed
kubectl cluster-info
API server and CoreDNS addresses
kubectl get --raw='/readyz?verbose'
API server health checks, one per line
kubectl api-versions
every group/version the server serves
Version skew: kubectl is supported within one minor version of the API server, older or
newer, so a v1.37 client covers 1.36 to 1.38 control planes.
Kubeconfig and contexts
A kubeconfig file lists clusters (API URL and CA), users (credentials) and contexts
(a cluster, a user and a default namespace), plus the current-context.
A context names a cluster, a user and a namespace; current-context picks the one kubectl uses.
Source
Used when
--kubeconfig ./ci.yaml
given: only that file
KUBECONFIG=~/.kube/a:~/.kube/b
set: files merged, the first file to set a value wins (; on Windows)
az aks get-credentials --resource-group rg --name prod
kind
kind export kubeconfig --name dev
k3s
copy /etc/rancher/k3s/k3s.yaml from the server and fix its server: address
kubectx and kubens
Install with brew install kubectx or kubectl krew install ctx ns (then kubectl ctx,
kubectl ns). With fzf installed, running either without arguments opens a picker.
Command
Does
kubectx
list contexts
kubectx prod
switch
kubectx -
back to the previous context
kubectx -c
print the current one
kubectx prod=gke_acme_europe-west1_prod
rename
kubectx -d old
delete
kubens web, kubens -, kubens -c
the same for the namespace
Command anatomy
kubectl get deploy/api -n web -o yaml verb TYPE/NAME flags
Form
Example
TYPE
kubectl get pods
TYPE NAME…
kubectl get pod api-7d9f web-5c2b
TYPE/NAME…
kubectl get deploy/api svc/api
TYPE1,TYPE2
kubectl get deploy,svc,cm -l app=api
TYPE.GROUP
kubectl get certificates.cert-manager.io: disambiguates kinds with the same name
TYPE.VERSION.GROUP
kubectl get deployments.v1.apps
-f FILE, a directory, a URL or -
kubectl get -f k8s/
-k DIR
objects from a kustomization
Global flag
Does
-n web, -A
namespace, all namespaces
--context prod, --kubeconfig f
which cluster and credentials
--as jane, --as-group devs
impersonate (needs the impersonate permission)
--request-timeout=10s
give up on slow API calls
-v=6
log request URLs and status codes; -v=8 adds bodies, -v=9 everything
kubectl options
list every global flag
Short names
Short
Kind
Short
Kind
po
pods
deploy
deployments
rs
replicasets
sts
statefulsets
ds
daemonsets
cj
cronjobs
svc
services
ing
ingresses
ep
endpoints (prefer endpointslices)
netpol
networkpolicies
cm
configmaps
sa
serviceaccounts
pv
persistentvolumes
pvc
persistentvolumeclaims
sc
storageclasses
ns
namespaces
no
nodes
ev
events
hpa
horizontalpodautoscalers
pdb
poddisruptionbudgets
crd
customresourcedefinitions
pc
priorityclasses
quota
resourcequotas
limits
limitranges
csr
certificatesigningrequests
Secrets, Jobs, Roles and RoleBindings have no short name.
Discovering kinds and fields
Command
Shows
kubectl api-resources
every kind: short names, API group, namespaced or not
JSONPath has no regular expressions: pipe -o json into jq for those. On Windows, wrap the
template in double quotes and use single quotes inside it.
# name and node of every Pod, tab-separatedt='{range .items[*]}{.metadata.name}{"\t"}'t+='{.spec.nodeName}{"\n"}{end}'kubectl get pods -o jsonpath="$t"# Pods with their image(s), as a tablekubectl get pods -o custom-columns=\'POD:.metadata.name,IMAGE:.spec.containers[*].image'
metadata.name and metadata.namespace work on every kind
Pod field selectors also accept spec.restartPolicy, spec.serviceAccountName,
status.podIP; Events accept involvedObject.name, involvedObject.kind, reason, type.
Creating and changing
apply and diff
Command
Does
kubectl apply -f app.yaml
create or update; client-side apply keeps a last-applied-configuration annotation
kubectl apply -f k8s/ -R
a directory tree
kubectl apply -k overlays/prod
a kustomization
kubectl apply -f https://example.com/x.yaml
from a URL
kubectl apply --server-side -f app.yaml
server-side apply: the API server merges and records field owners
--field-manager=ci
the owner name recorded for your fields (SSA default kubectl)
--force-conflicts
take fields another manager owns
--dry-run=server
full validation and admission, nothing stored
--dry-run=client
local only, no cluster checks
--validate=strict
the default: unknown or duplicate fields fail; warn, ignore
kubectl apply --prune -l app=api -f k8s/
also delete labeled objects no longer in the files; easy to get wrong, test with --dry-run=server
kubectl diff -f k8s/
what apply would change; exit 0 none, 1 changes, above 1 error
create an HPA; --memory=80%; --cpu-percent is deprecated
kubectl get hpa -w
watch targets and replica counts
status, history, undo and restart work on Deployments, DaemonSets and StatefulSets.
restart sets a kubectl.kubernetes.io/restartedAt annotation on the Pod template, which is
also why it is the usual way to pick up changed ConfigMap or Secret values.
1/5
A Deployment with 3 replicas owns ReplicaSet api-7d9f (revision 1), which keeps 3 Pods of image 1.4.2 running.
Logs, exec and port-forward
kubectl logs
Does
kubectl logs api-7d9f
a single-container Pod
-c api, --all-containers
one container, all of them
-f
follow
-p, --previous
the previous, crashed instance
--since=10m, --since-time=2026-11-11T09:00:00Z
recent lines only
--tail=100
last N lines; default all, but 10 when you use -l
--timestamps, --prefix
add timestamps, [pod/name/container]
-l app=api -f --max-log-requests=10
several Pods by label; following is capped at 5 streams by default
kubectl logs deploy/api
one Pod of a Deployment, Job or Service
kubectl logs deploy/api --all-pods
every Pod of it, prefixed
--limit-bytes=1048576
cap the output
Command
Does
kubectl exec -it api-7d9f -- sh
interactive shell; everything after -- is the command
a Pod in the node's namespaces; node filesystem at /host (chroot /host)
--profile=sysadmin
privileged; others: general (default), baseline, restricted, netadmin
--custom=debug.yaml
a partial container spec merged into the debug container (env, mounts, security context)
Ephemeral containers can't be removed: they stay in the Pod until it is deleted. Node debug
Pods (node-debugger-worker-2-…) and --copy-to copies stay until you delete them.
Events and usage
Command
Does
kubectl events -n web
namespace events, oldest first
kubectl events --for pod/api-7d9f
one object
kubectl events --for deploy/api -w
then keep watching
kubectl events -A --types=Warning
only warnings, everywhere
kubectl get events --sort-by=.metadata.creationTimestamp
the older way; also .lastTimestamp
kubectl get events --field-selector involvedObject.name=api-7d9f
by object, server-side
kubectl top pods -A --sort-by=memory
live usage; --sort-by=cpu
kubectl top pod api-7d9f --containers
per container
kubectl top pods --sum
adds a total row
kubectl top nodes
node usage; --show-capacity uses capacity instead of allocatable
kubectl get --raw /api/v1/nodes/worker-2/proxy/stats/summary
the kubelet's stats through the API server
Events are kept for about an hour by default. top needs metrics-server and shows a short
recent average, not a peak.
See the status-by-status flowchart in Kubernetes debugging
for what to look at once you have the output.
Nodes
Command
Does
kubectl get nodes -o wide
versions, internal IPs, OS, container runtime
kubectl get nodes -L topology.kubernetes.io/zone,node.kubernetes.io/instance-type
labels as columns
kubectl describe node worker-2
conditions, taints, capacity, allocated requests and limits
kubectl get pods -A -o wide --field-selector spec.nodeName=worker-2
A plugin is any executable named kubectl-name on your PATH; kubectl name runs it
(kubectl-foo-bar becomes kubectl foo bar). kubectl plugin list shows what it finds.
krew is the plugin manager: install it with brew install krew or the script on the krew
site, then add ${KREW_ROOT:-$HOME/.krew}/bin to your PATH.
Command
Does
kubectl krew update
refresh the plugin index
kubectl krew search log
find plugins
kubectl krew install ctx ns neat
install
kubectl krew list, info tree
installed plugins, details of one
kubectl krew upgrade
upgrade all
kubectl krew uninstall neat
remove
Plugin
Does
Example
ctx, ns
kubectx and kubens
kubectl ns web
neat
strips status, managed fields and defaults from YAML
kubectl get deploy api -o yaml | kubectl neat
tree
ownership tree (Deployment, ReplicaSets, Pods)
kubectl tree deploy api
stern
tail many Pods at once, colored
kubectl stern api -n web
view-secret
decode a Secret
kubectl view-secret db password
who-can
which subjects hold a permission
kubectl who-can get secrets -n web
resource-capacity
requests, limits and usage per node
kubectl resource-capacity --util
node-shell
root shell on a node
kubectl node-shell worker-2
df-pv
disk usage of PersistentVolumes
kubectl df-pv
get-all
every object, beyond get all
kubectl get-all --namespace=web
Outside kubectl, k9s is a terminal UI for the same tasks (k9s -n web).
kuberc (~/.kube/kuberc, or the file in KUBERC; KUBERC=off disables it) holds kubectl
preferences separate from cluster credentials: default flags per command and your own aliases.
Flags you type still win.
kubectl kuberc view prints it; kubectl kuberc set --section aliases --name getn --command get --prependarg nodes --option output=wide writes the same alias for you.
Quick lookup
I want to…
Command
switch cluster
kubectl config use-context prod or kubectx prod
switch default namespace
kubectl config set-context --current --namespace=web or kubens web
see which cluster I'm on
kubectl config current-context
list everything running
kubectl get pods -A -o wide
find a Pod by label
kubectl get pods -l app=api -o wide
see why a Pod is Pending
kubectl describe pod P (Events at the bottom)
see why a Pod crashed
kubectl logs P --previous
follow logs of a Deployment
kubectl logs deploy/api -f --all-pods
get a shell
kubectl exec -it P -- sh
debug a distroless Pod
kubectl debug -it P --image=busybox:1.37 --target=CONTAINER
open a Service locally
kubectl port-forward svc/api 8080:80
preview a change
kubectl diff -f k8s/
apply a directory
kubectl apply -f k8s/ -R
scaffold a manifest
kubectl create deploy api --image=x --dry-run=client -o yaml
change an image
kubectl set image deploy/api api=ghcr.io/acme/api:1.4.3
restart Pods
kubectl rollout restart deploy/api
undo a bad rollout
kubectl rollout undo deploy/api
scale
kubectl scale deploy/api --replicas=5
run a CronJob now
kubectl create job manual-1 --from=cronjob/report
decode a Secret
kubectl get secret db -o jsonpath='{.data.password}' | base64 -d
copy a file out
kubectl cp P:/path/file ./file
see recent warnings
kubectl events -A --types=Warning
see CPU and memory
kubectl top pods -A --sort-by=cpu
check what I may do
kubectl auth can-i --list -n web
check a ServiceAccount's rights
kubectl auth can-i get secrets --as=system:serviceaccount:web:api
find which API group a kind is in
kubectl api-resources | grep -i gateway
read a field's docs
kubectl explain deploy.spec.strategy
get one field
kubectl get pod P -o jsonpath='{.status.podIP}'
sort by age
kubectl get pods --sort-by=.metadata.creationTimestamp