Part of the series CKA prep
CKA command memory sheet: Task, command, check
Remember the task, use its command, check the result. Essential CKA commands grouped for quick revision, with short YAML patterns where flags are not enough.
Imperative: do it with a command. Declarative: save YAML, then apply it.
Use this sheet for revision. Replace <placeholders> with the task’s values. Names such as web, dev, and app-cfg are examples. Each command is a task pattern, not part of one script.
Remember this order:
CONTEXT → NAMESPACE → INSPECT → CHANGE → CHECK
1. Start every task
alias k=kubectl
k config current-context
k config use-context <context>
k config set-context --current --namespace=<namespace>
Remember: correct cluster, correct namespace.
2. The six commands you will use most
k get <resource>
k describe <resource> <name>
k logs <pod> -c <container>
k exec <pod> -c <container> -- <command>
k edit <resource> <name>
k apply -f file.yaml
| Need | Use |
|---|---|
| See what exists | get |
| Find why it failed | describe, then read Events |
| Read application output | logs |
| Run a command inside a container | exec |
| Change a live object | edit |
| Create or update from YAML | apply -f |
3. Generate YAML instead of typing it
# Pod YAML.
k run web --image=nginx --dry-run=client -o yaml > pod.yaml
# Deployment YAML.
k create deployment web --image=nginx --replicas=3 --dry-run=client -o yaml > deploy.yaml
# Edit, validate, apply.
vi deploy.yaml
k apply --dry-run=server -f deploy.yaml
k apply -f deploy.yaml
k rollout status deployment/web
Forgot a field? Look it up:
k explain pod.spec
k explain pod.spec.containers
k explain pod.spec.volumes
k <command> --help
Remember: --dry-run=client -o yaml generates; apply -f saves.
4. Create workloads
# Namespace.
k create namespace dev
# Pod.
k run web --image=nginx --port=80 --labels=app=web
# Deployment.
k create deployment web --image=nginx --replicas=3
# Pod with a command.
k run worker --image=busybox:1.37.0 --command -- sh -c 'sleep 3600'
# Job and scheduled Job.
k create job hello --image=busybox:1.37.0 -- echo hello
k create cronjob hello --image=busybox:1.37.0 --schedule='*/5 * * * *' -- echo hello
Remember: run creates a Pod; create deployment creates managed replicas.
5. Change a Deployment
# Number of Pods.
k scale deployment/web --replicas=3
# Image: nginx is the container name here.
k set image deployment/web nginx=<image:tag>
# Requests and limits.
k set resources deployment/web -c nginx --requests=cpu=250m,memory=128Mi --limits=cpu=500m,memory=256Mi
# Environment variable.
k set env deployment/web MODE=production
# ServiceAccount in the same namespace as the Deployment.
k set serviceaccount deployment/web app-sa
# Check, inspect history, undo, or restart.
k rollout status deployment/web
k rollout history deployment/web
k rollout undo deployment/web
k rollout undo deployment/web --to-revision=2
k rollout restart deployment/web
Remember: change the Deployment’s Pod template. Check init containers separately. Keep saved YAML up to date.
6. Inspect and troubleshoot Pods
k get pods -A
k get pods -o wide
k get pods -l app=web
k get pods --show-labels
k describe pod <pod>
k get events --sort-by=.metadata.creationTimestamp
# Current logs, previous container logs, live logs.
k logs <pod> -c <container>
k logs <pod> -c <container> --previous
k logs -f <pod> -c <container>
# Container shell.
k exec -it <pod> -c <container> -- sh
# Usage: needs the metrics API.
k top nodes
k top pods --containers
| Symptom | First check |
|---|---|
| Pending | Pod events: resources, taints, affinity, PVC |
| ImagePullBackOff | Image name, tag, registry credentials |
| CrashLoopBackOff | Current and previous container logs |
| OOMKilled | Memory limit and actual memory needs |
| Running but not Ready | Readiness probe and application |
Remember: --previous is for a restarted container in the same Pod.
7. Services and network checks
# ClusterIP.
k expose deployment web --name=web-svc --port=80 --target-port=80
# NodePort: alternative Service example.
k expose deployment web --name=web-nodeport --type=NodePort --port=80 --target-port=80
# Fixed NodePort; check its selector afterward.
k create service nodeport web --tcp=80:80 --node-port=30080
k get service web-svc -o yaml
k get endpointslices -l kubernetes.io/service-name=web-svc
k get pods --show-labels
# Local tunnel; leave running.
k port-forward service/web-svc 8080:80
# In another terminal.
curl http://127.0.0.1:8080
# DNS check: use the actual namespace and DNS domain.
k run dns-check -n dev --image=busybox:1.37.0 --restart=Never --rm -it -- nslookup web-svc.dev.svc.cluster.local
# HTTP check from a Pod.
k run http-check -n dev --image=busybox:1.37.0 --restart=Never --rm -it -- wget -qO- http://web-svc:80
# CoreDNS.
k get pods -n kube-system -l k8s-app=kube-dns
k logs -n kube-system -l k8s-app=kube-dns
k get configmap coredns -n kube-system -o yaml
Remember: Service selector → Pod labels → ready endpoints → correct application port. Port-forward alone does not test normal Service forwarding.
8. ConfigMaps and Secrets
k create configmap app-cfg --from-literal=MODE=production
k create configmap nginx-cfg --from-file=default.conf
k create secret generic app-secret --from-literal=password='<value>'
k create secret tls web-tls --cert=tls.crt --key=tls.key
k set env deployment/web --from=configmap/app-cfg
k set env deployment/web --from=secret/app-secret
k patch configmap app-cfg --type=merge -p '{"immutable":true}'
One environment variable — under the container:
env:
- name: MODE
valueFrom:
configMapKeyRef:
name: app-cfg
key: MODE
ConfigMap file — under Pod spec:
containers:
- name: nginx
image: nginx
volumeMounts:
- name: config
mountPath: /etc/nginx/conf.d
readOnly: true
volumes:
- name: config
configMap:
name: nginx-cfg
| How it is used | How to pick up changed data |
|---|---|
| Environment variable | Replace Pod |
| Normal volume | Wait for file update; reload application if needed |
subPath file |
Replace Pod |
| Immutable ConfigMap | Create a new object and update its consumers |
Remember: ConfigMap stores ordinary settings. Secret stores sensitive values. Base64 is not encryption.
9. RBAC
k create serviceaccount app-sa -n dev
k create role pod-reader -n dev --verb=get,list,watch --resource=pods
k create rolebinding read-pods -n dev --role=pod-reader --serviceaccount=dev:app-sa
k auth can-i list pods -n dev --as=system:serviceaccount:dev:app-sa
k create clusterrole node-reader --verb=get,list,watch --resource=nodes
k create clusterrolebinding read-nodes --clusterrole=node-reader --serviceaccount=dev:app-sa
Remember: Role = permissions. Binding = who receives them. RoleBinding is namespaced; ClusterRoleBinding applies cluster-wide.
10. Scheduling and node maintenance
k label node <node> disk=ssd
k label node <node> disk-
k taint node <node> dedicated=apps:NoSchedule
k taint node <node> dedicated:NoSchedule-
k cordon <node>
k drain <node> --ignore-daemonsets
k uncordon <node>
k describe node <node>
k get limitrange,resourcequota
Add --delete-emptydir-data to drain only when losing that temporary data is allowed.
Under Pod spec:
nodeSelector:
disk: ssd
tolerations:
- key: dedicated
operator: Equal
value: apps
effect: NoSchedule
Required node affinity — under Pod spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: disk
operator: In
values: [ssd]
Remember: selector/affinity chooses; toleration permits. Cordon stops new placement; drain evicts; uncordon allows placement again.
11. Requests, limits, probes, HPA
Under an individual container:
resources:
requests:
cpu: 250m
memory: 128Mi
limits:
cpu: 500m
memory: 256Mi
Probes under the container; use real application paths:
readinessProbe:
httpGet: {path: /, port: 80}
periodSeconds: 5
livenessProbe:
httpGet: {path: /health, port: 80}
periodSeconds: 10
startupProbe:
httpGet: {path: /health, port: 80}
periodSeconds: 5
failureThreshold: 30
k autoscale deployment/web --min=2 --max=5 --cpu=70%
k get hpa
k describe hpa web
Older clients may use --cpu-percent=70; check k autoscale --help. CPU-utilization HPA needs metrics and CPU requests.
| Remember | Meaning |
|---|---|
| Request | Scheduling budget; count against node allocatable |
| CPU limit | Can throttle |
| Memory limit | Can lead to OOM kill |
| Readiness | Controls normal Service traffic |
| Liveness | Can restart container |
| Startup | Holds back readiness/liveness checks until startup succeeds |
12. Storage
k get storageclass
k get pv
k get pvc -A
k describe pvc <claim> -n <namespace>
k describe pv <volume>
k get volumeattachments
k patch pv <volume> --type=merge -p '{"spec":{"persistentVolumeReclaimPolicy":"Retain"}}'
PV and PVC — single-node practice example:
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv1
spec:
capacity:
storage: 1Gi
accessModes: [ReadWriteOnce]
persistentVolumeReclaimPolicy: Retain
storageClassName: manual
hostPath:
path: /data
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc1
spec:
accessModes: [ReadWriteOnce]
storageClassName: manual
resources:
requests:
storage: 1Gi
PVC mount — under Pod spec:
containers:
- name: app
image: nginx
volumeMounts:
- name: data
mountPath: /data
volumes:
- name: data
persistentVolumeClaim:
claimName: pvc1
For temporary shared files, use this volume source instead:
volumes:
- name: data
emptyDir: {}
StorageClass — use the installed provisioner’s name:
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: fast
provisioner: <installed-provisioner>
reclaimPolicy: Delete
volumeBindingMode: WaitForFirstConsumer
Remember: PVC requests; PV provides. RWO = one node. RWOP = one Pod with supported CSI. emptyDir ends with its Pod. hostPath is node-local. A waiting claim may need a consumer before binding.
13. Ingress, Gateway, NetworkPolicy
k create ingress web --class=<ingress-class> --rule='app.example.com/=web-svc:80'
k describe ingress web
k get gatewayclass
k get gateway,httproute
k describe gateway web-gw
k describe httproute web-route
Gateway and route — controller and CRDs must already exist:
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: web-gw
spec:
gatewayClassName: <installed-gateway-class>
listeners:
- name: http
protocol: HTTP
port: 80
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: web-route
spec:
parentRefs:
- name: web-gw
hostnames: [app.example.com]
rules:
- matches:
- path: {type: PathPrefix, value: /}
backendRefs:
- name: web-svc
port: 80
Keep Gateway, route, and Service in the same namespace for this example. Check Accepted and ResolvedRefs conditions.
NetworkPolicy — allow frontend Pods to reach database Pods on TCP 5432 in the same namespace:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-frontend
spec:
podSelector:
matchLabels: {app: db}
policyTypes: [Ingress]
ingress:
- from:
- podSelector:
matchLabels: {app: frontend}
ports:
- protocol: TCP
port: 5432
k apply -f policy.yaml
k describe networkpolicy allow-frontend
Remember: NetworkPolicy needs enforcement by the network plugin. Separate peers mean OR; namespace and Pod selectors in one peer mean AND. Policies add allowed traffic together.
14. Init containers and sidecars
Under Pod spec — regular init container:
initContainers:
- name: prepare
image: busybox:1.37.0
command: [sh, -c, 'echo preparing']
Under Pod spec — native sidecar:
initContainers:
- name: helper
image: busybox:1.37.0
restartPolicy: Always
command: [sh, -c, 'while true; do echo helping; sleep 5; done']
Add these to a Pod with its main application container. File sharing also needs a shared volume and mounts in both containers.
Remember: regular init finishes; sidecar keeps helping. Count startup resource needs as well as application requests.
15. Helm, Kustomize, operators
helm repo add <repo> <url>
helm repo update
helm search repo <chart>
helm show values <repo/chart> > values.yaml
helm upgrade --install <release> <repo/chart> -n <namespace> --create-namespace -f values.yaml
helm list -A
helm get values <release> -n <namespace>
helm history <release> -n <namespace>
helm rollback <release> <revision> -n <namespace>
helm uninstall <release> -n <namespace>
k kustomize ./overlay
k apply -k ./overlay
k get crd
k api-resources
k explain <custom-resource>.spec
k apply -f operator.yaml
k apply -f custom-resource.yaml
k get <custom-resource> -A
Remember: Helm manages releases; Kustomize changes manifest sets. A CRD defines an API; an operator implements its behavior. Use the task’s chart version and installation method.
16. Node and control-plane failures
On the node named by the task:
ssh <node>
sudo -i
systemctl status kubelet
journalctl -u kubelet -n 100 --no-pager
systemctl status containerd
journalctl -u containerd -n 100 --no-pager
crictl pods
crictl ps -a
crictl logs <container-id>
ls /etc/kubernetes/manifests
cat /var/lib/kubelet/config.yaml
cat /etc/kubernetes/manifests/kube-apiserver.yaml
cat /etc/kubernetes/manifests/etcd.yaml
After fixing the relevant configuration:
systemctl daemon-reload # when a systemd unit/drop-in changed
systemctl restart kubelet
Remember: use the actual runtime service and CRI endpoint. A kubectl failure can also be credentials, context, DNS, or networking. Keep static-manifest backups outside the watched directory.
17. kubeadm: create, join, upgrade
sudo kubeadm init --config kubeadm-config.yaml
kubeadm token create --print-join-command
sudo kubeadm join <endpoint> --token <token> --discovery-token-ca-cert-hash sha256:<hash>
Upgrade memory order:
Target kubeadm package → kubeadm upgrade → drain
→ target kubelet/kubectl packages → restart kubelet → uncordon
# First control-plane node.
sudo kubeadm upgrade plan
sudo kubeadm upgrade apply v<target-version>
# Other control-plane and worker nodes: use this instead.
sudo kubeadm upgrade node
# From a host with kubectl credentials.
k drain <node> --ignore-daemonsets
Package pattern — apt-based hosts with the correct repository; install kubeadm before its upgrade step, kubelet/kubectl after drain:
sudo apt-get update
apt-cache madison kubeadm
sudo apt-mark unhold <package>
sudo apt-get install -y <package>=<exact-package-version>
sudo apt-mark hold <package>
# On the upgraded node, after upgrading kubelet.
sudo systemctl daemon-reload
sudo systemctl restart kubelet
# From a host with kubectl credentials.
k uncordon <node>
k get nodes
# Certificate inspection.
sudo kubeadm certs check-expiration
sudo openssl x509 -in /etc/kubernetes/pki/apiserver.crt -noout -dates
Remember: upgrade one node at a time; use the required version and supported version skew. HA installation needs the task’s control-plane endpoint and join settings.
18. etcd: save, check, restore
# Save a live snapshot with the actual endpoint and client certificates.
sudo etcdctl --endpoints=https://127.0.0.1:2379 --cacert=<ca-file> --cert=<client-cert> --key=<client-key> snapshot save /opt/backup.db
# Check the snapshot.
sudo etcdutl snapshot status /opt/backup.db --write-out=table
# Restore data files into a new directory.
sudo etcdutl snapshot restore /opt/backup.db --data-dir=/var/lib/etcd-restored
Remember: etcdctl saves; etcdutl checks/restores. Restoring files is only part of recovery: stop affected components as required, use the correct member settings, point etcd at restored data, restart, and verify. Follow the topology and version-specific revision-bump guidance in the etcd recovery procedure.
Final memory check
| Task | Command to recall |
|---|---|
| Generate YAML | --dry-run=client -o yaml |
| Find failure reason | describe → Events |
| Previous crash output | logs --previous |
| Change replicas | scale |
| Change image | set image |
| Change requests/limits | set resources |
| Undo update | rollout undo |
| Check permissions | auth can-i |
| Move workloads off node | drain |
| Allow scheduling again | uncordon |
| Learn YAML field | explain |
| Apply saved configuration | apply -f |