CKAD theory
CKAD25% of the exam

Environment, Configuration & Security

Feed config and secrets into apps, cap resources, control who can do what, and run with least privilege. The heaviest domain.

The full loop: understand → drill the commands → prove it under the clock. Every objective below is taught here and practised in the drills.

1Understand it

ConfigMaps & Secrets

Keep configuration out of your image so the same image runs everywhere. A ConfigMap holds non-sensitive settings; a Secret holds sensitive values. Inject either as environment variables or mounted files.

ConfigMap is the settings menu; a Secret is the locked drawer for passwords. The app reads them at runtime instead of baking them in.
  • Inject via env (envFrom / valueFrom) or as a mounted volume.
  • Secrets are only base64-encoded, not encrypted by default, treat as sensitive.
  • A mounted ConfigMap updates the file live; env vars need a Pod restart.

Three ways to inject config

envFrom:                         # all keys → env vars
- configMapRef: { name: app-config }
env:
- name: DB_PASS                  # one secret key → env var
  valueFrom:
    secretKeyRef: { name: db, key: password }
volumeMounts:                    # or mount as files
- name: cfg
  mountPath: /etc/config
Exam tip: kubectl create configmap app --from-literal=KEY=val · kubectl create secret generic db --from-literal=password=...
Requests, limits & quotas

A request is the resources a Pod is guaranteed (used by the scheduler to place it); a limit is the ceiling it can't exceed. Over a memory limit gets the container OOMKilled; over a CPU limit just throttles it. ResourceQuotas cap a whole namespace.

Request = the seat reserved for you; limit = the most you can take from the buffet before being cut off.
  • requests drive scheduling; limits cap usage.
  • Memory over limit → OOMKilled (exit 137); CPU over limit → throttled.
  • ResourceQuota and LimitRange govern a namespace.

Container requests (scheduling) + limits (cap)

resources:
  requests:
    cpu: "250m"
    memory: "256Mi"
  limits:
    cpu: "500m"
    memory: "512Mi"
Exam tip: Set both requests and limits. Right-size from real usage, not guesses.
SecurityContext

A SecurityContext controls how securely a container runs: which user it runs as, whether it can gain extra privileges, and which Linux capabilities it has. Running as non-root and dropping capabilities is the baseline for a hardened app.

It's the access-badge level you give the app, grant the least it needs, nothing more.
  • runAsNonRoot / runAsUser set identity.
  • allowPrivilegeEscalation: false and readOnlyRootFilesystem: true harden it.
  • capabilities.drop: [ALL], then add only what's needed.

Hardened SecurityContext (Pod level + container override)

spec:
  securityContext:               # applies to all containers
    runAsNonRoot: true
    runAsUser: 1000
  containers:
  - name: app
    image: myapp
    securityContext:             # overrides for this container
      allowPrivilegeEscalation: false
      readOnlyRootFilesystem: true
      capabilities: { drop: ["ALL"] }
Exam tip: securityContext sits at Pod level (all containers) or per-container (overrides).
ServiceAccounts

A ServiceAccount is the identity a Pod uses to talk to the Kubernetes API. By default Pods get the namespace's default account; for least privilege you create a dedicated ServiceAccount and grant it only the permissions (via RBAC) it needs.

A ServiceAccount is the app's employee ID badge, it decides which doors (API actions) the app can open.
  • spec.serviceAccountName sets which account a Pod uses.
  • Permissions come from RBAC (Roles + bindings), not the account itself.
  • Avoid the default account for anything that calls the API.
Exam tip: kubectl create serviceaccount app, then bind a Role to it for scoped access.
RBAC, authorization

RBAC decides who can do what. A Role is a set of allowed verbs (get, list, create…) on resources within a namespace; a RoleBinding grants that Role to a user or ServiceAccount. ClusterRole and ClusterRoleBinding do the same cluster-wide.

A Role is a job description (what actions are allowed); a RoleBinding is hiring a specific person into that job.
  • Role + RoleBinding = namespaced; ClusterRole + ClusterRoleBinding = cluster-wide.
  • Bind Roles to ServiceAccounts so Pods get scoped API access.
  • Least privilege: grant only the verbs and resources needed.

Grant a ServiceAccount read access to Pods, then verify

kubectl create role reader --verb=get,list,watch --resource=pods
kubectl create rolebinding read-pods \
  --role=reader --serviceaccount=dev:app-sa
kubectl auth can-i list pods --as=system:serviceaccount:dev:app-sa
Exam tip: kubectl auth can-i ... --as=... confirms a binding works without deploying anything.
Admission control

After a request is authenticated and authorized, admission controllers get the final say, they can validate or even mutate it before it's stored. This is how rules like "every Pod must set resource limits" or "no privileged containers" get enforced. Pod Security Admission (PSA) is the built-in one you'll meet most.

Auth is the bouncer checking your ID and the guest list; admission control is the dress-code check at the door, even valid guests can be turned away or asked to adjust.
  • Runs after authentication + authorization, before the object is saved.
  • Two kinds: validating (accept/reject) and mutating (modify defaults).
  • Pod Security Admission enforces baseline/restricted profiles per namespace.

Enforce the "restricted" Pod Security profile on a namespace

kubectl label namespace dev \
  pod-security.kubernetes.io/enforce=restricted
Exam tip: For CKAD, focus on recognising admission control and applying PSA labels (pod-security.kubernetes.io/enforce).
Custom Resources (awareness)

Kubernetes can be extended with Custom Resource Definitions (CRDs), new object types beyond the built-ins. Operators use these to manage complex apps. For CKAD you mainly recognise them and interact with existing custom resources, not author controllers.

CRDs add new kinds of "forms" to Kubernetes' filing system; an operator is the clerk that acts on those forms.
  • A CRD defines a new kind; instances are custom resources.
  • kubectl get <crd-plural> works just like built-in objects.
  • Operators = CRD + a controller that reconciles it.
Exam tip: kubectl api-resources lists every kind available, including CRDs.

2 Drill the commands & prove it

Mastery, 0/6 objectives

An objective turns green only when you've solved every drill in it, not just one.

  • Create and source ConfigMaps from literals, files, and env-files; inject as env/envFrom.0/5
  • Create generic, docker-registry, and tls Secrets imperatively and consume them safely.0/5
  • Set resource requests/limits on workloads and define ResourceQuota / LimitRange.0/3
  • Define pod and container securityContext: runAsNonRoot, runAsUser, fsGroup, capabilities, readOnlyRootFilesystem, privileged.0/6
  • Create ServiceAccounts, attach them to workloads, and test effective permissions with auth can-i --as.0/4
  • Author Roles, ClusterRoles and their bindings imperatively with correct subject syntax.0/4
Drill · 1 / 270 solved
Command

Create a ConfigMap named app-config with two literals: COLOR=blue and SIZE=large.

$

Drills check the command pattern deterministically, there is often more than one correct form. For full fidelity, pair this with real-cluster reps (the killer.sh simulator is included free with your exam registration).