kubectl fluency
The imperative commands that generate most exam YAML, the output formats and jsonpath recipes that read any cluster in one line, and the shell setup that makes all of it faster.
After this lesson
- 01You can produce a correct manifest for any common resource with a kubectl generator and --dry-run=client -o yaml, without opening the docs.
- 02You can extract exactly the fields a question asks for with -o jsonpath, custom-columns, --sort-by and selectors.
- 03You can choose between edit, apply, replace --force and delete --force based on whether the field is mutable.
Two hours, up to twenty tasks: that is six minutes per task including reading, doing and checking. The difference between passing comfortably and running out of time is almost never Kubernetes knowledge; it is how many keystrokes stand between you and a correct object. This lesson is the keystroke budget. Everything here runs on the lab exactly as written.
Shell setup: sixty seconds that pay back all exam
alias k=kubectl
export do="--dry-run=client -o yaml"
export now="--force --grace-period=0"
source <(kubectl completion bash)
complete -o default -F __start_kubectl k
# Then the two commands you will use most:
k create deploy web --image=nginx:1.27 --replicas=2 $do > web.yaml
k delete pod stuck $nowImperative generators
# 1. Generate a manifest without touching the cluster
k -n team-a create deploy api --image=nginx:1.27 --replicas=3 $do > api.yaml
# 2. Find the field you need to add, with the exact spelling and type
k explain deploy.spec.strategy
k explain pod.spec.containers.livenessProbe --recursive | less
k explain pod.spec.tolerations
# 3. Edit the file in vim, then apply it
k apply -f api.yaml
# Multi-resource trick: generate a pod, pipe straight into a label change, apply in one line
k run tmp --image=busybox:1.36 --restart=Never $do -- sleep 3600 | k label --local -f - tier=debug -o yaml | k apply -f -
# --help is faster than the docs for flags
k create deploy --help | less
k run --help | grep -A2 -- --commandReading the cluster
k get pods -o wide # node, IP, nominated node, readiness gates
k get deploy web -o yaml # the whole object; pipe to grep or less
k get pod web -o json | less
k get pods -o name # pod/web, pod/api... handy for xargs and loops
k get pods -A # every namespace
k get pods -l app=web,tier!=cache # label selectors; also 'env in (prod,staging)'
k get pods --show-labels
k get pods --field-selector=status.phase!=Running -A
k get pods --sort-by=.metadata.creationTimestamp
k get events --sort-by=.lastTimestamp -n team-a
k get pods -o custom-columns=NAME:.metadata.name,NODE:.spec.nodeName,IP:.status.podIP
k get pods -w # watch; Ctrl+C to stop
k api-resources | grep -i policy # short names, api groups, namespaced or not
k api-versions | grep autoscaling# One field
k get deploy web -o jsonpath='{.spec.replicas}'
# A list, space separated
k get pods -o jsonpath='{.items[*].metadata.name}'
# One item per line, several fields: range ... end
k get nodes -o jsonpath='{range .items[*]}{.metadata.name}{" "}{.status.nodeInfo.kubeletVersion}{"\n"}{end}'
# Filter inside a list: the address whose type is InternalIP
k get nodes -o jsonpath='{range .items[*]}{.metadata.name}{" "}{.status.addresses[?(@.type=="InternalIP")].address}{"\n"}{end}'
# Filter whole items: pods on one node
k get pods -A -o jsonpath='{range .items[?(@.spec.nodeName=="cka-worker")]}{.metadata.namespace}{"/"}{.metadata.name}{"\n"}{end}'
# Container images in a Deployment, taints on nodes, the InternalIP of one node
k get deploy web -o jsonpath='{.spec.template.spec.containers[*].image}'
k get nodes -o jsonpath='{range .items[*]}{.metadata.name}{": "}{.spec.taints[*].key}{"\n"}{end}'
k get node cka-worker -o jsonpath='{.status.addresses[?(@.type=="InternalIP")].address}'
# Tabular output sorted by a jsonpath (sorted on the server response, works with custom-columns)
k -n kube-system get pods --sort-by=.metadata.name -o custom-columns=POD:.metadata.name,NODE:.spec.nodeName
# When jsonpath gets ugly, yq is on the exam hosts
k get deploy web -o yaml | yq '.spec.template.spec.containers[].image'Changing objects: pick the tool by what you are changing. kubectl edit opens the live object in vim and is right for any mutable field; if you save something invalid it reopens with the error at the top. kubectl apply -f is right when you have the file, and it is what you want after generating with $do. kubectl replace --force -f file.yaml deletes and recreates, which is the only way to change an immutable field: a Pod's image is mutable, but its containers' names, its volumes, its nodeName, resources on a running Pod (without the in-place resize feature) and most of a Service's or a Job's spec are not. kubectl delete pod X $now skips the grace period when a Pod is stuck Terminating; use it on Pods, never on nodes or namespaces. Pods owned by a Deployment do not need to be edited at all: change the Deployment's template and the rollout does the rest.
k config get-contexts # the * marks the current one
k config use-context kind-cka
k config current-context
k config set-context --current --namespace=team-a # every later command defaults to team-a
k config view --minify # the active cluster, user and namespace only
k config view --minify -o jsonpath='{..namespace}'
# When a kubeconfig is given as a file in the task
k --kubeconfig=/root/other.kubeconfig get nodes
export KUBECONFIG=/root/other.kubeconfigIn the docs · the tab you get on exam day
- kubectl quick reference ↗search: “cheat sheet”
- JSONPath support ↗search: “jsonpath”
- kubectl create (generated reference) ↗search: “kubectl create”
- Configure access to multiple clusters ↗search: “configure access multiple clusters”
context · kubectl config use-context kind-cka
Generate a manifest, then apply it
/tmp/cka/fluency/web.yaml: name web, namespace fd-fluency, image nginx:1.27, 2 replicas. Add the label tier=frontend to the Deployment's own metadata in that file, then create the Deployment from the file. Both the file and the live Deployment must carry the label and have 2 replicas.- 01
Set up the scenario
curl -fsSL https://codewithmuh.com/labs/cka/t/fd-fluency-1/setup | bash - 02
Solve it in your terminal
Work the way the exam makes you: kubectl, the docs, nothing else. Put any answer files under
/tmp/cka/. - 03
Check your work
curl -fsSL https://codewithmuh.com/labs/cka/t/fd-fluency-1/verify | bashCounts toward your readiness score. - 04
Clean up
curl -fsSL https://codewithmuh.com/labs/cka/t/fd-fluency-1/cleanup | bash
context · kubectl config use-context kind-cka
Node names and InternalIPs with jsonpath
kubectl get nodes command with a jsonpath expression, write the name and the InternalIP of every node in the cluster to /tmp/cka/fluency/nodes.txt. One node per line, in the form <name> <ip> separated by one space, nothing else in the file.- 01
Set up the scenario
curl -fsSL https://codewithmuh.com/labs/cka/t/fd-fluency-2/setup | bash - 02
Solve it in your terminal
Work the way the exam makes you: kubectl, the docs, nothing else. Put any answer files under
/tmp/cka/. - 03
Check your work
curl -fsSL https://codewithmuh.com/labs/cka/t/fd-fluency-2/verify | bashCounts toward your readiness score. - 04
Clean up
curl -fsSL https://codewithmuh.com/labs/cka/t/fd-fluency-2/cleanup | bash
context · kubectl config use-context kind-cka
A sorted custom-columns listing
kube-system namespace to /tmp/cka/fluency/kube-system-pods.txt. Use kubectl custom columns with exactly two columns, headed POD (the Pod name) and NODE (the node the Pod runs on), sorted by Pod name. Keep the header line.- 01
Set up the scenario
curl -fsSL https://codewithmuh.com/labs/cka/t/fd-fluency-3/setup | bash - 02
Solve it in your terminal
Work the way the exam makes you: kubectl, the docs, nothing else. Put any answer files under
/tmp/cka/. - 03
Check your work
curl -fsSL https://codewithmuh.com/labs/cka/t/fd-fluency-3/verify | bashCounts toward your readiness score. - 04
Clean up
curl -fsSL https://codewithmuh.com/labs/cka/t/fd-fluency-3/cleanup | bash
Finished reading?
0 of 3 tasks passed. Readiness counts tasks, so run them before you move on.