CertGrid CertGrid

CKAD command cheat sheet

The commands a CKAD task actually needs, grouped by what you are trying to do - generate a manifest, change a live object, wire in configuration, expose something, and find out why it is broken. Every output below is from a real session on the path's cluster, not an illustration.

Generate a manifest instead of typing one

  • kubectl run NAME --image=IMG --dry-run=client -o yaml

    A Pod skeleton. Redirect it to a file and edit - never type YAML from memory.

    Full guide
  • kubectl create deployment NAME --image=IMG --replicas=N --dry-run=client -o yaml

    A Deployment skeleton, including the selector and template labels.

    Full guide
  • kubectl create job NAME --image=IMG --dry-run=client -o yaml -- CMD ARGS

    A Job. Everything after -- becomes the container args.

    Full guide
  • kubectl create cronjob NAME --image=IMG --schedule='*/1 * * * *' -- CMD

    A CronJob, with the four-level jobTemplate nesting filled in correctly.

    Full guide
  • kubectl create secret generic NAME --from-literal=k=v --dry-run=client -o yaml

    A Secret with the base64 already done for you.

    Full guide
  • kubectl expose deployment NAME --port=P --target-port=T --dry-run=client -o yaml

    A Service whose selector is copied from the Deployment - the field most often got wrong by hand.

    Full guide
  • kubectl create ingress NAME --rule='host/path=svc:port' --dry-run=client -o yaml

    An Ingress, expanded from a compact rule string.

    Full guide

Namespace and context

  • kubectl config set-context --current --namespace=NS

    Set the namespace once per task. Removes the whole class of mistakes caused by a forgotten -n.

    Full guide
  • kubectl config view --minify -o jsonpath='{..namespace}'

    Which namespace kubectl is pointed at. Empty means default.

    Full guide
  • kubectl get pods -A --field-selector=status.phase=Running

    Server-side filtering on the handful of indexed fields.

    Full guide
  • kubectl api-resources

    apiVersion and short name for every kind the cluster serves.

    Full guide

Change something that already exists

  • kubectl set image deployment/NAME CONTAINER=IMAGE

    Change the image and trigger a rollout, with no manifest edit.

    Full guide
  • kubectl set env deployment/NAME KEY=VALUE

    Add or change an environment variable. A trailing dash (KEY-) removes one.

    Full guide
  • kubectl set resources deployment/NAME --requests=cpu=100m --limits=memory=128Mi

    Requests and limits without opening an editor.

    Full guide
  • kubectl patch deployment NAME --type=merge -p '{...}'

    Reaches any field - but a Deployment selector is immutable, as shown.

    Full guide
  • kubectl scale deployment NAME --replicas=N

    Immediate, no rollout. --replicas=0 stops a workload without deleting it.

    Full guide
  • kubectl rollout history deploy/NAME

    Revisions, with CHANGE-CAUSE if the annotation was set.

    Full guide
  • kubectl rollout undo deploy/NAME --to-revision=N

    Go back to a named revision. The history renumbers afterwards.

    Full guide
  • kubectl rollout pause deploy/NAME

    Batch several edits into one rollout. Resume with rollout resume.

    Full guide

Configuration, secrets and limits

  • kubectl create configmap NAME --from-literal=K=V

    One key per --from-literal. --from-env-file gives one key per line; --from-file gives one key holding the whole file.

    Full guide
  • kubectl get pod NAME -o jsonpath='{.status.containerStatuses[0].state.waiting.message}'

    CreateContainerConfigError names the missing ConfigMap or Secret key exactly.

    Full guide
  • kubectl get secret NAME -o jsonpath='{.data.KEY}' | base64 -d

    Decode a Secret. Base64 is encoding, not encryption.

    Full guide
  • kubectl create secret docker-registry NAME --docker-server=... --docker-username=...

    The typed Secret imagePullSecrets requires. An Opaque one is ignored.

    Full guide
  • kubectl get pod NAME -o jsonpath='{.status.containerStatuses[0].state.terminated}'

    OOMKilled with exit 137 means the memory limit was hit. SIGKILL leaves no log.

    Full guide
  • kubectl run NAME --image=IMG # in a namespace with a compute ResourceQuota

    A quota on a compute resource makes requests and limits mandatory.

    Full guide
  • kubectl auth can-i VERB RESOURCE --as=system:serviceaccount:NS:NAME

    Check a permission without deploying anything. Note the four-part username.

    Full guide
  • kubectl create role NAME --verb=get,list,watch --resource=pods

    A namespaced Role. Bind it with kubectl create rolebinding.

    Full guide

Services, ingress and reaching things

  • kubectl get endpointslice -l kubernetes.io/service-name=SVC

    The first check on any Service. No endpoints means the selector matches nothing.

    Full guide
  • kubectl exec POD -- cat /etc/resolv.conf

    The search list and ndots that decide which short names resolve.

    Full guide
  • kubectl get pod -l app=X -o jsonpath='{.items[0].spec.containers[0].ports}'

    containerPort is documentation. targetPort is what routes.

    Full guide
  • kubectl exec POD -- nslookup NAME

    A default-deny egress policy blocks DNS too - the symptom looks like broken DNS.

    Full guide
  • kubectl port-forward svc/NAME LOCAL:REMOTE

    Reach a ClusterIP Service from your own machine without changing it.

    Full guide
  • kubectl patch svc NAME --type=merge -p '{"spec":{"type":"NodePort"}}'

    The real way to expose something. port-forward is for debugging only.

    Full guide
  • kubectl get pvc

    Pending with WaitForFirstConsumer and no Pod yet is normal, not a fault.

    Full guide

Resources that extend Kubernetes

  • kubectl get crd

    Everything installed on this cluster that is not built in.

    Full guide
  • kubectl api-resources --api-group=GROUP

    The kinds one extension serves, with short names - exactly as for native objects.

    Full guide
  • kubectl explain KIND.spec --api-version=GROUP/VERSION

    The schema of a custom resource, read from the CRD the cluster holds.

    Full guide
  • kubectl api-resources | grep KIND

    The APIVERSION column is the fix for every "no matches for kind" error.

    Full guide
  • kubectl get --raw /metrics | grep apiserver_requested_deprecated_apis

    Which deprecated APIs this cluster is still being asked for - before you upgrade.

    Full guide
  • kubectl get deploy NAME -o custom-columns=READY:.status.readyReplicas,AVAILABLE:.status.availableReplicas

    readyReplicas ahead of availableReplicas means minReadySeconds has not elapsed.

    Full guide
  • kubectl get pods -o custom-columns=POD:.metadata.name,OWNER:.metadata.ownerReferences[0].kind

    Which controller made each Pod. Deployment Pods are owned by a ReplicaSet.

    Full guide

Find out why it is broken

  • kubectl logs POD --previous

    The log of the container that actually crashed. The current one has not failed yet.

    Full guide
  • kubectl logs -l LABEL --prefix=true --tail=N

    Every matching Pod at once, with the Pod name on each line.

    Full guide
  • kubectl get events --sort-by=.lastTimestamp

    Events are unordered by default. Add --field-selector type=Warning to cut the noise.

    Full guide
  • kubectl get events --field-selector type=Warning

    Usually the whole diagnosis in a busy namespace.

    Full guide
  • kubectl top pods --containers

    Actual consumption. The scheduler, though, counts requests rather than usage.

    Full guide
  • kubectl debug POD --image=busybox --target=CONTAINER -it -- sh

    Attach a shell to a Pod whose image has none. Shares the Pod network.

    Full guide
  • kubectl debug POD --copy-to=NEW --container=C --image=busybox -- sh

    Debug a copy when the original will not stay up. The original is untouched.

    Full guide
  • kubectl describe pod NAME | grep -E "Liveness|Killing"

    A restart loop on a slow-starting app is usually the liveness probe, not a bug.

    Full guide