VK Cloud

External Secrets Operator в Managed Kubernetes: безопасное управление секретами без ручной работы

24 июля 2026 г.
268267_007n7ek.jpg
Евгений Левашов
Автор статьи
_blog_head_158.png

Пароль к базе данных лежит в объекте Secret, который хранится в etcd. Прочитать его значение можно одной командой: kubectl get secret db-creds -o jsonpath='{.data.password}' | base64 -d. Здесь нет шифрования — только base64-кодирование. Если etcd не настроен на encryption at rest (по умолчанию он не настроен), секреты хранятся на дисках control plane в открытом виде.

Команды, которые работают с несколькими кластерами, обычно выбирают один из двух путей. Первый — держать секреты в Git рядом с манифестами: быстро, но рано или поздно значение утечёт в историю коммитов. Второй — вручную выполнять kubectl create secret в каждом кластере при каждом обновлении. Оба подхода ломаются при масштабировании.

External Secrets Operator решает задачу иначе: секреты остаются в централизованном хранилище (KMS), а оператор в кластере сам вытягивает их и по расписанию создаёт нативные объекты Secret. В VK Cloud Managed Kubernetes ESO доступен как аддон, который подключается через панель управления — без написания Helm-чартов и RBAC с нуля.

В статье разберём, почему нативные Kubernetes Secrets небезопасны, как устроен ESO изнутри, как подключить аддон в VK Cloud и настроить первый ExternalSecret, а также сравним подходы к хранению секретов по ключевым параметрам.

Новиков2.jpg

Статья подготовлена вместе с экспертом

Сергей Новиков, менеджер продукта Managed Kubernetes

Почему нативные Kubernetes Secrets небезопасны

Kubernetes Secrets хранят данные в формате base64. Кодирование обратимо без ключей: команда kubectl get secret my-secret -o jsonpath='{.data.password}' | base64 -d возвращает значение в открытом виде за долю секунды. Любой, у кого есть право на k_ubectl get secret_ в нужном namespace, читает все значения.

Корень проблемы глубже. Секреты хранятся в etcd, и без явной настройки encryption at rest лежат там незашифрованными. Encryption at rest не включён по умолчанию: администратор кластера должен самостоятельно создать EncryptionConfiguration и подключить KMS-провайдер. В Kubernetes 1.28 устаревший KMS v1 стал deprecated, с версии 1.29 он отключён по умолчанию — актуальный путь это KMS v2. Без этой конфигурации резервная копия etcd содержит все секреты в читаемом виде.

Отсюда исходная точка для любых Kubernetes secrets best practices: не доверять хранению секретов только в etcd без шифрования и внешнего контроля доступа.

Три типичных антипаттерна

  • Секреты в Git. Разработчик кладёт манифест с kind: Secret в репозиторий — чаще всего «временно» или «только на dev». Git хранит историю навсегда: даже удалив файл в следующем коммите, значение остаётся в git log. По данным GitGuardian State of Secrets Sprawl 2026, в 2025 году в публичных коммитах GitHub обнаружено 28,6 млн секретов — рост на 34% год к году. Учётные данные к AI-сервисам выросли на 81% и достигли 1 275 105 штук. По предыдущему отчёту GitGuardian, из секретов, утёкших в 2022 году, 70% оставались активными по состоянию на январь 2025 года — их никто не отозвал.
  • Ручное обновление секретов. При ротации пароля инженер обходит каждый кластер и namespace вручную. При десяти кластерах это часы работы, при тридцати — гарантированные пропуски. История изменений нигде не ведётся, кроме записок в чате.
  • Размытая ответственность. Секреты разбросаны по кластерам, CI/CD-переменным и локальным файлам разработчиков. Нет единой точки аудита: кто получил доступ, когда, к какому значению. При инциденте восстановить картину практически невозможно.

Как работает External Secrets Operator

External Secrets Operator — контроллер Kubernetes, который устанавливается как Deployment и добавляет в кластер три кастомных ресурса (CRD):

  • SecretStore — namespaced-ресурс, описывает подключение к конкретному хранилищу секретов (адрес, аутентификация, провайдер).
  • ClusterSecretStore — то же самое, но доступен из всех namespace.
  • ExternalSecret — описывает, какой секрет нужен: из какого хранилища, под каким именем создать нативный Secret, как часто обновлять.

Рабочий цикл: контроллер ESO читает объект ExternalSecret, обращается к внешнему KMS по защищённому каналу, получает актуальное значение, создаёт или обновляет нативный Kubernetes Secret. Приложение использует его через переменную окружения или volume mount.

Пример SecretStore с подключением к HashiCorp Vault (шаблон; для KMS VK Cloud параметры провайдера — см. шаг 3):

apiVersion: external-secrets.io/v1 kind: SecretStore metadata: name: vault-backend namespace: production spec: provider: vault: server: "https://vault.example.com" path: "secret" version: "v2" auth: kubernetes: mountPath: "kubernetes" role: "my-role"

Пример ExternalSecret:

apiVersion: external-secrets.io/v1 kind: ExternalSecret metadata: name: db-password namespace: production spec: refreshInterval: 1h secretStoreRef: name: vault-backend kind: SecretStore target: name: db-secret data: - secretKey: password remoteRef: key: prod/db-password

ESO находится в CNCF Sandbox с июля 2022 года. Актуальная версия Helm-чарта — v2.6.0 (июнь 2026), стабильный API — external-secrets.io/v1, предыдущий v1beta1 поддерживается как legacy.

Автоматическая ротация

Параметр refreshInterval задаёт, как часто контроллер сверяет значение в кластере со значением в KMS. При расхождении, или по истечении интервала, ESO обновляет нативный Secret без ручного вмешательства. Ротация пароля в KMS автоматически распространяется на все кластеры, где есть соответствующий ExternalSecret.

Разделение ответственности

ESO реализует принцип least privilege на уровне процесса разработки. Разработчик описывает потребность: нужен секрет db-password из хранилища prod-store. Он не знает значения и не может его прочитать без прав на KMS. Значение знают KMS и команда SecOps, которая управляет хранилищем. Кластерный инженер настраивает SecretStore и политики IAM. Граница ответственности видна по манифестам в Git: там нет значений, только ссылки.

Поддерживаемые хранилища

ESO поддерживает широкий список провайдеров: HashiCorp Vault, AWS Secrets Manager, Azure Key Vault, GCP Secret Manager, IBM Cloud Secrets Manager, Akeyless, CyberArk, Pulumi ESC и другие. При миграции между хранилищами меняется только блок provider в SecretStore — ExternalSecret и приложение остаются без изменений. KMS VK Cloud интегрируется как нативный провайдер аддона.

Аддон External Secrets Operator в VK Cloud: что даёт платформенная интеграция

Изолированное централизованное хранилище секретов. KMS VK Cloud физически отделён от кластеров Managed Kubernetes. Доступ управляется через IAM с детальными политиками: каждый сервисный аккаунт получает права только на нужные секреты и только на чтение. Каждое обращение фиксируется в аудит-логе — кто, когда, к какому секрету обращался. KMS в роли провайдера ESO превращает пару «оператор + хранилище» в единую управляемую систему.

Передача по защищённым внутренним каналам платформы. ESO в кластере общается с KMS VK Cloud через внутреннюю инфраструктуру провайдера, не выходя в публичный интернет. Канал защищён TLS, аутентификация — через сервисный аккаунт IAM. Перехват трафика между кластером и хранилищем не компрометирует секрет в пути.

Отсутствие ручной работы при развёртывании. При классической схеме разработчик пишет ExternalSecret-манифест и применяет его через kubectl apply. Значение приходит автоматически: не нужны ни kubectl create secret --from-literal, ни ручное копирование из менеджера паролей команды, ни Confluence-страницы с «актуальными» паролями.

Подключение через панель управления. Self-managed установка ESO включает helm install, настройку RBAC, создание ServiceAccount, ручную конфигурацию SecretStore под конкретный провайдер, проверку сертификатов. Аддон в Managed Kubernetes VK Cloud убирает этот слой: оператор устанавливается и преднастраивается через панель управления.

Пошаговая настройка: от подключения аддона до первого ExternalSecret

Шаг 1. Подключение аддона

Откройте панель управления VK Cloud, перейдите в раздел «Managed Kubernetes», выберите нужный кластер. В меню кластера откройте вкладку «Аддоны», найдите External Secrets Operator и подтвердите установку. После успешного развёртывания в кластере появится namespace external-secrets с контроллером и CRD.

Проверить результат:

kubectl get pods -n external-secrets kubectl get crd | grep external-secrets

Шаг 2. Создание секрета в KMS VK Cloud

Перейдите в раздел «Key Management» панели VK Cloud. Создайте новый секрет с именем в иерархической нотации через /: например, prod/db-password. Задайте значение. Иерархическое именование помогает строить политики IAM по префиксу: сервисный аккаунт prod-кластера получает доступ к prod/*, dev-кластера — к dev/*.

Шаг 3. Настройка SecretStore

SecretStore описывает подключение к KMS VK Cloud. При установке аддона часть параметров может быть преднастроена автоматически. Шаблонный манифест:

apiVersion: external-secrets.io/v1 kind: SecretStore metadata: name: vkcloud-kms namespace: production spec: provider: vkcloud: endpoint: "https://..." auth: serviceAccountRef: name: eso-sa namespace: external-secrets

Создайте ServiceAccount с правами на чтение нужных секретов в IAM VK Cloud и привяжите его к SecretStore.

Шаг 4. Создание ExternalSecret

apiVersion: external-secrets.io/v1 kind: ExternalSecret metadata: name: db-password-sync namespace: production spec: refreshInterval: 1h secretStoreRef: name: vkcloud-kms kind: SecretStore target: name: db-secret creationPolicy: Owner data: - secretKey: password remoteRef: key: prod/db-password

Применить манифест:

kubectl apply -f externalsecret-db.yaml

Шаг 5. Проверка синхронизации

kubectl describe externalsecret db-password-sync -n production # Ожидаем: Status: SecretSynced kubectl get secret db-secret -n production kubectl exec -n production deploy/my-app -- printenv | grep DB_PASSWORD

Если статус SecretSyncedError, смотрите события: kubectl get events -n production --field-selector reason=SecretSyncError. Типичные причины — неверный путь к секрету в KMS, недостаточные права ServiceAccount или недоступный endpoint.

Практические рекомендации

Политики доступа: кластер должен видеть только свои секреты. Создавайте отдельный сервисный аккаунт IAM для каждого кластера и окружения. Prod-кластер получает политику на чтение prod/*, staging — staging/*, dev — dev/*. Если все кластеры используют один аккаунт с доступом ко всем секретам, компрометация одного кластера открывает секреты всех окружений — прямое нарушение принципа least privilege. В манифесте SecretStore указывайте минимально необходимый путь: не *, а конкретный префикс вида prod/service-name/.

Ротация секретов: настройка refreshInterval. Частота синхронизации зависит от типа секрета:

  • TLS-сертификаты с коротким сроком действия — refreshInterval: 1h или 24h в зависимости от срока действия сертификата.
  • Пароли к базам данных — 1h, разумный баланс между свежестью и нагрузкой на KMS API.
  • Краткосрочные API-токены с TTL 15–30 минут — 5m или 15m.

Короткий интервал увеличивает количество обращений к KMS API — при большом числе ExternalSecret это может стать значимой нагрузкой. Длинный интервал увеличивает окно, в котором скомпрометированный секрет продолжает работать после отзыва в KMS.

Сравнение подходов к секретам в Kubernetes

Sealed Secrets упомянуты как компромиссный вариант для команд, которым нужно хранить зашифрованные манифесты в Git без внешнего хранилища.

Подход Где хранится секрет Ротация Риск утечки Сложность операций
Нативный Kubernetes Secret (base64) etcd кластера Вручную Высокий — нет шифрования по умолчанию Низкая
Sealed Secrets (Bitnami) Git (зашифровано) Пересоздание манифеста Средний Средняя
HashiCorp Vault (self-managed) Vault-кластер Автоматическая через ESO Низкий Высокая — управление Vault
ESO + KMS VK Cloud (аддон) KMS VK Cloud (изолировано) Автоматическая через refreshInterval Минимальный Низкая — аддон

Sealed Secrets решают задачу GitOps: манифест зашифрован и безопасно хранится в репозитории. Но ротация требует пересоздания манифеста и нового коммита, централизованного аудита обращений нет, а при компрометации ключа контроллера расшифровываются все манифесты.

External Secrets Operator переводит управление секретами из ручного и реактивного режима в автоматический и централизованный. Разработчик описывает потребность в манифесте, SecOps управляет значениями в KMS, ESO синхронизирует их в кластере по расписанию. При использовании аддона в VK Cloud Managed Kubernetes этот слой доступен без самостоятельной установки оператора, настройки RBAC и интеграции с KMS: аддон подключается через панель управления, хранилище изолировано от кластеров, трафик идёт по внутренним каналам платформы.

Частые вопросы про External Secrets Operator

Что такое External Secrets Operator?

Контроллер Kubernetes, который читает описание нужного секрета из CRD ExternalSecret, получает значение из внешнего хранилища (KMS, Vault, AWS Secrets Manager и др.) и создаёт нативный объект Secret в кластере. Находится в CNCF Sandbox с июля 2022 года, актуальная версия — v2.6.0.

Чем ESO лучше нативных Kubernetes Secrets?

Нативный Secret хранит данные в base64 в etcd, и без encryption at rest значения доступны в открытом виде на дисках control plane. ESO хранит секреты в изолированном внешнем хранилище: кластер получает только финальное значение через защищённый канал, ротация автоматическая через refreshInterval, аудит обращений ведётся в KMS.

Как подключить External Secrets Operator в VK Cloud?

Панель управления VK Cloud → Managed Kubernetes → выбрать кластер → вкладка «Аддоны» → External Secrets Operator → подтвердить установку. После развёртывания создать секрет в KMS VK Cloud, настроить SecretStore с указанием сервисного аккаунта IAM, применить манифест ExternalSecret.

Нужно ли перезапускать поды при обновлении секрета в KMS?

ESO обновляет нативный Secret автоматически по refreshInterval. Поведение приложения зависит от способа монтирования:

  • Переменные окружения (env/envFrom) — Pod читает значения при старте и не видит обновлений до перезапуска. Для автоматического rolling restart используют Stakater Reloader с аннотацией на Deployment.
  • Volume mount — kubelet обновляет файл в примонтированном томе автоматически примерно через 60 секунд после обновления Secret. Некоторые приложения умеют читать файл повторно без перезапуска.

Оставьте заявку, чтобы получить консультацию

Наши специалисты свяжутся с вами в ближайшее время и ответят на все вопросы.

section-subscribe_2x.png

            Узнавайте о выходе новых статей в блоге первыми!

            Будем держать в курсе новостей и облачных трендов

            section-subscribe_2x.png
              section-subscribe_2x.png
              Теги: VK Cloud, kubernetes
              Ссылка скопирована
              Поделиться

              Почитать по теме

              _blog_head_100.png
              24 июля

              S3-CSI в Managed Kubernetes: масштабирование приложений без потери общих файлов

              blog_head_39_69.png
              20 июля

              Kubernetes для разработчика: локально (Minikube, kind) и в облаке

              40+ готовых сервисов