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.

, 11 min read

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

Official references