1. ConfigMap
ConfigMap lưu trữ cặp key-value non-sensitive. Không được mã hóa (plain text).
# Tạo 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 lưu trữ sensitive data. Được base64 encode (không phải mã hóa — encode thôi!).
# Tạo 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 trước)
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 Type | Mục đích |
|---|---|
Opaque | Generic — default type, any key-value data |
kubernetes.io/dockerconfigjson | Docker registry credentials |
kubernetes.io/tls | TLS certificate và private key |
kubernetes.io/service-account-token | ServiceAccount token (auto-created) |
Exam tip: Secret data là base64 encoded, không encrypted. Bất kỳ ai có quyền đọc Secret đều có thể decode:
echo 'YWRtaW4=' | base64 -d. Để encrypt at rest, phải enable EncryptionConfiguration — nhưng CKAD không test điều này. Exam thường test: tạo secret và inject vào Pod.
3. Inject qua 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 qua 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)
| Method | Khi dùng | Auto-update khi CM/Secret đổi? |
|---|---|---|
envFrom / env.valueFrom | App đọc env vars | Không (cần restart pod) |
| Volume mount | App đọc từ files, hoặc cần auto-reload | Có (sau ~1-2 phút) |
Exam tip: Volume-mounted ConfigMaps/Secrets tự động update khi nguồn thay đổi (sau kubelet sync period ~1 phút). Env vars phải restart pod mới reflect changes. CKAD thường test cả 2 methods — nắm rõ syntax của
configMapKeyRefvsconfigMapRef(có chữ "Key" thì là single key).
5. Cheat Sheet
| Task | Command / YAML |
|---|---|
| Tạo CM từ literals | kubectl create cm name --from-literal=k=v |
| Tạo Secret từ literals | kubectl create secret generic n --from-literal=k=v |
| Load all CM keys as env | envFrom: - configMapRef: name: ... |
| Load specific key | env: - valueFrom: configMapKeyRef: ... |
| Mount as files | volumes: 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.