Как управлять секретами в Kubernetes (Vault, Sealed Secrets)?

Кратко о механике Kubernetes Secret

Secret — namespaced объект, содержащий пары ключ/значение (base64). По умолчанию kubelet монтирует Secret как файлы в volume или подставляет в переменные окружения при старте контейнера. Переменные окружения не меняются без рестарта; монтированные файлы обновляются kubelet асинхронно (но subPath ломает обновления). По умолчанию etcd хранит Secret в открытом виде — это риск, поэтому необходима защита на уровне кластера.

Sealed Secrets — Git-friendly workflow

  • Идея: зашифровать Secret публичным ключом контроллера (в кластере есть приватный ключ), получить ресурс SealedSecret, безопасный для хранения в Git. Контроллер расшифровывает и создаёт обычный Secret в кластере.

  • Паттерн: разработчик создаёт/шифрует секрет → пушит SealedSecret в репозиторий → CI/CD/ArgoCD/Flux применяет манифест → контроллер в кластере разворачивает живой Secret.

  • Плюсы: безопасно хранить в Git, простой workflow для GitOps. Минусы: приватный ключ контроллера — точка доверия, ротация ключей требует плана.

Пример (упрощённо):

apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
metadata: { name: db-creds, namespace: prod }
spec:
encryptedData:
password: <ENCRYPTED_BASE64>

Vault — централизованный секрет-менеджер и динамические секреты

  • Vault даёт централизованное хранилище, KMS-подобные возможности, политики доступа, аудит, а также динамическую генерацию учётных данных (DB, cloud creds).

  • Аутентификация Kubernetes: Vault привязывает Kubernetes ServiceAccount → выдаёт временные токены/секреты по политике.

  • Интеграция с Kubernetes: два популярных паттерна

    • Vault Agent Injector (sidecar + init): инжектирует секреты в Pod (файлы или env) и обновляет их по ротации; может сигнализировать приложению. Аннотации на Pod задают путь/политику.

    • CSI Secrets Store Provider for Vault: CSI драйвер монтирует секреты как файлы через SecretProviderClass. Поддерживает refresh и унифицированный интерфейс для различных провайдеров.

  • Преимущества Vault: централизованная ротация, аудит, секреты не хранятся в etcd (если используется CSI/Agent вместо статического Secret), динамические креды снижают blast radius.

Пример CSI-монтажа (сокращённо):

volumes:
\- name: secret-vol
csi:
driver: secrets-store.csi.k8s.io
readOnly: true
volumeAttributes:
secretProviderClass: "vault-kv"

Другие паттерны

  • SOPS + Git: шифруете YAML секретов симметрично/асимметрично (KMS) и храните в Git; при deploy расшифровываете CI и применяете.

  • External Secrets / ExternalSecrets Operator: синхронизирует секреты из Vault/Cloud Secret Manager в Kubernetes Secret автоматически (часто в зашифрованном виде или с коротким TTL).

Практические best practices

  • Шифрование etcd at rest: включите encryptionConfiguration, ключи в KMS.

  • Минимизация прав доступа: RBAC, выдача прав get/list на Secret только тем SA, которые реально нужны. Ограничьте ClusterRoleBinding.

  • Не хранить секреты в Git в открытом виде — используйте SealedSecrets/SOPS/Encrypted Git.

  • Avoid env for sensitive long-lived secrets: предпочтительнее монтировать как файл; env нельзя обновить без рестарта.

  • Отключать автоматическое монтирование SA токена (automountServiceAccountToken: false) где оно не нужно.

  • Короткоживущие токены: отдавайте приложениям временные креды (Vault dynamic creds, projected service account tokens).

  • Ротация и автоматизация: автоматическая ротация паролей/ключей и процесс обновления приложений; следить за successful refresh.

  • Аудит и логирование: аудит обращений к секретам (Vault audit, kube-apiserver audit).

  • Backup и recovery: бэкапить зашифрованные секреты и ключи (и etcd snapshot зашифрованный).

  • Обновление без рестарта: монтируйте секрет как volume (не subPath), либо используйте Vault Agent/CSI + sidecar/notify, чтобы приложение могло перечитать конфиг при смене значения.

Выбор паттерна по задачам

  • Для GitOps + простоты → SealedSecrets или SOPS.

  • Для централизованной политики, аудита и динамических кредов → Vault (CSI или Agent).

  • Для простой синхронизации из cloud secrets → External Secrets.

Операционные замечания

  • План ротации ключей контроллера SealedSecrets и ключей KMS.

  • Тестировать восстановление и ротацию в staging.

  • Не давать developer-robot-аккаунтам широкие права на чтение всех секретов — применяйте least-privilege.