nav-img
Evolution

Управление секретами 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.

Перед началом работы

  1. Создайте сервисный аккаунт и назначьте ему роль scsm.user.

  2. Сгенерируйте ключ доступа для сервисного аккаунта.

  3. Создайте секрет в Secret Management.

  4. Установите ESO одним из способов:

Создайте 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

  1. Создайте файл csm-secret.yaml:

    nano csm-secret.yaml
  2. Скопируйте и сохраните в подготовленном файле спецификацию:

    apiVersion: v1
    kind: Secret
    metadata:
    name: csm-secret
    labels:
    type: csm
    type: Opaque
    stringData:
    key_id: '000000000000000000001'
    key_secret: '000000000000000000002'

    Где:

    • key_id — логин ключа доступа созданного сервисного аккаунта;

    • key_secret — пароль ключа доступа созданного сервисного аккаунта.

  3. В кластере Kubernetes создайте k8s Secret:

    kubectl apply -f "csm-secret.yaml"

Шаг 2. Создайте SecretStore, указывающий на csm-secret k8s Secret

  1. Создайте файл csm-secret-store.yaml:

    nano csm-secret-store.yaml
  2. Скопируйте и сохраните в подготовленном файле спецификацию:

    apiVersion: external-secrets.io/v1beta1
    kind: SecretStore
    metadata:
    name: csm
    spec:
    provider:
    cloudrusm:
    auth:
    secretRef:
    accessKeyIDSecretRef:
    name: csm-secret
    key: key_id
    accessKeySecretSecretRef:
    name: csm-secret
    key: key_secret
    projectID: 50000000-4000-3000-2000-100000000001

    Где:

  3. Создайте SecretStore в кластере Kubernetes:

    kubectl apply -f "csm-secret-store.yaml"

Шаг 3. Создайте ExternalSecrete для извлечения секрета из Secret Management

  1. Создайте файл csm-external-secret.yaml:

    nano csm-external-secret.yaml
  2. Выберите вариант формата секрета, в котором был создан my-first-secret в Secret Management:


    Секрет вставляется в текстовом формате в виде строки.

    Скопируйте и сохраните в подготовленном файле спецификацию:

    apiVersion: external-secrets.io/v1beta1
    kind: ExternalSecret
    metadata:
    name: csm-ext-secret
    spec:
    refreshInterval: 10s
    secretStoreRef:
    name: csm
    kind: SecretStore
    target:
    name: my-awesome-secret
    creationPolicy: Owner
    data:
    - secretKey: target_key
    remoteRef:
    key: my-first-secret

    Где:

    • spec:

      • refreshInterval — временной интервал обновления секрета.

    • target:

      • name — имя создаваемого k8s Secret.

    • remoteRef — информация, как получить значение из внешнего секрета:

      • key — имя или идентификатор секрета в Secret Management.

  3. Создайте ExternalSecret в кластере Kubernetes

    kubectl apply -f "csm-external-secret.yaml"
  4. Проверьте, что k8s Secret c именем my-awesome-secret присутствует в кластере и содержит значение секрета my-first-secret из Secret Management:

    kubectl get secrets my-awesome-secret -o yaml

В ответе получите yaml-спецификацию.

apiVersion: v1
data:
target_key: bG0yZG0TESTHdpZm0m
kind: Secret
metadata:
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: 00ec00a000d0cf0a000d0000000e0000
creationTimestamp: "2025-04-03T16:02:42Z"
labels:
reconcile.external-secrets.io/created-by: b0d0e0f00c0d00a00ba00d00cd00fcb0
reconcile.external-secrets.io/managed: "true"
name: my-awesome-secret
namespace: default
ownerReferences:
- apiVersion: external-secrets.io/v1beta1
blockOwnerDeletion: true
controller: true
kind: ExternalSecret
name: csm-ext-secret
uid: fa0d0000-0a0c-0ec0-0000-00c0c1c0d0fa
resourceVersion: "1548"
uid: c00efe0-0d00-0dfe-a0c0-f00e0a000000
type: Opaque

В разделе data для ключа target_key будет указано bG0yZG0TESTHdpZm0m — значение секрета lordofwar1234wifif в формате base64.

Подсказка

Значения не декодируются автоматически. Для расшифровки используйте утилиту base64.

Поиск секретов по имени или меткам (тегам)

Секреты можно отфильтровать по названию или меткам (тегам):

  1. Создайте файл csm-external-secret.yaml:

    nano csm-external-secret-search.yaml
  2. Скопируйте и сохраните в подготовленном файле следующую спецификацию:

    apiVersion: external-secrets.io/v1beta1
    kind: ExternalSecret
    metadata:
    name: csm-ext-secret
    spec:
    refreshInterval: 10s
    secretStoreRef:
    name: csm
    kind: SecretStore
    target:
    name: my-awesome-secret
    creationPolicy: Owner
    dataFrom:
    - find: # You can use the name and tags separately or together to search for secrets.
    tags:
    env: production
    name:
    regexp: "my.*secret"
  3. Для проверки выполните команду:

    kubectl get secrets my-awesome-secret -o yaml

В ответе получите yaml-спецификацию, найденную по заданным параметрам:

apiVersion: v1
data:
my-first-secret: bG0yZG0TESTHdpZm0m
my-second-secret: ewogICJsb2dpbiI6ICJteV9sb2dpbiIsCiAgInBhc3N3b3JkIjogImFzZm5zZGZpbjEyTCIKfQ==
kind: Secret
metadata:
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: 49db1066bcc65a9d20c825b8295ad49b
creationTimestamp: "2025-04-03T16:02:42Z"
labels:
reconcile.external-secrets.io/created-by: b0d0e0f00c0d00a00ba00d00cd00fcb0
reconcile.external-secrets.io/managed: "true"
name: my-awesome-secret
namespace: default
ownerReferences:
- apiVersion: external-secrets.io/v1beta1
blockOwnerDeletion: true
controller: true
kind: ExternalSecret
name: csm-ext-secret
uid: fa0d0000-0a0c-0ec0-0000-00c0c1c0d0fa
resourceVersion: "10631"
uid: ac00efe0-0d00-0dfe-a0c0-f00e0a000000
type: Opaque

Раздел data содержит значения из нескольких секретов, найденных по регулярному выражению my.*secret. Значение секретов my-first-secret и my-second-secret выводятся в формате base64 и не декодируются автоматически. Поэтому для расшифровки используйте утилиту base64.