8. Секреты и безопасность
В values.yaml и Git нельзя хранить пароли и ключи в открытом виде: любой с доступом к репозиторию или helm get values увидит секреты. В production обычно выбирают Sealed Secrets, SOPS (часто через плагин helm-secrets), External Secrets с Vault или другим бэкендом. Ниже — сравнение подходов и минимальные примеры «безопасного» деплоя.
Plain Secret и открытые values — почему это плохо
| Риск | Деталь |
|---|---|
| Git | История коммитов «помнит» секрет даже после удаления |
helm get values |
Values попадают в Secret релиза в namespace — см. RBAC |
| Логи CI | Случайный echo или артефакт с сырым YAML |
Допустимо только для локальной отладки и одноразовых учебных кластеров — и то без реальных учётных данных.
Sealed Secrets
Идея: в Git лежит SealedSecret, зашифрованный публичным ключом контроллера в кластере. Расшифровать может только тот кластер (или согласованная ротация ключей).
Учебный поток
# Сервер с установленным sealed-secrets-controller и kubeseal локально
kubectl create secret generic my-app \
--from-literal=api-key='REDACTED' \
--dry-run=client -o yaml \
| kubeseal -o yaml > templates/sealedsecret-my-app.yaml # путь внутри вашего chart
Далее SealedSecret можно рендерить через Helm как обычный шаблон (или хранить статично в templates/) и ставить helm upgrade — контроллер создаст обычный Secret.
Best practices:
- ротация ключей и runbook на аварийный сценарий;
- ограничить RBAC на
SealedSecretи итоговыйSecret; - не коммитить несшифрованный
Secret.
Документация: Sealed Secrets.
SOPS и плагин helm-secrets
Mozilla SOPS шифрует YAML/JSON (часто через KMS или age). Плагин helm-secrets позволяет передавать Helm расшифрованные values только на время выполнения на доверенной машине/агенте CI.
# Установка плагина (окружение команды может отличаться)
helm plugin install https://github.com/jkroepke/helm-secrets
# Пример вызова (файл values.enc.yaml зашифрован SOPS)
helm secrets upgrade --install my-app ./my-app -n apps \
-f values.yaml \
-f secrets.enc.yaml
Production:
- ключи KMS/age только через OIDC агента CI, не в переменной репозитория;
- не кэшировать расшифрованный файл в артефактах;
- проверить совместимость версии плагина с Helm 3.
HashiCorp Vault и операторы
Подходы без хранения значения в Git вообще:
| Паттерн | Суть |
|---|---|
| Vault Agent Injector | Токен/Sidecar подставляет секрет в Pod |
| Vault CSI Provider | Том с секретами, синхронизация |
| External Secrets Operator + Vault | CR ExternalSecret → обычный Secret в namespace |
Helm при этом ставит приложение и, при необходимости, ServiceAccount / политику доступа; содержимое секрета живёт в Vault.
Комментарий: см. материалы по Vault в разделе «Хранилище секретов» этого сайта — та же модель доверия и least privilege.
Практика: задеплоить секрет безопасно (выберите один контур)
Вариант A — Sealed Secret
- Установить Sealed Secrets controller в кластер (отдельный Helm chart / манифесты платформы).
- Получить
kubesealи создатьSealedSecretизkubectl create secret ... --dry-run=client. - Положить YAML в
templates/или включить в chart как шаблон с{{ .Release.Namespace }}при необходимости. helm upgrade --install— убедиться, что обычныйSecretпоявился:kubectl get secret -n apps.
Вариант B — SOPS + helm-secrets
- Создать
secrets.yaml, зашифроватьsops -e -i secrets.yaml(или через.sops.yamlс KMS). - В CI: запуск
helm secrets upgradeс ключом расшифровки. - В Git только
secrets.enc.yaml.
Production checklist
| # | Практика |
|---|---|
| 1 | Секреты не в открытом values.yaml и не в логах CI |
| 2 | RBAC: кто может читать Secret и helm get values |
| 3 | Включено шифрование etcd у провайдера (где применимо) |
| 4 | Ротация секретов и отзыв при утечке |
| 5 | Единый стандарт команды: Sealed / SOPS / Vault, а не «кто как успел» |