Chuyển đến nội dung chính

Lesson 6: ConfigMaps & Secrets

Creating and consuming ConfigMaps and Secrets in Kubernetes. Injection via env vars (envFrom, valueFrom) and volume mounts. Secret types and security considerations.

ConfigMap and Secret injection — envFrom, valueFrom and Volume Mount

1. ConfigMap

ConfigMap stores non-sensitive key-value pairs. Not encrypted (plain text).

# Create ConfigMap — Imperative
kubectl create configmap app-config \
  --from-literal=DB_HOST=mysql \
  --from-literal=DB_PORT=3306

kubectl create configmap app-config --from-file=config.properties
kubectl create configmap app-config --from-env-file=.env

# Declarative YAML
apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
data:
  DB_HOST: mysql
  DB_PORT: "3306"
  config.properties: |
    server.port=8080
    debug=false

2. Secret

Secret stores sensitive data. It is base64 encoded (not encrypted — just encoded!).

# Create Secret — Imperative
kubectl create secret generic db-secret \
  --from-literal=username=admin \
  --from-literal=password=mypassword

kubectl create secret generic db-secret --from-file=credentials.txt

# Declarative (base64 encode first)
echo -n 'admin' | base64    # YWRtaW4=
echo -n 'mypassword' | base64  # bXlwYXNzd29yZA==

apiVersion: v1
kind: Secret
metadata:
  name: db-secret
type: Opaque
data:
  username: YWRtaW4=
  password: bXlwYXNzd29yZA==
Secret TypePurpose
OpaqueGeneric — default type, any key-value data
kubernetes.io/dockerconfigjsonDocker registry credentials
kubernetes.io/tlsTLS certificate and private key
kubernetes.io/service-account-tokenServiceAccount token (auto-created)

Exam tip: Secret data is base64 encoded, not encrypted. Anyone with permission to read a Secret can decode it: echo 'YWRtaW4=' | base64 -d. To encrypt at rest, you must enable EncryptionConfiguration — but CKAD does not test this. The exam typically tests: creating a Secret and injecting it into a Pod.

3. Inject via Environment Variables

spec:
  containers:
  - name: app
    image: myapp

    # Method 1: envFrom — load ALL keys as env vars
    envFrom:
    - configMapRef:
        name: app-config
    - secretRef:
        name: db-secret

    # Method 2: valueFrom — load SPECIFIC key
    env:
    - name: DATABASE_HOST
      valueFrom:
        configMapKeyRef:
          name: app-config
          key: DB_HOST
    - name: DB_PASSWORD
      valueFrom:
        secretKeyRef:
          name: db-secret
          key: password

4. Inject via Volume Mount

spec:
  volumes:
  - name: config-vol
    configMap:
      name: app-config
  - name: secret-vol
    secret:
      secretName: db-secret

  containers:
  - name: app
    image: myapp
    volumeMounts:
    - name: config-vol
      mountPath: /etc/config    # Each key becomes a file
    - name: secret-vol
      mountPath: /etc/secrets
      readOnly: true

  # Result: /etc/config/DB_HOST contains "mysql"
  #         /etc/secrets/password contains "mypassword" (decoded)
MethodWhen to UseAuto-update when CM/Secret changes?
envFrom / env.valueFromApp reads env varsNo (requires pod restart)
Volume mountApp reads from files, or needs auto-reloadYes (after ~1-2 minutes)

Exam tip: Volume-mounted ConfigMaps/Secrets auto-update when the source changes (after kubelet sync period ~1 minute). Env vars require a pod restart to reflect changes. CKAD often tests both methods — know the syntax for configMapKeyRef vs configMapRef (the one with "Key" is for a single key).

5. Cheat Sheet

TaskCommand / YAML
Create CM from literalskubectl create cm name --from-literal=k=v
Create Secret from literalskubectl create secret generic n --from-literal=k=v
Load all CM keys as envenvFrom: - configMapRef: name: ...
Load a specific keyenv: - valueFrom: configMapKeyRef: ...
Mount as filesvolumes: configMap/secret + volumeMounts

6. Practice Questions

Q1: A Pod needs to consume ALL key-value pairs from a ConfigMap named "app-settings" as environment variables. Which configuration is correct?

  • A) env: - name: APP_SETTINGS valueFrom: configMapRef: name: app-settings
  • B) envFrom: - configMapRef: name: app-settings ✓
  • C) volumes: - configMap: name: app-settings
  • D) env: - configMapKeyRef: name: app-settings key: "*"

Explanation: envFrom with configMapRef loads ALL keys from the ConfigMap as environment variables. env with valueFrom configMapKeyRef only loads ONE specific key. The wildcard "*" syntax does not exist.

Q2: You create a Secret with the command: kubectl create secret generic mysecret --from-literal=password=secret123. How is the data stored in etcd?

  • A) Plain text: "password=secret123"
  • B) AES-256 encrypted
  • C) Base64 encoded ✓
  • D) SHA-256 hashed

Explanation: By default, Kubernetes stores Secret data as base64 encoded values in etcd — NOT encrypted. Base64 is encoding, not encryption. Anyone with etcd access can decode it. To encrypt at rest, an EncryptionConfiguration must be configured separately.

Q3: A ConfigMap is updated with new values. A Pod is using this ConfigMap mounted as a volume at /etc/config. What happens?

  • A) The Pod fails immediately because the config changed
  • B) The files in /etc/config are automatically updated (with a short delay) ✓
  • C) Nothing happens — the Pod must be restarted to see changes
  • D) The Pod is restarted automatically by Kubernetes

Explanation: Volume-mounted ConfigMaps are automatically updated when the ConfigMap changes, after the kubelet sync period (typically ~1 minute). Environment variables from ConfigMaps do NOT auto-update — the Pod must be recreated. Applications that watch for file changes can react to these updates without restarts.