Processing: секрет yc-s3 для подов задач workflows

Задача падала ещё до обращения к S3, на разборе конфигурации:
  pydantic ValidationError for S3AccountModel
  Value error, Expecting value: line 1 column 1 (char 0)
  ValueError: SERVICE_S3 is not valid
"Expecting value ... char 0" — это разбор пустоты: файла по пути не было.

Секрет secrets/minio/apps/processing из Vault при этом настроен верно, и
движок его видит (S3_SERVICE_ACCOUNT=/vault/secrets/processing-s3). Но в
поды задач движок его НЕ передаёт — для них у него отдельный механизм,
зашитый в код:

  services[S3Storage] = Service{
      CredentialsName: "yc-s3",
      CredentialsPath: "/etc/sarex/yc-s3",
      Envs: {"SERVICE_S3": `{"service_account":
             "/etc/sarex/yc-s3/yc-s3-service-account.json"}`},
  }
  (pkg/kube_services/services.go)

То есть он монтирует в Job обычный Secret с именем yc-s3 из namespace
задач (JOBS_NAMESPACE=processing). Ни имя секрета, ни путь, ни имя файла
не настраиваются.

vault-agent сюда не дотягивается по построению: поды задач движок создаёт
сам во время работы, аннотаций инжекции у них нет. Поэтому секрет заводит
ansible — tasks/app-secrets.yml, шаблон app-secrets.yaml.j2 и описание в
k8s_file_secrets. Формат содержимого повторяет
engine/yc-s3-service-account.json из compose-стека и совпадает с тем, что
vault-agent рендерит самому движку.

Манифест рендерится, применяется и сразу удаляется — в нём креды открытым
текстом, ровно как у секретов реестра. Namespace объявлен в том же
манифесте: на холодном старте Flux до слоя apps ещё не дошёл, а apply в
несуществующий namespace упал бы. Повторное создание безвредно, так же
заведён namespace vault.
This commit is contained in:
emelinda 2026-08-09 23:30:53 +03:00
parent 5efa1a5fd2
commit e1a81d3dd8
4 changed files with 125 additions and 0 deletions

View File

@ -107,6 +107,30 @@ compose_cmd: "docker compose"
# Добавляешь ConfigMap, который читает приложение, — добавь нагрузку сюда, # Добавляешь ConfigMap, который читает приложение, — добавь нагрузку сюда,
# иначе правка будет уезжать в кластер и не применяться, а выглядеть это будет # иначе правка будет уезжать в кластер и не применяться, а выглядеть это будет
# как «изменение не сработало». # как «изменение не сработало».
# --- Секреты-файлы для подов задач workflows ---------------------------------
# Их монтирует не vault-agent, а сам движок в создаваемые им Job'ы. Имя
# секрета, namespace и имя файла ЗАШИТЫ В КОД движка
# (pkg/kube_services/services.go: CredentialsName "yc-s3", CredentialsPath
# /etc/sarex/yc-s3) — переименовывать нельзя. namespace задач задаёт
# JOBS_NAMESPACE в apps/processing/base/engine-low.yaml.
#
# Формат содержимого повторяет engine/yc-s3-service-account.json из
# compose-стека и совпадает с тем, что vault-agent рендерит движку в
# /vault/secrets/processing-s3.
k8s_file_secrets:
- name: yc-s3
namespace: processing
key: yc-s3-service-account.json
content: |
{
"host": "http://minio.minio.svc.cluster.local:9000",
"bucket": "{{ sarex_django_s3_bucket }}",
"access_key_id": "{{ sarex_minio_k8s_user }}",
"secret_access_key": "{{ sarex_secrets.SAREX_MINIO_ROOT_PASSWORD }}",
"region": "us-east-1",
"verify": false
}
# --- Досоздание баз в работающей СУБД --------------------------------------- # --- Досоздание баз в работающей СУБД ---------------------------------------
# Выключено по умолчанию, включается задачей `uv run poe dbsync`. # Выключено по умолчанию, включается задачей `uv run poe dbsync`.
# #

View File

@ -0,0 +1,64 @@
---
# Секреты-файлы для подов, которые создаёт не Flux, а сам движок workflows.
#
# ЗАЧЕМ ОТДЕЛЬНО ОТ VAULT. Приложения контура получают креды аннотациями
# vault-agent — но это работает только для подов, чей шаблон мы описываем.
# Поды задач создаёт workflows-engine во время работы, аннотаций у них нет, и
# единственное, что он умеет подключить, — обычный Secret из namespace задач:
#
# services[S3Storage] = Service{
# CredentialsName: "yc-s3",
# CredentialsPath: "/etc/sarex/yc-s3",
# Envs: {"SERVICE_S3": `{"service_account":
# "/etc/sarex/yc-s3/yc-s3-service-account.json"}`},
# }
# (pkg/kube_services/services.go)
#
# Имя секрета, путь монтирования и имя файла зашиты в код движка — поменять их
# нельзя, можно только положить секрет ровно с такими именами.
#
# Без него задача падает не на доступе к S3, а на разборе конфигурации:
# pydantic_core.ValidationError: 1 validation error for S3AccountModel
# Value error, Expecting value: line 1 column 1 (char 0)
# ValueError: SERVICE_S3 is not valid
# то есть файл по пути просто отсутствует и читается как пустая строка.
#
# Как и у секретов реестра: манифест рендерится, применяется и сразу
# удаляется — в нём креды в открытом виде.
- name: Отрендерить манифест секретов-файлов
ansible.builtin.template:
src: app-secrets.yaml.j2
dest: "{{ deploy_dir }}/k3s/app-secrets.yaml"
owner: root
group: root
mode: "0600"
no_log: true
tags: [appsecrets]
# ./k3s смонтирован в k3s-server как /output — отсюда и путь.
- name: Применить секреты-файлы в кластере
ansible.builtin.command:
argv:
- "{{ compose_cmd.split()[0] }}"
- compose
- exec
- "-T"
- k3s-server
- kubectl
- apply
- "-f"
- /output/app-secrets.yaml
chdir: "{{ deploy_dir }}"
register: app_secret_apply
changed_when: >-
'created' in app_secret_apply.stdout or
'configured' in app_secret_apply.stdout
tags: [appsecrets]
# Удаляем всегда, в том числе если apply упал: файл содержит креды.
- name: Удалить манифест секретов-файлов с хоста
ansible.builtin.file:
path: "{{ deploy_dir }}/k3s/app-secrets.yaml"
state: absent
tags: [appsecrets]

View File

@ -33,6 +33,12 @@
- name: Создать секреты доступа к реестру в кластере - name: Создать секреты доступа к реестру в кластере
ansible.builtin.include_tasks: registry-secrets.yml ansible.builtin.include_tasks: registry-secrets.yml
# Секреты-файлы для подов, которые создаёт сам движок workflows. Идут сразу за
# секретами реестра: намеренно ДО Flux, потому что namespace задач манифест
# создаёт сам — ждать слой apps незачем.
- name: Создать секреты-файлы для подов задач
ansible.builtin.include_tasks: app-secrets.yml
- name: Волна 2 — gitea-init, flux-k8s-init и vault(+init) - name: Волна 2 — gitea-init, flux-k8s-init и vault(+init)
ansible.builtin.command: ansible.builtin.command:
cmd: "{{ compose_cmd }} up -d {{ aero_platform_services_wave2 | join(' ') }}" cmd: "{{ compose_cmd }} up -d {{ aero_platform_services_wave2 | join(' ') }}"

View File

@ -0,0 +1,31 @@
{# Секреты-файлы, которые монтируются в поды НЕ через vault-agent.
Обычные приложения контура берут креды из Vault аннотациями инжекции. Здесь
так нельзя: эти файлы монтирует в свои Job'ы движок workflows-engine, а он
создаёт поды сам и об аннотациях ничего не знает — ему нужен готовый Secret
в namespace задач. Имя секрета и путь монтирования зашиты в код движка
(pkg/kube_services/services.go, поля CredentialsName и CredentialsPath),
поэтому переименовать их нельзя.
Значения приходят из sarex_secrets, в репозиторий не попадают. #}
{% for s in k8s_file_secrets %}
---
{# Namespace объявлен здесь же: на холодном старте Flux до него ещё не дошёл,
а apply секрета в несуществующий namespace упал бы. Повторное создание
безвредно — Flux спокойно подхватит уже существующий объект, ровно так же
заведён namespace vault. #}
apiVersion: v1
kind: Namespace
metadata:
name: {{ s.namespace }}
---
apiVersion: v1
kind: Secret
metadata:
name: {{ s.name }}
namespace: {{ s.namespace }}
type: Opaque
stringData:
{{ s.key }}: |
{{ s.content | indent(4, true) }}
{% endfor %}