В чому різниця між ConfigMap та Secret?
Для звичайних налаштувань:
Junior рівень
Просте пояснення
ConfigMap та Secret — це об’єкти Kubernetes для зберігання налаштувань додатку окремо від коду. Різниця в тому, що ConfigMap для звичайних налаштувань, а Secret — для паролів та чутливих даних.
Проста аналогія
- ConfigMap — як стікер на моніторі з налаштуваннями (адреса сервера, порт)
- Secret — як сейф з паролями та ключами
ConfigMap
Для звичайних налаштувань:
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
DB_HOST: "postgres.default.svc.cluster.local"
DB_PORT: "5432"
APP_ENV: "production"
Secret
Для паролів та ключів:
apiVersion: v1
kind: Secret
metadata:
name: app-secret
type: Opaque
data:
DB_PASSWORD: cGFzc3dvcmQxMjM= # base64 від "password123"
API_KEY: c2VjcmV0LWtleQ== # base64 від "secret-key"
Важливо: base64 — це не шифрування! Це просто кодування. Будь-хто може декодувати.
Як використовувати в Pod’і?
Як змінні оточення:
containers:
- name: app
image: myapp
env:
- name: DB_HOST
valueFrom:
configMapKeyRef:
name: app-config
key: DB_HOST
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: app-secret
key: DB_PASSWORD
Як файли (volume):
volumes:
- name: config-volume
configMap:
name: app-config
- name: secret-volume
secret:
secretName: app-secret
Порівняння
| ConfigMap | Secret | |
|---|---|---|
| Дані | Звичайний текст | Base64 |
| Для чого | Налаштування | Паролі, ключі |
| Безпека | Низька | Середня (потрібен RBAC) |
Що запам’ятати Junior-розробнику
- ConfigMap — для звичайних налаштувань, Secret — для паролів
- Secret зберігається в base64 (це не шифрування!)
- Обидва можна використовувати як змінні або як файли
- Файли з ConfigMap/Secret оновлюються без перезапуску Pod’а
- Не зберігайте секрети в git — використовуйте external secrets
Коли НЕ використовувати ConfigMap/Secret
НЕ зберігайте в ConfigMap: великі файли (>1MB ліміт), бінарні файли. НЕ зберігайте в Secret: секрети зовнішніх систем (API-ключі третіх сторін) – краще Vault.
Middle рівень
Зберігання даних
ConfigMap:
- Дані у відкритому текстовому вигляді в etcd
- Ліміт розміру: 1 МБ (обмеження etcd)
Secret:
- Дані в base64 (НЕ шифрування! base64 легко декодується). Для шифрування потрібен EncryptionConfiguration або зовнішнє рішення (Vault, Sealed Secrets).
- Secrets зберігаються в etcd у відкритому вигляді (якщо не увімкнено EncryptionConfiguration). Доступ до etcd = доступ до всіх Secret’ів.
- Для реального захисту потрібно увімкнути Encryption at Rest в etcd
Два способи використання
1. Environment Variables
env:
- name: DB_HOST
valueFrom:
configMapKeyRef:
name: app-config
key: DB_HOST
Плюс: просто Мінус: не оновлюються “на льоту” без перезапуску Pod’а
2. Volumes (монтування файлами)
volumeMounts:
- name: config-volume
mountPath: /etc/config
readOnly: true
Плюс: оновлюються автоматично (Kubelet оновлює файли) Мінус: додаток має вміти перечитувати конфіг
Immutable ConfigMap/Secret
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
APP_ENV: "production"
immutable: true # Не можна змінити після створення
Переваги:
- Захист від випадкових змін
- Знижує навантаження на kube-apiserver
- Kubelet не моніторить зміни
External Secrets
Для великих проектів використовуйте External Secrets Operator:
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: db-credentials
spec:
secretStoreRef:
name: aws-secrets-manager
kind: ClusterSecretStore
target:
name: db-credentials-secret
data:
- secretKey: DB_PASSWORD
remoteRef:
key: prod/db/password
Синхронізує секрети з HashiCorp Vault, AWS Secrets Manager, Azure Key Vault.
Що запам’ятати Middle-розробнику
- Secret в base64 ≠ шифрування. Потрібне додаткове налаштування.
- Env vars не оновлюються, volumes — оновлюються автоматично
- Immutable об’єкти захищають від випадкових змін
- External Secrets Operator — стандарт для production
- RBAC: обмежуйте доступ до Secrets
Senior рівень
Архітектура зберігання секретів
Без Encryption at Rest:
etcd зберігає: DB_PASSWORD: cGFzc3dvcmQxMjM=
Будь-хто з доступом до etcd може декодувати.
З Encryption at Rest:
# kube-apiserver configuration
encryption-provider-config:
kind: EncryptionConfiguration
resources:
- resources: ["secrets"]
providers:
- aescbc:
keys:
- name: key1
secret: <base64-encoded-key>
- identity: {}
Тепер секрети шифруються в etcd.
Безпека: глибокий аналіз
| Рівень | Захист | Опис |
|---|---|---|
| Base64 only | Ні | Будь-хто з доступом до etcd/API читає |
| RBAC | Частковий | Обмежує доступ до API |
| Encryption at Rest | Хороший | Шифрує дані в etcd |
| External KMS | Найкращий | Ключі шифрування поза кластером |
RBAC для Secrets
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: secret-reader
rules:
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get", "list"]
resourceNames: ["app-secret"] # тільки конкретний secret
Порівняння підходів: Env vs Volume
| Аспект | Env Vars | Volumes |
|---|---|---|
| Оновлення | Вимагає restart Pod | Автоматичне |
| Розмір | Підходить для простих значень | Підходить для файлів |
| Безпека | Видно в kubectl describe pod |
Тільки через exec в контейнер |
| Hot reload | Ні | Так (додаток має перечитати) |
Spring Boot + ConfigMap/Secret
ConfigMap як application.properties:
apiVersion: v1
kind: ConfigMap
metadata:
name: spring-config
data:
application.properties: |
spring.datasource.url=jdbc:postgresql://db:5432/mydb
spring.jpa.hibernate.ddl-auto=validate
volumeMounts:
- name: config
mountPath: /config
readOnly: true
env:
- name: SPRING_CONFIG_LOCATION
value: "file:/config/application.properties"
Secret Management: еволюція
Level 0: Секрети в git (anti-pattern)
Level 1: Kubernetes Secrets (base64)
Level 2: Secrets + Encryption at Rest
Level 3: External Secrets Operator + Vault/KMS
Level 4: Service Mesh (mTLS) + SPIFFE/SPIRE (identity)
Immutable об’єкти: коли використовувати
immutable: true
Використовуйте, коли:
- Конфігурація не змінюється між деплоями
- Хочете додатковий захист від змін
- Зниження навантаження на API server (великі ConfigMap)
Не використовуйте, коли:
- Налаштування змінюються динамічно
- A/B testing з різними конфігами
Troubleshooting
Secret не монтується:
kubectl describe pod myapp
# Warning: Couldn't find secret app-secret in namespace default
Причини:
- Secret не створений
- Secret в іншому namespace
- Помилка в імені
ConfigMap оновився, але Pod не бачить змін:
- Volume update delay: Kubelet оновлює файли з затримкою (syncPeriod, за замовчуванням 1 хв)
- Додаток не перечитує файл — потрібен hot reload mechanism
Підсумок для Senior
- ConfigMap для конфігів, Secret — для паролів.
- Secret за замовчуванням не безпечний без Encryption at Rest або зовнішнього KMS.
- Віддавайте перевагу монтуванню файлами для hot reload.
- External Secrets Operator + Vault/KMS — production стандарт.
- RBAC: обмежуйте доступ до Secrets за принципом найменших привілеїв.
- Immutable об’єкти: захист від змін + зниження навантаження на API.
- Spring Boot: монтуйте ConfigMap як application.properties для динамічної конфігурації.
🎯 Шпаргалка для інтерв’ю
Обов’язково знати:
- ConfigMap — звичайні налаштування (текст), Secret — чутливі дані (base64)
- Base64 ≠ шифрування! Будь-хто може декодувати; потрібна Encryption at Rest
- Обидва можна використовувати як env vars (не оновлюються без restart) або volumes (auto-update)
- Ліміт розміру: 1 МБ (обмеження etcd)
- Immutable ConfigMap/Secret — захист від змін + зниження навантаження на API server
- External Secrets Operator + Vault/KMS — production стандарт
- RBAC: обмежуйте доступ до Secrets за принципом least privilege
Часті уточнюючі запитання:
- «Secret безпечно зберігає паролі?» — За замовчуванням ні (base64 в etcd); потрібна EncryptionConfiguration
- «Env vars vs volumes?» — Volumes оновлюються автоматично, env vars вимагають restart Pod
- «Що таке External Secrets Operator?» — Синхронізує секрети з Vault, AWS Secrets Manager, Azure Key Vault
- «Коли використовувати immutable?» — Коли конфіг не змінюється між деплоями (захист + performance)
Червоні прапорці (НЕ говорити):
- «Secrets зашифровані в K8s» (тільки base64; потрібно увімкнути Encryption at Rest)
- «Зберігаю секрети в git в base64» (це не шифрування, будь-хто декодує)
- «ConfigMap для паролів» (використовуйте Secret)
- «Env vars оновлюються без restart» (тільки volumes auto-update)
Пов’язані теми:
- [[Що таке Kubernetes і навіщо він потрібен]] — об’єкти K8s
- [[Що таке Ingress в Kubernetes]] — TLS secrets
- [[Як моніторити додатки в Kubernetes]] — моніторинг конфігурації