CKA — ConfigMaps & Secrets

5 minute read

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.

Next: Scaling & HPA →

Updated: