Decoupling application code from environment configuration and enforcing security policies is tested extensively on the CKAD exam. You must know how to pass ConfigMaps and Secrets into Pods as environment variables or volume mounts.
TL;DR (Quick Summary)#
- Create ConfigMap:
kubectl create configmap app-config --from-literal=DB_HOST=postgres --from-literal=DB_PORT=5432 - Create Secret:
kubectl create secret generic db-credentials --from-literal=password=SuperSecret123 - SecurityContext: Enforce container immutability (
readOnlyRootFilesystem: true,runAsNonRoot: true,allowPrivilegeEscalation: false). - ServiceAccount: Associate custom ServiceAccounts with Pods using
serviceAccountName: app-sa.
1. Configuration & Secret Injection Architecture#
graph TD
subgraph K8sConfig ["Cluster Configuration"]
CM["ConfigMap: app-config
(DB_HOST, DB_PORT)"]
Sec["Secret: db-pass
(password: base64)"]
end
subgraph PodExecution ["Pod Execution Environment"]
Pod1["Pod Containers"]
EnvVars["Environment Variables
(envFrom / valueFrom)"]
VolMounts["Volume Mounts
(/etc/config, /etc/secrets)"]
end
CM -->|Inject as| EnvVars
Sec -->|Mount as| VolMounts
EnvVars --> Pod1
VolMounts --> Pod1
2. CKAD Terminal Hands-on Drills#
Scenario A: Inject ConfigMap as Environment Variables#
Create a ConfigMap named web-env and inject all its key-value pairs into a Pod named backend-api.
# 1. Create ConfigMap
kubectl create configmap web-env \
--from-literal=APP_MODE=production \
--from-literal=LOG_LEVEL=debugbackend-api.yaml:
apiVersion: v1
kind: Pod
metadata:
name: backend-api
spec:
containers:
- name: api
image: busybox:1.36
command: ["sh", "-c", "env && sleep 3600"]
envFrom:
- configMapRef:
name: web-envVerify injected variables inside container:
kubectl apply -f backend-api.yaml
kubectl logs backend-api | grep -E "APP_MODE|LOG_LEVEL"Scenario B: Mount Secret as Files in Volume#
Create a secret tls-certs and mount it into a Pod at /etc/tls as read-only files.
kubectl create secret generic tls-certs \
--from-literal=cert.pem=FAKE_CERT_DATA \
--from-literal=key.pem=FAKE_KEY_DATAsecure-pod.yaml:
apiVersion: v1
kind: Pod
metadata:
name: secure-pod
spec:
volumes:
- name: cert-volume
secret:
secretName: tls-certs
containers:
- name: web
image: nginx:1.25-alpine
volumeMounts:
- name: cert-volume
mountPath: /etc/tls
readOnly: trueScenario C: Enforce Pod & Container SecurityContext#
Create a Pod named restricted-pod enforcing non-root user execution (UID 10001), dropping all Linux capabilities except NET_BIND_SERVICE, and setting the filesystem as read-only.
restricted-pod.yaml:
apiVersion: v1
kind: Pod
metadata:
name: restricted-pod
spec:
securityContext:
runAsNonRoot: true
runAsUser: 10001
runAsGroup: 10001
fsGroup: 2000
containers:
- name: app
image: busybox:1.36
command: ["sh", "-c", "sleep 3600"]
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop:
- ALL
add:
- NET_BIND_SERVICEScenario D: Assign Custom ServiceAccount#
Create a ServiceAccount app-monitor-sa and attach it to a Pod.
kubectl create serviceaccount app-monitor-sasa-pod.yaml:
apiVersion: v1
kind: Pod
metadata:
name: sa-pod
spec:
serviceAccountName: app-monitor-sa
containers:
- name: monitor
image: busybox:1.36
command: ["sleep", "3600"]Summary & Next Steps#
In this episode, we covered:
- ConfigMap and Secret creation via
kubectl. - Ingesting configurations via
envFromand Secret volume mounts. - Hardening containers using
securityContext(runAsNonRoot,readOnlyRootFilesystem). - Binding custom ServiceAccounts.
In CKAD Episode 4: Services, Ingress & Network Policies, we will expose workloads externally and construct network firewall rules!

