CKA — ConfigMaps & Secrets
CKA Exam Domain
Workloads & Scheduling — 15%
Understand ConfigMaps and Secrets. Know how to create them and consume them in Pods.
ConfigMaps and Secrets are how you inject configuration into your workloads without baking values into container images. The CKA exam tests both creation and consumption patterns.
ConfigMaps
A ConfigMap stores non-confidential configuration data as key-value pairs. Pods can consume ConfigMap data as environment variables or mounted files.
Creating ConfigMaps
From literals:
kubectl create configmap app-config \
--from-literal=DB_HOST=mysql \
--from-literal=DB_PORT=3306
From a file:
kubectl create configmap app-config --from-file=config.properties
From a directory (all files in the directory become keys):
kubectl create configmap app-config --from-file=config-dir/
Declarative YAML:
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
namespace: default
data:
DB_HOST: mysql
DB_PORT: "3306"
app.properties: |
server.port=8080
server.name=myapp
Note: Values in ConfigMaps are stored as plain text strings. Numeric values must be quoted in YAML (
"3306").
Verify
kubectl get configmap app-config
kubectl describe configmap app-config
kubectl get configmap app-config -o yaml
Using ConfigMaps
As environment variables — envFrom (all keys)
apiVersion: v1
kind: Pod
metadata:
name: app
spec:
containers:
- name: app
image: nginx:1.27
envFrom:
- configMapRef:
name: app-config
Every key in app-config becomes an environment variable in the container.
As environment variables — valueFrom (specific key)
apiVersion: v1
kind: Pod
metadata:
name: app
spec:
containers:
- name: app
image: nginx:1.27
env:
- name: DATABASE_HOST
valueFrom:
configMapKeyRef:
name: app-config
key: DB_HOST
As a volume mount
apiVersion: v1
kind: Pod
metadata:
name: app
spec:
containers:
- name: app
image: nginx:1.27
volumeMounts:
- name: config-volume
mountPath: /etc/config
volumes:
- name: config-volume
configMap:
name: app-config
Each key becomes a file inside /etc/config/. For example, DB_HOST becomes /etc/config/DB_HOST with content mysql.
Exam tip: Volume-mounted ConfigMaps are automatically updated when the ConfigMap changes (with a short delay). Environment variables are not updated — the Pod must be restarted.
Secrets
A Secret stores sensitive data like passwords, tokens, and keys. Data is base64-encoded but not encrypted by default.
Important: Base64 is NOT encryption. Anyone with access to the Secret can decode it. For real encryption, enable encryption at rest in the API server.
Creating Secrets
From literals:
kubectl create secret generic db-creds \
--from-literal=username=admin \
--from-literal=password=secret123
From a file:
kubectl create secret generic tls-cert --from-file=cert.pem --from-file=key.pem
Declarative YAML (values must be base64-encoded):
apiVersion: v1
kind: Secret
metadata:
name: db-creds
type: Opaque
data:
username: YWRtaW4= # echo -n "admin" | base64
password: c2VjcmV0MTIz # echo -n "secret123" | base64
Or use stringData to provide plain text (Kubernetes encodes it for you):
apiVersion: v1
kind: Secret
metadata:
name: db-creds
type: Opaque
stringData:
username: admin
password: secret123
Verify
kubectl get secret db-creds
kubectl describe secret db-creds
kubectl get secret db-creds -o yaml
# Decode a value
kubectl get secret db-creds -o jsonpath='{.data.password}' | base64 -d
Using Secrets
As environment variables — envFrom
apiVersion: v1
kind: Pod
metadata:
name: app
spec:
containers:
- name: app
image: nginx:1.27
envFrom:
- secretRef:
name: db-creds
As environment variables — valueFrom (specific key)
env:
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-creds
key: password
As a volume mount
apiVersion: v1
kind: Pod
metadata:
name: app
spec:
containers:
- name: app
image: nginx:1.27
volumeMounts:
- name: secret-volume
mountPath: /etc/secrets
readOnly: true
volumes:
- name: secret-volume
secret:
secretName: db-creds
Each key becomes a file at /etc/secrets/. Files are readable only by the container process.
ConfigMap vs Secret
| Feature | ConfigMap | Secret |
|---|---|---|
| Purpose | Non-sensitive configuration | Sensitive data (passwords, tokens) |
| Encoding | Plain text | Base64-encoded |
| Encryption at rest | No (by default) | Optional (must configure) |
| Size limit | 1 MiB | 1 MiB |
| RBAC | Standard | Can restrict access to Secrets separately |
| Mounted file permissions | Default (0644) | Restricted (0644, but can set to 0400) |
| Consumed as | Env vars, volumes | Env vars, volumes |
Immutable ConfigMaps & Secrets
Starting from Kubernetes v1.21 (stable), you can mark a ConfigMap or Secret as immutable:
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
DB_HOST: mysql
immutable: true
apiVersion: v1
kind: Secret
metadata:
name: db-creds
type: Opaque
data:
password: c2VjcmV0MTIz
immutable: true
Benefits of immutable ConfigMaps/Secrets:
- Performance — Kubelet doesn’t need to watch for changes
- Safety — Prevents accidental modifications
- Scale — Reduces load on the API server in large clusters
Note: Once marked immutable, you cannot change the data or remove the immutable flag. You must delete and recreate the resource.
kubectl Commands
# ConfigMap operations
kubectl create configmap app-config --from-literal=key=value
kubectl get configmap
kubectl describe configmap app-config
kubectl get configmap app-config -o yaml
kubectl delete configmap app-config
# Secret operations
kubectl create secret generic db-creds --from-literal=password=secret
kubectl get secrets
kubectl describe secret db-creds
kubectl get secret db-creds -o yaml
kubectl delete secret db-creds
# Decode a Secret value
kubectl get secret db-creds -o jsonpath='{.data.password}' | base64 -d
Practice Questions
Q1. Create a ConfigMap named web-config with keys THEME=dark and LANGUAGE=en.
Show Answer
kubectl create configmap web-config \
--from-literal=THEME=dark \
--from-literal=LANGUAGE=en
Verify:
kubectl get configmap web-config -o yaml
Q2. Create a Pod named web that uses all keys from the web-config ConfigMap as environment variables.
Show Answer
apiVersion: v1
kind: Pod
metadata:
name: web
spec:
containers:
- name: web
image: nginx:1.27
envFrom:
- configMapRef:
name: web-config
kubectl apply -f web-pod.yaml
kubectl exec web -- env | grep -E "THEME|LANGUAGE"
Q3. Create a Secret named api-key with token=abc123. Then create a Pod that mounts it at /etc/api.
Show Answer
kubectl create secret generic api-key --from-literal=token=abc123
apiVersion: v1
kind: Pod
metadata:
name: api-consumer
spec:
containers:
- name: app
image: busybox:1.36
command: ["sleep", "3600"]
volumeMounts:
- name: api-secret
mountPath: /etc/api
readOnly: true
volumes:
- name: api-secret
secret:
secretName: api-key
Verify:
kubectl exec api-consumer -- cat /etc/api/token
# Output: abc123
Q4. How do you decode a Secret value stored in Kubernetes?
Show Answer
kubectl get secret <secret-name> -o jsonpath='{.data.<key>}' | base64 -d
Example:
kubectl get secret db-creds -o jsonpath='{.data.password}' | base64 -d
Q5. What happens if you try to update a ConfigMap that has immutable: true?
Show Answer
The API server will reject the update. Immutable ConfigMaps cannot be edited — you must delete and recreate the ConfigMap. This also means any Pods referencing it will need to be restarted to pick up the new ConfigMap name.
Next — learn how to scale your workloads to handle varying traffic.