87 June 16, 2024, 1:42 p.m.

Передача секретов с помощью Ansible в кластер kubernetes

Задача: составить плейбук для передчи серкретов в определенные namespace из текстов или файлов

Для реализации задачи потребуется определить структуру переменных:

Для текстовых значений

SECRETS:
  DOCUMENTSERVER:
    values:
      - {name: JWT_SECRET, value: dfskldsjfdsjf, namespace: ds-ns, state: present}
  EMAIL:
    values:
      - {name: EMAIL-DB-USER,               value: superuser,  namespace: email-ns, state: present}
      - {name: EMAIL-DB-PASSWORD,    value: dsfkdsjkf,    namespace: email-ns, state: present}

где:

  • DOCUMENTSERVER или EMAIL - удобные названия, чтобы не путаться если проектов много;
  • values - служебный параметр;
  • name - имя секрета, которое будет преобразовано в нижний регистр, а “_” будут заменены на “-“;
  • value - содержимое секрета;
  • namespace - пространство имён куда будет помещён секрте;
  • state - может принимать в себя true или false в зависимости от значения секрет будет либо, удалён, либо создан.

Для файлов, по аналогии с кодом выше

SECRETS_FILE:
  EMAIL:
    values:
      - {name: cert.pem, path: cert.pem,  namespace: email-ns, state: present}
      - {name: key.pem,  path: key.pem,   namespace: email-ns, state: present}

Плейбуки

Для текстовых секретов

    - name: Ensure Kubernetes namespace exists
      kubernetes.core.k8s:
        kubeconfig: "~/.kube/config"
        state: present
        definition:
          apiVersion: v1
          kind: Namespace
          metadata:
            name: "{{ item.1.namespace }}"
      loop: "{{ lookup('subelements', SECRETS, 'values', wantlist=True) }}"
      when: item.1.namespace is defined and item.1.namespace | length > 0

    - name: Create Kubernetes secrets
      kubernetes.core.k8s:
        kubeconfig: "~/.kube/config"
        state: "{{ item.1.state }}"
        namespace: "{{ item.1.namespace }}"
        definition:
          apiVersion: v1
          kind: Secret
          metadata:
            name: "{{ item.1.name | lower | replace('_', '-') }}-secret"
            namespace: "{{ item.1.namespace }}"
          type: Opaque
          data:
            prod: "{{ item.1.value | b64encode }}"
      loop: "{{ lookup('subelements', SECRETS, 'values', wantlist=True) }}"
      when: item.1.value is defined and item.1.value | length > 0

Для файловых секретов

Нужно обратить внимание на путь, где должны находиться секреты.

    - name: Ensure Kubernetes namespace exists
      kubernetes.core.k8s:
        kubeconfig: "~/.kube/config"
        state: present
        definition:
          apiVersion: v1
          kind: Namespace
          metadata:
            name: "{{ item.1.namespace }}"
      loop: "{{ lookup('subelements', SECRETS_FILE, 'values', wantlist=True) }}"
      when: item.1.path is defined and item.1.path | length > 0

    - name: Create Kubernetes secrets from files
      kubernetes.core.k8s:
        kubeconfig: "~/.kube/config"
        state: "{{ item.1.state }}"
        namespace: "{{ item.1.namespace }}"
        definition:
          apiVersion: v1
          kind: Secret
          metadata:
            name: "{{ item.1.name | lower | replace('_', '-') }}-secret"
            namespace: "{{ item.1.namespace }}"
          type: Opaque
          data:
            prod: "{{ lookup('template', './files/secrets/' + item.1.path) | b64encode }}"
      loop: "{{ lookup('subelements', SECRETS_FILE, 'values', wantlist=True) }}"
      when: item.1.path is defined and item.1.path | length > 0

Подключение секрета в Deployment

# ========== ENVS =============
        env:
          - name: TZ
            value: "Europe/Moscow"
          - name: EMAIL_DB_DRIVER
            value: "pgsql"
          - name: EMAIL_DB_USER
            valueFrom:
              secretKeyRef:
                name: email-db-user-secret
                key: prod
# ====== VOLUME MOUNTS =======
        volumeMounts:
          - name: cert-secret-volume
            mountPath: /mnt/SSL/cert.pem
            subPath: cert.pem
            readOnly: true
          - name: key-secret-volume
            mountPath: /mnt/SSL/key.pem
            subPath: key.pem
            readOnly: true

# ======== VOLUMES ==========
      volumes:
        - name: cert-secret-volume
          secret:
            secretName: cert.pem-secret
            items:
            - key: prod
              path: cert.pem
        - name: key-secret-volume
          secret:
            secretName: key.pem-secret
            items:
            - key: prod
              path: key.pem