The exam-day cheat sheet

Every command and short YAML example this course uses, grouped by exam domain, plus the kubernetes.io search phrase that finds the right page for each topic.

30 min

Key ideas in this lesson · tap one for a simple explanation

What you will be able to do

  • Write any YAML skeleton on this page from memory, or with one kubectl explain.
  • Find the right docs page for any exam topic with a single search phrase.
  • Run the cluster checks and then the node checks in order, without looking anything up.

This page is a reference, not a lesson. Keep it open while you do the mocks, until you no longer need it.

  • Everything here runs on the lab as written.
  • Node commands run in a shell: docker exec -it cka-control-plane bash in the lab, or ssh <node> then sudo -i on the exam.
  • The examples are short on purpose. kubectl explain <kind>.<path> shows any other field you need.
  • The first block of each domain shows the domain's exam weight in its title, so you know where a minute is worth most.
  • You cannot bring this page into the exam. The table at the end gives the kubernetes.io search phrase for each topic instead.
kubectl: setup, generators, reading and changing objects
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
printf 'set ts=2 sw=2 et nu\n' > ~/.vimrc

k run web --image=nginx:1.27 --port=80 --labels=app=web $do > pod.yaml
k run tmp --image=busybox:1.36 --restart=Never -it --rm -- sh          # throwaway shell
k create deploy web --image=nginx:1.27 --replicas=3 --port=80 $do > deploy.yaml
k expose deploy web --name=web-svc --port=80 --target-port=8080 --type=ClusterIP
k create svc nodeport web --tcp=80:8080 --node-port=30080
k create cm app-cfg --from-literal=KEY=value --from-file=app.properties
k create cm app-env --from-env-file=.env      # env files cannot be combined with the other two
k create secret generic db --from-literal=password=s3cret
k create secret tls web-tls --cert=tls.crt --key=tls.key
k create job once --image=busybox:1.36 -- sh -c 'date'
k create job manual --from=cronjob/nightly
k create cj nightly --image=busybox:1.36 --schedule='0 2 * * *' -- sh -c 'date'
k create ingress web --class=nginx --rule='shop.example.com/*=web-svc:80'
k create ns team-a; k create quota q --hard=pods=10,requests.cpu=2 -n team-a
k create pdb web-pdb --selector=app=web --min-available=1
k create priorityclass high --value=100000
k autoscale deploy web --min=2 --max=6 --cpu=70%
k scale deploy web --replicas=5
k set image deploy/web nginx=nginx:1.26
k set env deploy/web LOG_LEVEL=debug; k set env deploy/web --from=configmap/app-cfg
k set resources deploy/web -c nginx --requests=cpu=100m,memory=64Mi --limits=cpu=200m,memory=128Mi
k set sa deploy/web app
k label pod web tier=frontend --overwrite; k label pod web tier-
k annotate deploy web kubernetes.io/change-cause="image 1.26" --overwrite
k explain deploy.spec.strategy; k explain pod.spec.containers.livenessProbe --recursive
k api-resources | grep -i <word>; k api-versions

# --- Reading the cluster: formats, selectors, jsonpath, config
k get pods -o wide -A; k get pods -o name; k get pods --show-labels
k get pods -l app=web,tier!=cache; k get pods -l 'env in (prod,staging)'
k get pods -A --field-selector=status.phase!=Running
k get pods --sort-by=.metadata.creationTimestamp; k get events --sort-by=.lastTimestamp
k get pods -o custom-columns=NAME:.metadata.name,NODE:.spec.nodeName,IP:.status.podIP
k get deploy web -o jsonpath='{.spec.template.spec.containers[*].image}'
k get pods -o jsonpath='{.items[*].metadata.name}'
k get nodes -o jsonpath='{range .items[*]}{.metadata.name}{" "}{.status.addresses[?(@.type=="InternalIP")].address}{"\n"}{end}'
k get pods -A -o jsonpath='{range .items[?(@.spec.nodeName=="cka-worker")]}{.metadata.namespace}/{.metadata.name}{"\n"}{end}'
k get nodes -o jsonpath='{range .items[*]}{.metadata.name}{": "}{.spec.taints[*].key}{"\n"}{end}'
k get deploy web -o yaml | yq '.spec.template.spec.containers[].image'
k get pods -w                                     # Ctrl+C to stop

k config get-contexts; k config use-context <ctx>; k config current-context
k config set-context --current --namespace=<ns>; k config view --minify
k --kubeconfig=/path/kubeconfig get nodes

k edit deploy web                                 # mutable fields
k apply -f file.yaml                              # from a file
k get pod web -o yaml > p.yaml; k replace --force -f p.yaml   # immutable Pod fields
k delete pod web $now                             # stuck Terminating
Architecture (25%): RBAC, service accounts, certificates, kubeconfig
k create role dev --verb=get,list,watch --resource=pods,deployments -n team-a
k create role dev-pod --verb=get --resource=pods --resource-name=web -n team-a
k create rolebinding dev-rb --role=dev --user=jane -n team-a
k create clusterrole nodes-ro --verb=get,list,watch --resource=nodes
k create clusterrole health --verb=get --non-resource-url=/healthz
k create clusterrolebinding nodes-ro-rb --clusterrole=nodes-ro --group=ops
k create rolebinding sa-rb --clusterrole=view --serviceaccount=team-a:app -n team-a   # ClusterRole bound in one namespace
k auth can-i list pods --as=jane -n team-a
k auth can-i get nodes --as=system:serviceaccount:team-a:app
k auth can-i --list --as=jane -n team-a

k create sa app -n team-a
k create token app -n team-a --duration=1h
# Pod: spec.serviceAccountName: app   spec.automountServiceAccountToken: false

# Client certificate for a user via the CSR API
openssl genrsa -out jane.key 2048
openssl req -new -key jane.key -subj "/CN=jane/O=devs" -out jane.csr
base64 < jane.csr | tr -d '\n'    # one line; goes into spec.request below
k certificate approve jane; k certificate deny jane
k get csr jane -o jsonpath='{.status.certificate}' | base64 -d > jane.crt
k config set-credentials jane --client-key=jane.key --client-certificate=jane.crt --embed-certs
k config set-context jane --cluster=kubernetes --user=jane --namespace=team-a

# kubeadm-managed certificates (on the control plane)
kubeadm certs check-expiration
kubeadm certs renew apiserver; kubeadm certs renew all
openssl x509 -in /etc/kubernetes/pki/apiserver.crt -noout -dates -subject -ext subjectAltName
Architecture: kubeadm upgrade sequence, drain, etcd backup and restore
# --- Upgrade one minor (example 1.36 -> 1.37). On the node, as root. Control plane first, then each worker.
sed -i 's|v1\.36|v1.37|' /etc/apt/sources.list.d/kubernetes.list && apt-get update
apt-cache madison kubeadm | head -3
apt-mark unhold kubeadm && apt-get install -y kubeadm='1.37.0-*' && apt-mark hold kubeadm
kubeadm version
kubeadm upgrade plan
kubeadm upgrade apply v1.37.0                 # first control plane only
kubeadm upgrade node                          # other control planes and every worker
# From a machine with kubectl, before touching kubelet on that node:
kubectl drain <node> --ignore-daemonsets --delete-emptydir-data
# Back on the node:
apt-mark unhold kubelet kubectl && apt-get install -y kubelet='1.37.0-*' kubectl='1.37.0-*' && apt-mark hold kubelet kubectl
systemctl daemon-reload && systemctl restart kubelet
kubectl uncordon <node>
kubectl get nodes                              # VERSION column moves node by node

# --- Node maintenance
kubectl cordon <node>; kubectl drain <node> --ignore-daemonsets --delete-emptydir-data --force; kubectl uncordon <node>

# --- etcd: find the flags first (static pod on the control plane)
grep -E 'listen-client-urls|cert-file|key-file|trusted-ca-file|data-dir' /etc/kubernetes/manifests/etcd.yaml

# Snapshot
etcdctl --endpoints=https://127.0.0.1:2379 \
  --cacert=/etc/kubernetes/pki/etcd/ca.crt \
  --cert=/etc/kubernetes/pki/etcd/server.crt \
  --key=/etc/kubernetes/pki/etcd/server.key \
  snapshot save /opt/etcd-backup.db
etcdutl snapshot status /opt/etcd-backup.db -w table

# Restore into a new data dir, then point the static pod at it
etcdutl snapshot restore /opt/etcd-backup.db --data-dir /var/lib/etcd-restored
# edit /etc/kubernetes/manifests/etcd.yaml: the etcd-data hostPath volume -> /var/lib/etcd-restored
# kubelet notices the manifest change and recreates etcd; wait, then:
crictl ps | grep etcd; kubectl get pods -A

# --- Static pods and the control plane
ls /etc/kubernetes/manifests/                 # kube-apiserver, controller-manager, scheduler, etcd
grep staticPodPath /var/lib/kubelet/config.yaml
kubectl -n kube-system get pods -o wide         # control-plane pods are named <component>-<node>
Architecture: Helm, Kustomize, CRDs and operators
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx; helm repo update
helm search repo ingress-nginx --versions | head
helm show values ingress-nginx/ingress-nginx > values.yaml
helm install ingress ingress-nginx/ingress-nginx -n ingress --create-namespace --version 4.13.0 -f values.yaml --set controller.replicaCount=2
helm upgrade ingress ingress-nginx/ingress-nginx -n ingress --version 4.13.1 --reuse-values
helm list -A; helm status ingress -n ingress; helm get values ingress -n ingress
helm history ingress -n ingress; helm rollback ingress 1 -n ingress
helm template ingress ingress-nginx/ingress-nginx -n ingress > rendered.yaml   # inspect without installing
helm uninstall ingress -n ingress

kubectl kustomize overlays/prod                  # render
kubectl apply -k overlays/prod; kubectl delete -k overlays/prod
# kustomization.yaml keys you will touch: resources, namespace, namePrefix, labels, images (name/newTag), patches (path + target)

kubectl get crd; kubectl get crd <name> -o yaml | less
kubectl explain <kind> --recursive | less        # works for CRD kinds too
kubectl api-resources | grep <group>
kubectl get <plural>.<group> -A                   # fully qualified when short names collide
Architecture: CSR object, kustomization.yaml and a minimal CRD
apiVersion: certificates.k8s.io/v1
kind: CertificateSigningRequest
metadata:
  name: jane
spec:
  request: <base64 of jane.csr, one line>
  signerName: kubernetes.io/kube-apiserver-client
  expirationSeconds: 86400
  usages:
    - client auth
---
# overlays/prod/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
  - ../../base
namespace: prod
namePrefix: prod-
labels:
  - pairs:
      env: prod
    includeSelectors: true
images:
  - name: nginx
    newTag: "1.27"
patches:
  - path: replicas.yaml
    target:
      kind: Deployment
      name: web
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
  name: backups.ops.example.com
spec:
  group: ops.example.com
  scope: Namespaced
  names:
    plural: backups
    singular: backup
    kind: Backup
    shortNames: ["bk"]
  versions:
    - name: v1
      served: true
      storage: true
      schema:
        openAPIV3Schema:
          type: object
          properties:
            spec:
              type: object
              properties:
                schedule: { type: string }
                retainDays: { type: integer }
Workloads (15%): rollouts, scheduling, autoscaling
k rollout status deploy/web --timeout=120s
k rollout history deploy/web; k rollout history deploy/web --revision=2
k rollout undo deploy/web; k rollout undo deploy/web --to-revision=1
k rollout pause deploy/web; k rollout resume deploy/web; k rollout restart deploy/web
k scale deploy web --replicas=4; k scale sts db --replicas=3
k autoscale deploy web --min=2 --max=6 --cpu=70%; k get hpa

k taint node cka-worker dedicated=gpu:NoSchedule        # NoSchedule | PreferNoSchedule | NoExecute
k taint node cka-worker dedicated=gpu:NoSchedule-       # remove
k label node cka-worker disk=ssd; k label node cka-worker disk-
k cordon cka-worker; k uncordon cka-worker
k get pods -o wide                                      # which node did it land on
k describe pod web | grep -A10 Events                   # FailedScheduling tells you why

k get ds,job,cj -A; k get job once -o jsonpath='{.status.succeeded}'
k create job manual --from=cronjob/nightly
k get pdb; k get priorityclass; k get limitrange,resourcequota -n team-a
k describe quota -n team-a
Workloads: Pod spec skeletons (scheduling, probes, resources, config, sidecar)
apiVersion: v1
kind: Pod
metadata:
  name: web
  labels: { app: web }
spec:
  priorityClassName: high
  serviceAccountName: app
  nodeSelector:
    disk: ssd
  tolerations:
    - key: dedicated
      operator: Equal          # or Exists (then omit value)
      value: gpu
      effect: NoSchedule
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
          - matchExpressions:
              - { key: disk, operator: In, values: [ssd] }   # In NotIn Exists DoesNotExist Gt Lt
    podAntiAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        - labelSelector:
            matchLabels: { app: web }
          topologyKey: kubernetes.io/hostname
  topologySpreadConstraints:
    - maxSkew: 1
      topologyKey: kubernetes.io/hostname
      whenUnsatisfiable: DoNotSchedule
      labelSelector:
        matchLabels: { app: web }
  initContainers:
    - name: init-cfg
      image: busybox:1.36
      command: ["sh", "-c", "echo ready > /work/ok"]
      volumeMounts: [{ name: work, mountPath: /work }]
    - name: log-shipper              # sidecar: an init container that keeps running
      image: busybox:1.36
      restartPolicy: Always
      command: ["sh", "-c", "tail -F /work/app.log"]
      volumeMounts: [{ name: work, mountPath: /work }]
  containers:
    - name: nginx
      image: nginx:1.27
      ports: [{ containerPort: 80 }]
      resources:
        requests: { cpu: 100m, memory: 64Mi }
        limits: { cpu: 200m, memory: 128Mi }
      env:
        - name: DB_PASSWORD
          valueFrom:
            secretKeyRef: { name: db, key: password }
        - name: LOG_LEVEL
          valueFrom:
            configMapKeyRef: { name: app-cfg, key: LOG_LEVEL }
      envFrom:
        - configMapRef: { name: app-cfg }
      startupProbe:
        httpGet: { path: /, port: 80 }
        failureThreshold: 30
        periodSeconds: 2
      readinessProbe:
        httpGet: { path: /, port: 80 }
        initialDelaySeconds: 2
        periodSeconds: 5
      livenessProbe:
        exec:
          command: ["sh", "-c", "test -f /tmp/healthy"]
        periodSeconds: 10
        failureThreshold: 3
      volumeMounts:
        - { name: work, mountPath: /work }
        - { name: cfg, mountPath: /etc/app, readOnly: true }
  volumes:
    - name: work
      emptyDir: {}
    - name: cfg
      configMap:
        name: app-cfg
    - name: secrets
      secret:
        secretName: db
  restartPolicy: Always            # Pod-level: Always | OnFailure | Never
Workloads: HPA (autoscaling/v2), PDB, LimitRange, ResourceQuota, CronJob
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: web
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: web
  minReplicas: 2
  maxReplicas: 6
  metrics:
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 70
  behavior:
    scaleDown:
      stabilizationWindowSeconds: 60
---
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: web-pdb
spec:
  minAvailable: 2                 # or maxUnavailable: 1
  selector:
    matchLabels: { app: web }
---
apiVersion: v1
kind: LimitRange
metadata:
  name: defaults
spec:
  limits:
    - type: Container
      default: { cpu: 200m, memory: 128Mi }
      defaultRequest: { cpu: 100m, memory: 64Mi }
      max: { cpu: "1", memory: 512Mi }
---
apiVersion: v1
kind: ResourceQuota
metadata:
  name: team-quota
spec:
  hard:
    pods: "10"
    requests.cpu: "2"
    requests.memory: 2Gi
    limits.cpu: "4"
---
apiVersion: batch/v1
kind: CronJob
metadata:
  name: nightly
spec:
  schedule: "0 2 * * *"
  concurrencyPolicy: Forbid
  successfulJobsHistoryLimit: 3
  jobTemplate:
    spec:
      backoffLimit: 2
      activeDeadlineSeconds: 300
      template:
        spec:
          restartPolicy: OnFailure
          containers:
            - name: run
              image: busybox:1.36
              command: ["sh", "-c", "date"]
Networking (20%): Services, endpoints, DNS, Ingress, policies
k expose deploy web --name=web-svc --port=80 --target-port=8080 --type=NodePort
k get svc web-svc -o wide; k get endpointslices -l kubernetes.io/service-name=web-svc
k get svc web-svc -o jsonpath='{.spec.ports[0].nodePort}'         # 30000-32767
k run tmp --image=busybox:1.36 --restart=Never -it --rm -- wget -qO- --timeout=2 http://web-svc.team-a.svc.cluster.local
k run tmp --image=busybox:1.36 --restart=Never -it --rm -- nslookup web-svc.team-a.svc.cluster.local
# DNS names: <svc>.<ns>.svc.cluster.local   <pod-ip-dashed>.<ns>.pod.cluster.local   <pod>.<headless-svc>.<ns>.svc.cluster.local

k -n kube-system get deploy coredns; k -n kube-system get svc kube-dns
k -n kube-system get cm coredns -o yaml                   # the Corefile
k -n kube-system logs deploy/coredns --tail=50
k -n kube-system rollout restart deploy coredns
k get pod tmp -o jsonpath='{.spec.dnsPolicy}'; cat /etc/resolv.conf   # inside a pod

k get ingressclass; k get ingress -A; k describe ingress web
curl -H 'Host: shop.example.com' http://localhost:8080/              # lab: ingress-nginx on 8080
k -n ingress-nginx logs deploy/ingress-nginx-controller --tail=50

k get gatewayclass,gateway,httproute -A; k describe httproute web

k get netpol -n team-a; k describe netpol deny-all -n team-a
k get pods -n team-a --show-labels                        # does the podSelector match anything?

# On a node: the pod network
ip addr; ip route; cat /etc/cni/net.d/*; crictl ps
Networking: Service, Ingress, Gateway, HTTPRoute, NetworkPolicy
apiVersion: v1
kind: Service
metadata:
  name: web-svc
  namespace: team-a
spec:
  type: ClusterIP                 # ClusterIP | NodePort | LoadBalancer; clusterIP: None for headless
  selector:
    app: web
  ports:
    - name: http
      port: 80                    # the Service's port
      targetPort: 8080            # the container's port (number or port name)
      # nodePort: 30080           # NodePort only, 30000-32767
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: web
  namespace: team-a
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  ingressClassName: nginx
  tls:
    - hosts: [shop.example.com]
      secretName: web-tls
  rules:
    - host: shop.example.com
      http:
        paths:
          - path: /
            pathType: Prefix      # Prefix | Exact | ImplementationSpecific
            backend:
              service:
                name: web-svc
                port:
                  number: 80
---
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: shared-gw
  namespace: team-a
spec:
  gatewayClassName: nginx
  listeners:
    - name: http
      protocol: HTTP
      port: 80
      hostname: shop.example.com
      allowedRoutes:
        namespaces:
          from: Same              # Same | All | Selector
    - name: https
      protocol: HTTPS
      port: 443
      hostname: shop.example.com
      tls:
        mode: Terminate
        certificateRefs:
          - name: web-tls
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: web
  namespace: team-a
spec:
  parentRefs:
    - name: shared-gw
  hostnames: [shop.example.com]
  rules:
    - matches:
        - path:
            type: PathPrefix      # PathPrefix | Exact | RegularExpression
            value: /
      backendRefs:
        - name: web-svc
          port: 80
          weight: 90
        - name: web-canary
          port: 80
          weight: 10
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: web-policy
  namespace: team-a
spec:
  podSelector:
    matchLabels: { app: web }     # {} selects every pod in the namespace
  policyTypes: [Ingress, Egress]  # listing a type with no rules = deny all of that type
  ingress:
    - from:
        - podSelector:
            matchLabels: { app: frontend }
        - namespaceSelector:
            matchLabels: { kubernetes.io/metadata.name: monitoring }
        - ipBlock:
            cidr: 10.0.0.0/8
            except: [10.0.1.0/24]
      ports:
        - protocol: TCP
          port: 8080
  egress:
    - to:
        - namespaceSelector: {}
          podSelector:
            matchLabels: { k8s-app: kube-dns }
      ports:
        - { protocol: UDP, port: 53 }
        - { protocol: TCP, port: 53 }
# A podSelector and a namespaceSelector in ONE list item (no dash before the second) is AND; separate items are OR.
Storage (10%): StorageClass, PV, PVC, mounting
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: fast
  annotations:
    storageclass.kubernetes.io/is-default-class: "true"
provisioner: rancher.io/local-path        # lab; kubernetes.io/no-provisioner for manual PVs
reclaimPolicy: Delete                      # Delete | Retain
volumeBindingMode: WaitForFirstConsumer    # or Immediate
allowVolumeExpansion: true
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-data
spec:
  capacity:
    storage: 1Gi
  accessModes: [ReadWriteOnce]             # ReadWriteOnce | ReadOnlyMany | ReadWriteMany | ReadWriteOncePod
  persistentVolumeReclaimPolicy: Retain
  storageClassName: manual
  hostPath:
    path: /data/pv-data
  # local volumes need nodeAffinity:
  # local: { path: /mnt/disks/ssd1 }
  # nodeAffinity:
  #   required:
  #     nodeSelectorTerms:
  #       - matchExpressions:
  #           - { key: kubernetes.io/hostname, operator: In, values: [cka-worker] }
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: data
  namespace: team-a
spec:
  accessModes: [ReadWriteOnce]
  storageClassName: manual                 # must match the PV, or omit to use the default class
  resources:
    requests:
      storage: 500Mi                       # a PV with >= this capacity binds
  # volumeName: pv-data                    # pin to one PV
---
# In a Pod:
#   volumes:
#     - name: data
#       persistentVolumeClaim:
#         claimName: data
#   containers[].volumeMounts:
#     - { name: data, mountPath: /var/lib/data }
# Check: kubectl get pv,pvc -A   STATUS Bound; a Pending PVC with WaitForFirstConsumer is normal until a Pod uses it.
# Reclaim: Retain leaves the PV Released; delete it and recreate (or clear spec.claimRef) to reuse.
Troubleshooting order: the cluster first, then the node

kubectl get

what is not Running or Ready?

describe and logs

events and errors say why

Node shell

systemctl and journalctl for the kubelet

crictl

containers, even with the API down

Start with kubectl. Go to a node shell only when kubectl points there, or when the API server does not answer.

Troubleshooting (30%): inside the cluster, then on the node
k get nodes; k describe node <node> | grep -A8 Conditions; k top nodes
k get pods -A --field-selector=status.phase!=Running
k get pods -A -o wide | grep -vE 'Running|Completed'
k describe pod web -n ns | tail -25                      # Events: image pull, scheduling, probes, mounts
k logs web -n ns; k logs web -c app --previous; k logs -l app=web --all-containers --tail=50
k logs deploy/web -n ns --since=10m -f
k get events -n ns --sort-by=.lastTimestamp; k events --for pod/web -n ns
k top pods -A --sort-by=memory; k top pod web --containers -n ns
k exec -it web -n ns -- sh; k exec web -n ns -- cat /etc/resolv.conf
k debug -it web -n ns --image=busybox:1.36 --target=app      # ephemeral container sharing the process namespace
k debug web -n ns -it --copy-to=web-debug --container=app -- sh   # a copy with a new command
k debug node/cka-worker -it --image=busybox:1.36              # host filesystem at /host
k get --raw '/readyz?verbose'; k get --raw '/livez?verbose'
k -n kube-system get pods -o wide; k -n kube-system logs kube-apiserver-cka-control-plane --tail=50
k -n kube-system logs kube-scheduler-cka-control-plane; k -n kube-system logs kube-controller-manager-cka-control-plane
k get svc,endpointslices -n ns; k get netpol -A
k auth can-i create pods --as=system:serviceaccount:ns:app -n ns
k get pod web -o yaml | grep -E 'image:|nodeName|serviceAccountName|phase|reason|message'

# --- On a node (lab: docker exec -it cka-control-plane bash; exam: ssh <node>, then sudo -i)
systemctl status kubelet; systemctl restart kubelet; systemctl enable --now kubelet
journalctl -u kubelet --no-pager --since '10 min ago' | tail -50
journalctl -u kubelet -f
cat /var/lib/kubelet/config.yaml                       # staticPodPath, clusterDNS, authentication
cat /etc/kubernetes/kubelet.conf                       # server URL, client certs
cat /var/lib/kubelet/kubeadm-flags.env                 # extra kubelet args
ls /etc/kubernetes/manifests/                          # static pod manifests; a typo here breaks the control plane
ls /etc/kubernetes/pki/                                # certificates

systemctl status containerd; journalctl -u containerd --no-pager | tail -30
crictl ps -a; crictl ps -a | grep -i apiserver
crictl logs <container-id>; crictl logs --tail=50 <container-id>
crictl pods; crictl images; crictl inspect <container-id>
cat /etc/crictl.yaml                                   # runtime endpoint if crictl complains

ip addr; ip route; cat /etc/cni/net.d/*                # pod network
ss -ltnp | grep -E '6443|10250|2379'                   # apiserver, kubelet, etcd listening?
df -h; free -m; top -bn1 | head -15                    # disk pressure, memory pressure
swapon --show                                          # kubelet refuses to start with swap on unless configured
cat /etc/hosts; nslookup kubernetes.default.svc.cluster.local 10.96.0.10 # DNS from the node
TopicSearch phrase (kubernetes.io/docs)Page it lands on
, rollouts, undodeploymentDeployments
rbacUsing RBAC Authorization
account tokensConfigure Service Accounts for
Client certs, certificate signing requestsCertificate Signing Requests
upgradekubeadm upgradeUpgrading kubeadm clusters
kubeadm init and joincreating a cluster with kubeadmCreating a cluster with kubeadm
HA highly available kubeadmCreating Highly Available Clusters with kubeadm
backup and restoreetcd backupOperating etcd clusters for Kubernetes
Drain a nodesafely nodeSafely Drain a Node
Static podsstatic podCreate
(helm.sh/docs) helm install, helm upgrade, helm rollbackHelm Install / Upgrade / Rollback
kustomizeDeclarative Management of Kubernetes Objects Using Kustomize
custom resource definitionsExtend the Kubernetes API with CustomResourceDefinitions
Operatorsoperator patternOperator pattern
, , interfaceContainer Runtime Interface (CRI), and Network Plugins for CNI
configmapConfigMaps
secretSecrets
Resources, requests, limitsresource management pods Resource Management for Pods and Containers
, limit range / resource quotasLimit Ranges / Resource Quotas
nodeSelector, assign pods to nodesAssigning Pods to Nodes
Taints and and tolerationsTaints and Tolerations
Topology spreadtopology spread constraintsPod Topology Spread Constraints
Probesliveness readiness startup Configure Liveness, Readiness and Startup Probes
Init containers, / sidecar containersInit Containers / Sidecar Containers
, , , daemonset / job / cronjob / statefulsetThe page named after each one
horizontalpodautoscaler walkthroughHorizontalPodAutoscaler Walkthrough
pod disruption budgetSpecifying a Disruption Budget for your Application
pod security admissionPod Security Admission
Priority and preemptionpod priority preemptionPod Priority and Preemption
ServicesserviceService
DNS namesdns pod serviceDNS for Services and Pods
customizationcustomizing dns serviceCustomizing DNS Service
ingressIngress
gateway apiGateway API (and gateway-api.sigs.k8s.io for the full spec)
network policiesNetwork Policies
, access modes, reclaimpersistent volumesPersistent Volumes
storage classesStorage Classes
VolumesvolumesVolumes
debugdebug running podDebug Running Pods
Node debugging, crictlDebugging Kubernetes nodes with crictl
Cluster troubleshootingtroubleshooting clustersTroubleshooting Clusters
Metrics, kubectl topresource metrics pipelineResource metrics pipeline
Logginglogging architectureLogging Architecture
kubectl referencecheat sheetkubectl Quick Reference
jsonpathJSONPath Support
Multiple clusters, contextsconfigure access multiple clustersConfigure Access to Multiple Clusters

In the official docs· open on exam day too

Finished this lesson?

This is a reference lesson. Mark it done once you have read it.