Stage 7 · Master
CKAD — Certified Kubernetes Application Developer
Application Environment & Config (25%)
ConfigMaps, Secrets, SecurityContext, and ServiceAccounts — the largest CKAD domain.
ConfigMaps
ConfigMaps store non-sensitive configuration data as key-value pairs. They can be mounted as volumes or injected as environment variables. ConfigMaps decouple configuration from container images.
# From literal values
kubectl create configmap my-config --from-literal=db_host=mysql --from-literal=db_port=3306
# From a file
kubectl create configmap my-config --from-file=config.yaml
# From a directory
kubectl create configmap my-config --from-file=./config-dir/ConfigMaps can be created from literals, files, or directories. Each key in the ConfigMap corresponds to a filename or literal key.
spec:
containers:
- name: app
image: my-app
envFrom:
- configMapRef:
name: my-config
volumeMounts:
- name: config-volume
mountPath: /etc/config
readOnly: true
volumes:
- name: config-volume
configMap:
name: my-configenvFrom injects all ConfigMap keys as environment variables. Volume mount makes ConfigMap data available as files. Files are updated automatically when the ConfigMap changes.
Secrets
Secrets store sensitive data like passwords, tokens, and certificates. They are base64-encoded by default but not encrypted. Use etcd encryption at rest for production security.
# From literal values
kubectl create secret generic my-secret --from-literal=username=admin --from-literal=password=s3cr3t
# From a file
kubectl create secret generic my-secret --from-file=ssh-key=~/.ssh/id_rsa
# TLS secret
kubectl create secret tls my-tls --cert=cert.pem --key=key.pem
# Decode a secret value
kubectl get secret my-secret -o jsonpath='{.data.password}' | base64 -d
echo ""Secrets are base64-encoded, not encrypted. Anyone with cluster access can decode them. Use etcd EncryptionConfiguration and external secret stores for real security.
Kubernetes Secrets are base64-encoded, which is not encryption. Enable etcd encryption at rest using EncryptionConfiguration. For production, use external secret stores like Vault or cloud provider secret managers.
SecurityContext
A SecurityContext defines privilege and access control settings for Pods and containers. It controls runAsUser, runAsNonRoot, readOnlyRootFilesystem, and capabilities.
spec:
securityContext:
runAsUser: 1000
runAsGroup: 3000
fsGroup: 2000
containers:
- name: app
image: my-app
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop:
- ALL
add:
- NET_BIND_SERVICEPod-level SecurityContext applies to all containers. Container-level SecurityContext overrides for that container. Drop ALL capabilities and add only what is needed.
ServiceAccounts
ServiceAccounts provide identity for Pods. By default, every Pod gets a default ServiceAccount in its namespace. ServiceAccounts are used for RBAC, API access, and external authentication.
apiVersion: v1
kind: ServiceAccount
metadata:
name: my-sa
namespace: production
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: pod-reader
namespace: production
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: my-binding
namespace: production
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: pod-reader
subjects:
- kind: ServiceAccount
name: my-sa
namespace: productionThis creates a ServiceAccount with a Role that allows reading Pods. The RoleBinding connects the Role to the ServiceAccount. The Pod can now read Pods in the production namespace.
ResourceQuotas and LimitRanges
ResourceQuotas limit total resource consumption per namespace. LimitRanges set default and maximum resource limits for individual containers. Together, they prevent resource abuse.
apiVersion: v1
kind: ResourceQuota
metadata:
name: my-quota
namespace: development
spec:
hard:
pods: "10"
requests.cpu: "4"
requests.memory: "8Gi"
limits.cpu: "8"
limits.memory: "16Gi"
---
apiVersion: v1
kind: LimitRange
metadata:
name: my-limits
namespace: development
spec:
limits:
- default:
cpu: "500m"
memory: "256Mi"
defaultRequest:
cpu: "100m"
memory: "128Mi"
type: ContainerThe ResourceQuota caps total resources in the namespace. The LimitRange sets default resource requests and limits for containers that do not specify them.
The Config and Security domain is 25% of the CKAD. Practice creating ConfigMaps and Secrets imperatively, mounting them as volumes and environment variables, and setting SecurityContext on Pods.
Key Commands
kubectl create configmap my-config --from-literal=key=value
kubectl create secret generic my-secret --from-literal=key=value
kubectl get configmap -A
kubectl get secret -A
kubectl describe configmap my-config
kubectl describe secret my-secret
kubectl get serviceaccounts -A
kubectl auth can-i --list --as=system:serviceaccount:default:my-sa
kubectl get resourcequotas -A
kubectl get limitranges -AUse kubectl auth can-i with --as to check what a ServiceAccount can do. This is essential for verifying RBAC configurations on the CKAD exam.
Mark this lesson complete to store local progress and unlock a cleaner resume path the next time you visit.