Управление секретами Kubernetes c помощью ESO и Secret Management
ESO (External Secrets Operator) — контроллер Kubernetes, который извлекает секреты из внешних сервисов управления секретами, таких как Secret Management, HashiCorp Vault и другие, и создает секреты в Kubernetes.
Для управления секретами ESO легко интегрируется с Secret Management, который в свою очередь взаимодействует с Key Management. Это обеспечивает безопасное шифрование секретов.
Если секрет изменится во внешнем хранилище, ESO автоматически обновит соответствующие секреты в кластере Kubernetes.
Принцип работы ESO с Secret Management
Администратор в ESO создает ресурс ExternalSecret, в котором указывает:
идентификатор и параметры извлекаемого секрета;
объекты SecretStore или ClusterSecretStore, к которым обращается для подключения к Secret Management.
Если контроллер ESO обнаруживает новый или измененный ExternalSecret, то обращается к Secret Management и запрашивает секрет.
Полученный секрет при необходимости преобразуется в формат, используемый для создания Kubernetes Secret (k8s Secret).
После этого контроллер обновляет или создает соответствующий объект Secret в указанном пространстве имен Kubernetes.
Перед началом работы
Создайте сервисный аккаунт и назначьте ему роль scsm.user.
Сгенерируйте ключ доступа для сервисного аккаунта.
Создайте секрет в Secret Management.
Установите ESO одним из способов:
с помощью диспетчера пакетов Helm (см. рекомендации в разделе Option1: Intall from chart repository).
с помощью сервиса Managed Kubernetes, установив плагин.
Создайте ExternalSecret
Ниже приведен пример создания объекта ExternalSecret, который указывает на секрет my-first-secret (со значением lordofwar1234wifif) из Secret Management.
Для синхронизации секрета ESO создаст k8s Secret c именем my-awesome-secret и поместит в него my-fist-seceret. Если в Secret Management обновится значение секрета my-first-secret, то в my-awesome-secret в k8s Secret также появится новое значение.
Шаг 1. Создайте k8s Secret для аутентификации в SecretStore
Создайте файл csm-secret.yaml:
nano csm-secret.yamlСкопируйте и сохраните в подготовленном файле спецификацию:
apiVersion: v1kind: Secretmetadata:name: csm-secretlabels:type: csmtype: OpaquestringData:key_id: '000000000000000000001'key_secret: '000000000000000000002'Где:
key_id — логин ключа доступа созданного сервисного аккаунта;
key_secret — пароль ключа доступа созданного сервисного аккаунта.
В кластере Kubernetes создайте k8s Secret:
kubectl apply -f "csm-secret.yaml"
Шаг 2. Создайте SecretStore, указывающий на csm-secret k8s Secret
Создайте файл csm-secret-store.yaml:
nano csm-secret-store.yamlСкопируйте и сохраните в подготовленном файле спецификацию:
apiVersion: external-secrets.io/v1beta1kind: SecretStoremetadata:name: csmspec:provider:cloudrusm:auth:secretRef:accessKeyIDSecretRef:name: csm-secretkey: key_idaccessKeySecretSecretRef:name: csm-secretkey: key_secretprojectID: 50000000-4000-3000-2000-100000000001Где:
accessKeyIDSecretRef — ссылка на k8s Secret;
projectID — идентификатор проекта.
Создайте SecretStore в кластере Kubernetes:
kubectl apply -f "csm-secret-store.yaml"
Шаг 3. Создайте ExternalSecrete для извлечения секрета из Secret Management
Создайте файл csm-external-secret.yaml:
nano csm-external-secret.yamlВыберите вариант формата секрета, в котором был создан my-first-secret в Secret Management:
Секрет вставляется в текстовом формате в виде строки.
Скопируйте и сохраните в подготовленном файле спецификацию:
apiVersion: external-secrets.io/v1beta1kind: ExternalSecretmetadata:name: csm-ext-secretspec:refreshInterval: 10ssecretStoreRef:name: csmkind: SecretStoretarget:name: my-awesome-secretcreationPolicy: Ownerdata:- secretKey: target_keyremoteRef:key: my-first-secretГде:
spec:
refreshInterval — временной интервал обновления секрета.
target:
name — имя создаваемого k8s Secret.
remoteRef — информация, как получить значение из внешнего секрета:
key — имя или идентификатор секрета в Secret Management.
Создайте ExternalSecret в кластере Kubernetes
kubectl apply -f "csm-external-secret.yaml"Проверьте, что k8s Secret c именем my-awesome-secret присутствует в кластере и содержит значение секрета my-first-secret из Secret Management:
kubectl get secrets my-awesome-secret -o yaml
В ответе получите yaml-спецификацию.
apiVersion: v1data:target_key: bG0yZG0TESTHdpZm0mkind: Secretmetadata:annotations:kubectl.kubernetes.io/last-applied-configuration: |{"apiVersion":"external-secrets.io/v1beta1","kind":"ExternalSecret","metadata":{"annotations":{},"name":"csm-ext-secret","namespace":"default"},"spec":{"data":[{"remoteRef":{"key":"my-first-secret"},"secretKey":"target_key"}],"refreshInterval":"120s","secretStoreRef":{"kind":"SecretStore","name":"csm"},"target":{"creationPolicy":"Owner","name":"my-awesome-secret"}}}reconcile.external-secrets.io/data-hash: 00ec00a000d0cf0a000d0000000e0000creationTimestamp: "2025-04-03T16:02:42Z"labels:reconcile.external-secrets.io/created-by: b0d0e0f00c0d00a00ba00d00cd00fcb0reconcile.external-secrets.io/managed: "true"name: my-awesome-secretnamespace: defaultownerReferences:- apiVersion: external-secrets.io/v1beta1blockOwnerDeletion: truecontroller: truekind: ExternalSecretname: csm-ext-secretuid: fa0d0000-0a0c-0ec0-0000-00c0c1c0d0faresourceVersion: "1548"uid: c00efe0-0d00-0dfe-a0c0-f00e0a000000type: Opaque
В разделе data для ключа target_key будет указано bG0yZG0TESTHdpZm0m — значение секрета lordofwar1234wifif в формате base64.
Значения не декодируются автоматически. Для расшифровки используйте утилиту base64.
Поиск секретов по имени или меткам (тегам)
Секреты можно отфильтровать по названию или меткам (тегам):
Создайте файл csm-external-secret.yaml:
nano csm-external-secret-search.yamlСкопируйте и сохраните в подготовленном файле следующую спецификацию:
apiVersion: external-secrets.io/v1beta1kind: ExternalSecretmetadata:name: csm-ext-secretspec:refreshInterval: 10ssecretStoreRef:name: csmkind: SecretStoretarget:name: my-awesome-secretcreationPolicy: OwnerdataFrom:- find: # You can use the name and tags separately or together to search for secrets.tags:env: productionname:regexp: "my.*secret"Для проверки выполните команду:
kubectl get secrets my-awesome-secret -o yaml
В ответе получите yaml-спецификацию, найденную по заданным параметрам:
apiVersion: v1data:my-first-secret: bG0yZG0TESTHdpZm0mmy-second-secret: ewogICJsb2dpbiI6ICJteV9sb2dpbiIsCiAgInBhc3N3b3JkIjogImFzZm5zZGZpbjEyTCIKfQ==kind: Secretmetadata:annotations:kubectl.kubernetes.io/last-applied-configuration: |{"apiVersion":"external-secrets.io/v1beta1","kind":"ExternalSecret","metadata":{"annotations":{},"name":"csm-ext-secret","namespace":"default"},"spec":{"dataFrom":[{"find":{"name":{"regexp":"my.*secret"}}}],"refreshInterval":"120s","secretStoreRef":{"kind":"SecretStore","name":"csm"},"target":{"creationPolicy":"Owner","name":"my-awesome-secret"}}}reconcile.external-secrets.io/data-hash: 49db1066bcc65a9d20c825b8295ad49bcreationTimestamp: "2025-04-03T16:02:42Z"labels:reconcile.external-secrets.io/created-by: b0d0e0f00c0d00a00ba00d00cd00fcb0reconcile.external-secrets.io/managed: "true"name: my-awesome-secretnamespace: defaultownerReferences:- apiVersion: external-secrets.io/v1beta1blockOwnerDeletion: truecontroller: truekind: ExternalSecretname: csm-ext-secretuid: fa0d0000-0a0c-0ec0-0000-00c0c1c0d0faresourceVersion: "10631"uid: ac00efe0-0d00-0dfe-a0c0-f00e0a000000type: Opaque
Раздел data содержит значения из нескольких секретов, найденных по регулярному выражению my.*secret. Значение секретов my-first-secret и my-second-secret выводятся в формате base64 и не декодируются автоматически. Поэтому для расшифровки используйте утилиту base64.
- Принцип работы ESO с Secret Management
- Перед началом работы
- Создайте ExternalSecret
- Поиск секретов по имени или меткам (тегам)