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

Пароль к базе данных лежит в объекте 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, а также сравним подходы к хранению секретов по ключевым параметрам.

Сергей Новиков, менеджер продукта Managed Kubernetes
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 без шифрования и внешнего контроля доступа.
External Secrets Operator — контроллер Kubernetes, который устанавливается как Deployment и добавляет в кластер три кастомных ресурса (CRD):
Рабочий цикл: контроллер 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 интегрируется как нативный провайдер аддона.
Изолированное централизованное хранилище секретов. 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 убирает этот слой: оператор устанавливается и преднастраивается через панель управления.
Откройте панель управления VK Cloud, перейдите в раздел «Managed Kubernetes», выберите нужный кластер. В меню кластера откройте вкладку «Аддоны», найдите External Secrets Operator и подтвердите установку. После успешного развёртывания в кластере появится namespace external-secrets с контроллером и CRD.
Проверить результат:
kubectl get pods -n external-secrets kubectl get crd | grep external-secrets
Перейдите в раздел «Key Management» панели VK Cloud. Создайте новый секрет с именем в иерархической нотации через /: например, prod/db-password. Задайте значение. Иерархическое именование помогает строить политики IAM по префиксу: сервисный аккаунт prod-кластера получает доступ к prod/*, dev-кластера — к dev/*.
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.
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
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. Частота синхронизации зависит от типа секрета:
Короткий интервал увеличивает количество обращений к KMS API — при большом числе ExternalSecret это может стать значимой нагрузкой. Длинный интервал увеличивает окно, в котором скомпрометированный секрет продолжает работать после отзыва в KMS.
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: аддон подключается через панель управления, хранилище изолировано от кластеров, трафик идёт по внутренним каналам платформы.
Контроллер Kubernetes, который читает описание нужного секрета из CRD ExternalSecret, получает значение из внешнего хранилища (KMS, Vault, AWS Secrets Manager и др.) и создаёт нативный объект Secret в кластере. Находится в CNCF Sandbox с июля 2022 года, актуальная версия — v2.6.0.
Нативный Secret хранит данные в base64 в etcd, и без encryption at rest значения доступны в открытом виде на дисках control plane. ESO хранит секреты в изолированном внешнем хранилище: кластер получает только финальное значение через защищённый канал, ротация автоматическая через refreshInterval, аудит обращений ведётся в KMS.
Панель управления VK Cloud → Managed Kubernetes → выбрать кластер → вкладка «Аддоны» → External Secrets Operator → подтвердить установку. После развёртывания создать секрет в KMS VK Cloud, настроить SecretStore с указанием сервисного аккаунта IAM, применить манифест ExternalSecret.
ESO обновляет нативный Secret автоматически по refreshInterval. Поведение приложения зависит от способа монтирования:
Наши специалисты свяжутся с вами в ближайшее время и ответят на все вопросы.

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




