В чём разница между 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 ≠ шифрование. Нужна additional настройка.
- 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]] — мониторинг конфигурации