Модуль 6 / 19
ConfigMap і Secret
Зміст
1. Цілі модуля
Після модуля ви зможете відокремлювати конфігурацію від image, обирати ConfigMap або Secret, передавати значення як environment variables і files, прогнозувати оновлення даних та діагностувати CreateContainerConfigError.
- ConfigMap для нечутливої конфігурації
- Secret для чутливих даних
- env і projected volume
- безпека, оновлення та immutable resources
2. Теорія: ConfigMap
ConfigMap зберігає несекретні пари ключ-значення в data та бінарні значення в binaryData. Pod може використовувати їх як environment variables, аргументи команди або files у volume.
ConfigMap не призначений для паролів і токенів. Конфігурація є частиною контракту застосунку: імена keys, формат files, обов’язковість і типові значення слід документувати.
3. Теорія: Secret і модель загроз
Secret відокремлює чутливі дані від PodSpec та image, але base64 є кодуванням, а не шифруванням. Типово дані Secret можуть зберігатися в etcd без шифрування.
Для production увімкніть encryption at rest, обмежте get/list/watch через RBAC, надавайте Secret лише потрібному контейнеру, виключайте значення з Git і logs, розгляньте зовнішній secret store та ротацію.
4. Теорія: env, volume та оновлення
Environment variable зчитується під час запуску контейнера й не оновлюється у працюючому процесі. Зміна ConfigMap або Secret потребує повторного створення Pod, якщо застосунок отримує значення через env.
Файли звичайного ConfigMap/Secret volume оновлюються eventual-consistently після синхронізації kubelet. Застосунок має перечитати файл. Mount через subPath автоматичних оновлень не отримує. immutable об’єкт не можна змінити — створіть новий і оновіть посилання.
5. Методичні вказівки
- Не зберігайте реальні секрети в manifest або Git, навіть у base64
- Використовуйте stringData лише як зручне введення, а не захист
- Перед rollout перевіряйте наявність об’єкта та обов’язкових keys
- Надавайте перевагу file mount для секретів, якщо застосунок це підтримує
- Не друкуйте secret values у CI, logs або діагностичному виводі
- Для керованого оновлення використовуйте versioned names або checksum annotation
6. Лабораторна робота: конфігурація застосунку
Збережіть маніфест як config-lab.yaml. Навчальний Secret містить нечутливе демонстраційне значення; не копіюйте цей підхід для реальних credentials.
apiVersion: v1
kind: Namespace
metadata:
name: lab-config
---
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
namespace: lab-config
data:
APP_COLOR: blue
app.conf: |
color=blue
log_level=info
---
apiVersion: v1
kind: Secret
metadata:
name: app-secret
namespace: lab-config
type: Opaque
stringData:
API_TOKEN: training-token
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: app
namespace: lab-config
spec:
replicas: 2
selector:
matchLabels:
app.kubernetes.io/name: config-demo
template:
metadata:
labels:
app.kubernetes.io/name: config-demo
spec:
automountServiceAccountToken: false
containers:
- name: app
image: busybox:1.37.0
command: ["sh", "-c", "sleep 3600"]
env:
- name: APP_COLOR
valueFrom:
configMapKeyRef:
name: app-config
key: APP_COLOR
- name: API_TOKEN
valueFrom:
secretKeyRef:
name: app-secret
key: API_TOKEN
volumeMounts:
- name: config
mountPath: /etc/app
readOnly: true
- name: secret
mountPath: /var/run/secrets/course
readOnly: true
volumes:
- name: config
configMap:
name: app-config
- name: secret
secret:
secretName: app-secret
defaultMode: 04007. Лабораторна робота: env і files
Застосуйте об’єкти й перевірте ConfigMap через env і volume, а Secret — лише за наявністю захищеного файла, не виводячи його вміст.
kubectl apply -f config-lab.yaml
kubectl rollout status deployment/app -n lab-config --timeout=120s
kubectl get configmap app-config -n lab-config -o yaml
kubectl get secret app-secret -n lab-config -o jsonpath='{.type}{" keys="}{.data.API_TOKEN}{"\n"}'
kubectl exec -n lab-config deployment/app -- printenv APP_COLOR
kubectl exec -n lab-config deployment/app -- cat /etc/app/app.conf
kubectl exec -n lab-config deployment/app -- ls -l /var/run/secrets/course
kubectl get pods -n lab-configКритерій: два Ready Pod, APP_COLOR=blue, /etc/app/app.conf містить очікувані рядки, secret file має обмежений mode.
8. Лабораторна робота: оновлення
Оновіть ConfigMap. Mounted file зміниться не миттєво, а environment variable залишиться старою до створення нового Pod. Потім виконайте rollout restart.
kubectl patch configmap app-config -n lab-config --type=merge -p '{"data":{"APP_COLOR":"green","app.conf":"color=green\nlog_level=debug\n"}}'
kubectl get configmap app-config -n lab-config -o jsonpath='{.metadata.resourceVersion}{"\n"}'
kubectl exec -n lab-config deployment/app -- cat /etc/app/app.conf
kubectl exec -n lab-config deployment/app -- printenv APP_COLOR
kubectl rollout restart deployment/app -n lab-config
kubectl rollout status deployment/app -n lab-config --timeout=120s
kubectl exec -n lab-config deployment/app -- printenv APP_COLORКритерій: до restart файл містить green, а env ще blue; після restart новий Pod отримує APP_COLOR=green.
9. Діагностика: відсутній ключ Secret
Навмисно замініть secretKeyRef.key на відсутній. Нові Pods не зможуть створити контейнер і отримають CreateContainerConfigError; старі Pods може зберігати стратегія Deployment.
kubectl patch deployment app -n lab-config --type=json -p='[{"op":"replace","path":"/spec/template/spec/containers/0/env/1/valueFrom/secretKeyRef/key","value":"missing"}]'
kubectl rollout status deployment/app -n lab-config --timeout=30s
kubectl get deployment,replicaset,pod -n lab-config
kubectl get pods -n lab-config -o jsonpath='{range .items[*]}{.metadata.name}{" phase="}{.status.phase}{" waiting="}{.status.containerStatuses[0].state.waiting.reason}{"\n"}{end}'
kubectl describe pods -n lab-config -l app.kubernetes.io/name=config-demo
kubectl events -n lab-config --types=Warning
kubectl patch deployment app -n lab-config --type=json -p='[{"op":"replace","path":"/spec/template/spec/containers/0/env/1/valueFrom/secretKeyRef/key","value":"API_TOKEN"}]'
kubectl rollout status deployment/app -n lab-config --timeout=120s
kubectl delete namespace lab-configАлгоритм: Deployment Conditions → новий ReplicaSet → waiting.reason → Pod Events → перевірка object name і key → мінімальне виправлення посилання. Logs контейнера відсутні, бо процес ще не запускався.
10. Контроль і шпаргалка
- Чому base64 не захищає Secret?
- Чим оновлення env відрізняється від mounted file?
- Чому subPath не отримує оновлення?
- Які права RBAC особливо небезпечні для Secrets?
- Чому CreateContainerConfigError не діагностують через application logs?
Модуль засвоєно, якщо ви безпечно підключаєте конфігурацію, пояснюєте момент появи оновлень і відновлюєте rollout з відсутнім key за Events без розкриття Secret.
PDF для роботи офлайн
Завантажте оформлену версію модуля для читання без підключення до мережі.