Kubernetes cheat sheet
A scannable Kubernetes reference: 34 short snippets across 14 topics, each linking back to the lesson it came from.
At a glance
| Topic | What it covers | |
|---|---|---|
| Pods, Deployments and Services | The Pod is the smallest schedulable unit. Its containers share one network namespace, so they reach each other on | lesson |
| ConfigMaps, Secrets and probes | Configuration belongs in a ConfigMap rather than in the image, so the same image can run in every environment | lesson |
| Rollouts and debugging | Updating a Deployment's pod template starts a rolling update. Kubernetes brings new pods up and old ones down according | lesson |
| Cluster architecture and a local setup | A Kubernetes cluster is a set of machines split into a control plane that holds the desired state and makes decisions | lesson |
| kubectl fundamentals and writing manifests | An imperative command tells the cluster what to do once. A declarative file describes what should exist, for ever. Only | lesson |
| Labels, selectors, namespaces and annotations | A label is a key-value pair attached to an object. A selector is a query over labels. Almost every relationship in | lesson |
| Storage: volumes, PersistentVolumes and StorageClasses | Containers are disposable and their filesystem disappears with them. A volume is declared on the pod and mounted into | lesson |
| StatefulSets, DaemonSets and Jobs | A Deployment generates pods with random suffixes, starts them in any order and treats them as interchangeable. A | lesson |
| Ingress, Gateway API and exposing applications | Ingress is a routing rule expressed as a Kubernetes object. On its own it does nothing. You also need an Ingress | lesson |
| Resource requests, limits and autoscaling | A request is what the scheduler reserves on a node and what the autoscaler measures against. A limit is the ceiling the | lesson |
| Networking, DNS and NetworkPolicy | Kubernetes assumes a flat network with three simple rules: every pod gets its own IP, every pod can reach every other | lesson |
| RBAC, service accounts and pod security | Authorization is a decision the API server makes on every request: does this identity have this verb on this resource | lesson |
| Helm and packaging applications | A Helm chart is a parameterised bundle of manifests. A release is one installed instance of that chart in a namespace | lesson |
| Scheduling: affinity, taints and tolerations | The scheduler runs two phases: filtering, which removes nodes that cannot run the pod, and scoring, which ranks the | lesson |
Quick snippets
Pods, Deployments and Services
Pods
kubectl apply -f pod.yaml
kubectl get pods -o wide
kubectl describe pod web
kubectl delete pod web
Services
apiVersion: v1
kind: Service
metadata:
name: web
spec:
type: ClusterIP # ClusterIP | NodePort | LoadBalancer
selector:
app: web
ports:
- port: 80 # the port clients of the Service use
targetPort: 80 # the container port behind it
Services
kubectl get svc
kubectl get endpoints web # an empty list means the selector matches nothing
kubectl port-forward svc/web 8080:80
# other pods address it by DNS name:
# http://web.<namespace>.svc.cluster.localFull lesson: Pods, Deployments and Services →
ConfigMaps, Secrets and probes
ConfigMaps
apiVersion: v1
kind: ConfigMap
metadata:
name: web-config
data:
LOG_LEVEL: info
nginx.conf: |
server {
listen 80;
location / { return 200 "ok"; }
}
Secrets
kubectl create secret generic db-creds \
--from-literal=username=app \
--from-literal=password='s3cr3t'
kubectl get secret db-creds -o jsonpath='{.data.password}' | base64 -dFull lesson: ConfigMaps, Secrets and probes →
Rollouts and debugging
Rollouts
kubectl set image deployment/web web=nginx:1.28-alpine
kubectl rollout status deployment/web # blocks until finished
kubectl rollout history deployment/web
kubectl rollout undo deployment/web # back to the previous revision
kubectl rollout undo deployment/web --to-revision=3
kubectl rollout restart deployment/web # restart pods without changing the spec
Debugging a failing pod
kubectl get pods -w
kubectl describe pod web-7d9c8b6f4-abcde # events are at the bottom
kubectl logs web-7d9c8b6f4-abcde
kubectl logs web-7d9c8b6f4-abcde --previous # the container that crashed
kubectl exec -it web-7d9c8b6f4-abcde -- sh
kubectl get events --sort-by=.lastTimestampFull lesson: Rollouts and debugging →
Cluster architecture and a local setup
Everything talks to the API server
kubectl cluster-info # which cluster am I even talking to
kubectl version # client and server versions
kubectl config current-context
kubectl get nodes -o wide # kubelet version, IPs, runtime
kubectl get --raw='/readyz?verbose' # control plane component health
kubectl api-resources # every kind the server knows, and its scope
A real cluster on your laptop
# kubeconfig lives at $KUBECONFIG or ~/.kube/config
export KUBECONFIG=~/.kube/config:~/.kube/kind-dev
kubectl config set-context --current --namespace=dev
kubectl config view --minify # just the context you are usingFull lesson: Cluster architecture and a local setup →
kubectl fundamentals and writing manifests
Declarative versus imperative
# generate a skeleton, then own it as a file
kubectl create deployment web --image=nginx:1.27-alpine --replicas=3 \
--dry-run=client -o yaml > deploy.yaml
kubectl apply -f deploy.yaml
kubectl get deploy,pods -o wide
kubectl describe deploy web
The anatomy of a manifest
kubectl explain deployment.spec.strategy.rollingUpdate
kubectl explain pod.spec.containers.resources --recursive | head -40
The apply, diff and dry-run loop
kubectl apply -f deploy.yaml --dry-run=client # syntax only, no server
kubectl apply -f deploy.yaml --dry-run=server # schema + admission, no write
kubectl diff -f deploy.yaml # exactly what would change
kubectl apply -f deploy.yaml
kubectl apply -f manifests/ -R --prune -l env=dev # directory, recursive, prune removed objectsFull lesson: kubectl fundamentals and writing manifests →
Labels, selectors, namespaces and annotations
Labels and selectors are how objects find each other
metadata:
labels:
app.kubernetes.io/name: web
app.kubernetes.io/instance: web-prod
app.kubernetes.io/version: "1.27"
app.kubernetes.io/component: frontend
app.kubernetes.io/part-of: storefront
app.kubernetes.io/managed-by: helm
environment: prod
track: stable
Labels and selectors are how objects find each other
kubectl get pods --show-labels
kubectl get pods -l 'app.kubernetes.io/name=web,environment in (prod,staging)'
kubectl get pods -l '!canary'
kubectl label pod web-abc123 track=stable
kubectl label pod web-abc123 track- # remove a label
kubectl get pods -l app=web --field-selector status.phase=Running
Namespaces divide names, not networks
kubectl create namespace team-a
kubectl get namespaces
kubectl get pods -n team-a
kubectl get pods --all-namespaces
kubectl config set-context --current --namespace=team-a
kubectl get pods -A -o custom-columns=NS:.metadata.namespace,NAME:.metadata.name
# a common pattern: one namespace per team or per environment
kubectl create namespace storefront-staging
kubectl create namespace storefront-prodFull lesson: Labels, selectors, namespaces and annotations →
Storage: volumes, PersistentVolumes and StorageClasses
StorageClasses and StatefulSets
kubectl get storageclass
kubectl get pv,pvc -n storefront-prod
kubectl describe pvc pgdata -n storefront-prod # events explain Pending
kubectl get pvc pgdata -o jsonpath='{.spec.resources.requests.storage}'Full lesson: Storage: volumes, PersistentVolumes and StorageClasses →
StatefulSets, DaemonSets and Jobs
Jobs and CronJobs
kubectl get jobs -w
kubectl logs job/migrate
kubectl describe job migrate # events show why a pod was retried
kubectl get cronjobs
kubectl create job --from=cronjob/nightly-report manual-run-1Full lesson: StatefulSets, DaemonSets and Jobs →
Ingress, Gateway API and exposing applications
An Ingress object is only half the story
# the controller is a normal workload; install it once per cluster
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm install ingress-nginx ingress-nginx/ingress-nginx -n ingress-nginx --create-namespace
kubectl get pods -n ingress-nginx
kubectl get ingressclass
kubectl get svc -n ingress-nginx # the LoadBalancer the whole world hits
Hosts, paths and TLS
kubectl get ingress
kubectl describe ingress storefront # shows each rule and the resolved backend
kubectl get endpoints api # an ingress with no endpoints returns 503Full lesson: Ingress, Gateway API and exposing applications →
Resource requests, limits and autoscaling
Requests, limits and QoS
spec:
containers:
- name: api
image: ghcr.io/example/api:2.1.0
resources:
requests:
cpu: 250m # 0.25 of a core, reserved on the node
memory: 256Mi # used for scheduling and eviction ordering
limits:
cpu: "1" # throttled above this, never killed
memory: 512Mi # exceeded means OOMKilled
Requests, limits and QoS
kubectl top pods -n storefront
kubectl top nodes
kubectl get pod api-abc -o jsonpath='{.status.qosClass}'
kubectl describe pod api-abc | grep -A3 Limits
Vertical scaling, cluster scaling and disruption
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: api
spec:
minAvailable: 2 # or maxUnavailable: 1
selector:
matchLabels:
app: apiFull lesson: Resource requests, limits and autoscaling →
Networking, DNS and NetworkPolicy
The cluster network model
kubectl get pods -o wide # pod IPs and the node each runs on
kubectl get svc -A # ClusterIP, and ExternalIP if any
kubectl get svc kubernetes -o jsonpath='{.spec.clusterIP}'
kubectl get nodes -o custom-columns=NAME:.metadata.name,PODCIDR:.spec.podCIDR
kubectl get endpointslices -l kubernetes.io/service-name=web
CoreDNS and how names resolve
# what a pod's resolver actually contains
kubectl exec -it web-abc -- cat /etc/resolv.conf
# nameserver 10.96.0.10
# search storefront.svc.cluster.local svc.cluster.local cluster.local
# options ndots:5
CoreDNS and how names resolve
spec:
dnsPolicy: ClusterFirst
dnsConfig:
options:
- name: ndots
value: "2"
- name: timeout
value: "2"Full lesson: Networking, DNS and NetworkPolicy →
RBAC, service accounts and pod security
RBAC: roles, bindings and verbs
kubectl auth can-i get pods -n storefront --as=system:serviceaccount:storefront:ci
kubectl auth can-i --list -n storefront --as=system:serviceaccount:storefront:ci
kubectl create role deployer --verb=get,list,watch,update --resource=deployments -n storefront
kubectl describe clusterrole cluster-admin # note the wildcards
Service accounts and token projection
kubectl create serviceaccount api -n storefront
kubectl get serviceaccounts -A
kubectl get rolebindings,clusterrolebindings -A -o wide | grep storefront
kubectl auth whoami --as=system:serviceaccount:storefront:api
Keeping containers unprivileged
# enforce a baseline on a namespace, with a visible warning first
kubectl label namespace storefront \
pod-security.kubernetes.io/enforce=restricted \
pod-security.kubernetes.io/enforce-version=latest \
pod-security.kubernetes.io/warn=restricted \
pod-security.kubernetes.io/audit=restricted
kubectl get pod api-abc -o jsonpath='{.spec.securityContext}'Full lesson: RBAC, service accounts and pod security →
Helm and packaging applications
Charts and releases
storefront/
Chart.yaml # name, version, appVersion, dependencies
values.yaml # defaults for every template variable
charts/ # vendored subcharts
templates/
_helpers.tpl # named templates you can include
NOTES.txt # printed after a successful install
deployment.yaml
service.yaml
ingress.yaml
tests/test-connection.yaml
.helmignore
Charts and releases
helm create storefront
helm lint ./storefront
helm template storefront ./storefront --debug | less # render locally, no cluster
helm install storefront ./storefront -n storefront --create-namespace
helm list -A
helm status storefront -n storefront
helm get values storefront -n storefront
helm get manifest storefront -n storefront # what is actually deployed
Templates and values
# values.yaml
replicaCount: 2
image:
repository: ghcr.io/example/storefront
tag: "" # empty means use .Chart.AppVersion
resources:
requests:
cpu: 100m
memory: 128Mi
ingress:
enabled: falseFull lesson: Helm and packaging applications →
Scheduling: affinity, taints and tolerations
Taints and tolerations
kubectl taint nodes node-1 dedicated=gpu:NoSchedule
kubectl taint nodes node-1 dedicated=gpu:NoSchedule- # remove
kubectl describe node node-1 | grep -A4 Taints
kubectl label nodes node-1 node-pool=gpu
Taints and tolerations
spec:
nodeSelector:
node-pool: gpu
tolerations:
- key: dedicated
operator: Equal
value: gpu
effect: NoSchedule
containers:
- name: trainer
image: ghcr.io/example/trainer:0.9.1
Topology spread, priority and node maintenance
kubectl cordon node-1 # stop new pods being scheduled
kubectl drain node-1 --ignore-daemonsets --delete-emptydir-data
kubectl uncordon node-1
kubectl get pods -A -o wide --field-selector spec.nodeName=node-1
kubectl get pdb -A # what drain must respectFull lesson: Scheduling: affinity, taints and tolerations →
FAQ
Is this Kubernetes cheat sheet free to use?
Where do the examples come from?
How do I go deeper than a cheat sheet?
Related cheat sheets
Git Linux Docker Nginx CI / CD Bash Scripting
Last refreshed 2026-09-27.