iac/apps/processing/aero/kustomization.yaml
emelinda be205b3b14 Processing: один секрет на все файлы задач, добавлен django-auth.json
Следующая задача падала на
  run.py:91  data = json.load(file)
  json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
то есть снова читала пустой файл — на этот раз django-auth.json.

Аннотации пода показали, почему: VAULT_MOUNT_PATH у движка ОДИН НА ВСЕ
файлы. Он подставляет его в каждую аннотацию, меняя только имя ключа:

  agent-inject-file-django-auth:     django-auth.json
  agent-inject-template-django-auth: {{- with secret
                                     "secrets/data/apps/processing/yc-s3" -}}

Ключа django-auth.json в том секрете не было, агент отрендерил пустоту.

Поэтому путь переименован в secrets/apps/processing/job-files: имя yc-s3
описывало один из файлов и врало о содержимом. В секрет добавлен ключ
django-auth.json — объект {"token": "..."}, а не голая строка, потому что
задача читает файл целиком через json.load. Значение то же, что у
workspaces в DJANGO_BASIC_AUTH: base64 от логина и пароля администратора.

Правило на будущее: появился новый файл, который движок кладёт в под
задачи, — добавляется ключ в этот же секрет, с именем ровно как у файла.
2026-08-10 01:11:53 +03:00

310 lines
16 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: processing
resources:
- ../base
patches:
# --- Состав: только api и engine-low ---------------------------------------
# engine удалён: в base у него replicaCount 0, то есть он и там выключен, а
# образ прибит к тегу с опечаткой в имени (workflows-endigne_prod). Рабочий
# обработчик — engine-low, он же на более свежем образе contour_*.
- target: {kind: HelmRelease, name: engine}
patch: |
$patch: delete
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: engine
namespace: processing
# frontend идёт из base без патчей. Адреса бэкендов вшиты в бандл на этапе
# сборки (константа __BUILD_ENV__), но сборка ugok2 обращается к тому же
# origin относительными путями — иначе в остальных кластерах не понадобился
# бы отдельный маршрут /workflows/api/ перед /workflows/. Поэтому фронтенд
# публикуется на домене платформы, а не на своём поддомене: маршруты в
# infrastructure/istio-config/aero, VirtualService platform.
# --- workflows-api ----------------------------------------------------------
- target: {kind: HelmRelease, name: workflows-api}
patch: |
# S3 приезжает из Vault отдельным ФАЙЛОМ, а не парой переменных:
# приложение читает по этому пути целый JSON. В base путь ведёт в
# /etc/sarex/yc-s3/, куда в контуре ничего не смонтировано.
- op: test
path: /spec/values/services/backend/envs/3/name
value: S3_SERVICE_ACCOUNT
- op: replace
path: /spec/values/services/backend/envs/3/value/_default
value: /vault/secrets/processing-s3
- op: add
path: /spec/values/services/backend/podAnnotations/_default/vault.hashicorp.com~1agent-inject-secret-processing-s3
value: secrets/data/minio/apps/processing
- op: add
path: /spec/values/services/backend/podAnnotations/_default/vault.hashicorp.com~1agent-inject-template-processing-s3
value: |-
{{- with secret "secrets/data/minio/apps/processing" -}}
{
"host": "{{ index .Data.data "host" }}",
"bucket": "{{ index .Data.data "bucket" }}",
"access_key_id": "{{ index .Data.data "access_key_id" }}",
"secret_access_key": "{{ index .Data.data "secret_access_key" }}",
"region": "{{ index .Data.data "region" }}",
"verify": false
}
{{- end -}}
# --- engine-low -------------------------------------------------------------
# Патчи адресуются по индексу, поэтому перед каждым replace идёт op: test на
# имя переменной. Если в base порядок envs изменится, сборка упадёт явно,
# вместо того чтобы молча перезаписать соседнее значение.
- target: {kind: HelmRelease, name: engine-low}
patch: |
# Sentry — внешний домен, из контура недостижим. Значение прокидывается
# ещё и в каждый под задачи, поэтому зануляем в одном месте.
- op: test
path: /spec/values/services/backend/envs/2/name
value: WORKFLOWS_SENTRY_DSN
- op: replace
path: /spec/values/services/backend/envs/2/value/_default
value: ""
# В base адрес django неверный даже для кластеров, где он есть: сервис
# называется backend-svc и слушает 80, а не backend:8000. У api то же
# значение уже правильное.
- op: test
path: /spec/values/services/backend/envs/5/name
value: DJANGO_HOST
- op: replace
path: /spec/values/services/backend/envs/5/value/_default
value: http://backend-svc.django.svc.cluster.local:80
# S3 — как у api выше.
- op: test
path: /spec/values/services/backend/envs/6/name
value: S3_SERVICE_ACCOUNT
- op: replace
path: /spec/values/services/backend/envs/6/value/_default
value: /vault/secrets/processing-s3
# SMTP выключаем целиком: почтового релея в контуре нет. Вместе с флагом
# убираем аннотацию инжекции secrets/vault/common/smtp_auth — секрета в
# Vault нет, а vault-agent-init на несуществующем секрете не отрендерит
# шаблон и оставит под в Init:Error, до флага дело не дойдёт.
- op: test
path: /spec/values/services/backend/envs/23/name
value: ENABLE_SMTP
- op: replace
path: /spec/values/services/backend/envs/23/value/_default
value: "0"
- op: remove
path: /spec/values/services/backend/podAnnotations/_default/vault.hashicorp.com~1agent-inject-secret-processing-smtp
- op: remove
path: /spec/values/services/backend/podAnnotations/_default/vault.hashicorp.com~1agent-inject-template-processing-smtp
# Смежные сервисы, которых в контуре нет: documentations (PDM,
# filestream), resources, bim-api, workspace, issues, comparisons,
# mailgun. Оставляем только S3 — единственное внешнее хранилище, которое
# в aero действительно есть.
- op: test
path: /spec/values/services/backend/envs/22/name
value: ENABLE_PDM_STORAGE
- op: replace
path: /spec/values/services/backend/envs/22/value/_default
value: "0"
- op: test
path: /spec/values/services/backend/envs/26/name
value: ENABLE_BIM_API_V2_DB
- op: replace
path: /spec/values/services/backend/envs/26/value/_default
value: "0"
- op: test
path: /spec/values/services/backend/envs/27/name
value: ENABLE_WORKSPACE_API_DB
- op: replace
path: /spec/values/services/backend/envs/27/value/_default
value: "0"
- op: test
path: /spec/values/services/backend/envs/28/name
value: ENABLE_ISSUE_API_DB
- op: replace
path: /spec/values/services/backend/envs/28/value/_default
value: "0"
- op: test
path: /spec/values/services/backend/envs/29/name
value: ENABLE_RESOURCES_API
- op: replace
path: /spec/values/services/backend/envs/29/value/_default
value: "0"
- op: test
path: /spec/values/services/backend/envs/31/name
value: ENABLE_PDM_API_DB
- op: replace
path: /spec/values/services/backend/envs/31/value/_default
value: "0"
- op: test
path: /spec/values/services/backend/envs/32/name
value: ENABLE_COMPARISONS_API_DB
- op: replace
path: /spec/values/services/backend/envs/32/value/_default
value: "0"
- op: test
path: /spec/values/services/backend/envs/33/name
value: ENABLE_MAIL_GUN
- op: replace
path: /spec/values/services/backend/envs/33/value/_default
value: "0"
# Планирование подов задач. engine работает kubernetes-исполнителем и сам
# создаёт Job'ы, подставляя им nodeSelector dedicated=processing и
# соответствующий toleration. Выделенных нод в контуре нет — все три
# равнозначны, — поэтому поды задач висли бы в Pending с
# didn't match Pod's node affinity/selector
# ровно как это было у postgresql (см. postRenderers в его релизе).
#
# ENABLE_TOLERATION ЗДЕСЬ НЕ ВЫКЛЮЧАТЬ. Сначала я поставил его в "0" — и
# это тихо сломало запуск задач совсем: в движке классы ресурсов
# регистрируются ПОД ЭТИМ ЖЕ ФЛАГОМ,
# if resCfg.EnableToleration { services[HighResources] = ... }
# (pkg/kube_services/services.go), поэтому задача с service_request
# "high-resources" падала не на планировании, а раньше — на разборе:
# ERROR create k8s job: create k8s job: unknown service
# Ни одного пода при этом не создавалось, и в логе не было ни слова про
# nodeSelector, так что связь с этим флагом неочевидна.
#
# Вместо выключения переводим селектор на метку, которая есть на всех
# нодах, — kubernetes.io/os=linux. Класс сервисов остаётся
# зарегистрированным, nodeSelector совпадает с любой нодой, а toleration
# на несуществующий taint безвреден. Запрашиваемые ресурсы трогать не
# надо: в base это 1 CPU и 1Gi.
#
# IGNORE_TAINTS_AND_NODE_SELECTOR (появился в base из master) полагаться
# на него не стоит: в master workflows-engine такой переменной нет. Образ
# при этом contour_a03d37da-dirty2 — ручная сборка, поднятая тем же
# коммитом master, что добавил переменную, так что она там, вероятно,
# поддержана. Проверить нечем, поэтому селектор задан явно, а не через
# неё; вреда от того, что она выставлена в base, нет.
- op: test
path: /spec/values/services/backend/envs/53/name
value: TOLERATION_KEY
- op: replace
path: /spec/values/services/backend/envs/53/value/_default
value: kubernetes.io/os
- op: test
path: /spec/values/services/backend/envs/54/name
value: TOLERATION_VALUE
- op: replace
path: /spec/values/services/backend/envs/54/value/_default
value: linux
- op: test
path: /spec/values/services/backend/envs/55/name
value: TOLERATION_KEY_HIGH_MEM
- op: replace
path: /spec/values/services/backend/envs/55/value/_default
value: kubernetes.io/os
- op: test
path: /spec/values/services/backend/envs/56/name
value: TOLERATION_VALUE_HIGH_MEM
- op: replace
path: /spec/values/services/backend/envs/56/value/_default
value: linux
- op: test
path: /spec/values/services/backend/envs/57/name
value: TOLERATION_KEY_PERSISTENT
- op: replace
path: /spec/values/services/backend/envs/57/value/_default
value: kubernetes.io/os
- op: test
path: /spec/values/services/backend/envs/58/name
value: TOLERATION_VALUE_PERSISTENT
- op: replace
path: /spec/values/services/backend/envs/58/value/_default
value: linux
- op: test
path: /spec/values/services/backend/envs/70/name
value: DEFAULT_NODE_SELECTOR_KEY
- op: replace
path: /spec/values/services/backend/envs/70/value/_default
value: kubernetes.io/os
- op: test
path: /spec/values/services/backend/envs/71/name
value: DEFAULT_NODE_SELECTOR_VALUE
- op: replace
path: /spec/values/services/backend/envs/71/value/_default
value: linux
# --- Vault для ПОДОВ ЗАДАЧ, а не для самого движка ----------------------
# В сборке contour_a03d37da-dirty2 движок умеет не монтировать в Job
# готовый Secret, а вешать на него аннотации vault-agent — тогда файл
# с кредами кладёт агент, и Secret в namespace задач не нужен вовсе.
# Именно так это работает в UGMK, где никакого yc-s3 в namespace нет.
#
# В master workflows-engine этого кода нет (сборка с невлитой ветки),
# поэтому набор переменных восстановлен по строкам бинарника:
# VAULT_ROLE, VAULT_SA, VAULT_MOUNT_PATH
# vault.hashicorp.com/{role,secret-volume-path,agent-inject-file-*,
# agent-inject-secret-*,agent-inject-template-*}
# yc-s3, yc-s3-service-account.json, /etc/sarex/yc-s3
#
# В base задан только VAULT_USE=true — остальных трёх нет НИ В ОДНОМ
# кластере репозитория, поэтому аннотации выходили неполными, агент в под
# задачи ничего не клал, и файл читался как пустой:
# ValueError: SERVICE_S3 is not valid
# Expecting value: line 1 column 1 (char 0)
#
# Переменных нет в base, поэтому op: add с "-" (добавление в конец
# списка), а не replace по индексу.
- op: add
path: /spec/values/services/backend/envs/-
value:
name: VAULT_ROLE
value:
_default: processing
- op: add
path: /spec/values/services/backend/envs/-
value:
name: VAULT_SA
value:
_default: processing-vault
# VAULT_MOUNT_PATH — вопреки имени НЕ корень KV, а ПОЛНЫЙ путь секрета:
# движок подставляет значение в шаблон целиком. Проверено по аннотациям
# созданного пода задачи:
# agent-inject-secret-yc-s3: <VAULT_MOUNT_PATH>
# agent-inject-template-yc-s3:
# {{- with secret "<VAULT_MOUNT_PATH>" -}}
# {{ index .Data.data "yc-s3-service-account.json" }}
# Отсюда два следствия: путь пишется в форме чтения KV v2 (с /data/), а в
# секрете обязан быть ключ с именем ФАЙЛА.
#
# Путь ОДИН НА ВСЕ ФАЙЛЫ, которые движок кладёт в поды задач: он
# подставляет VAULT_MOUNT_PATH в каждую аннотацию, меняя только имя
# ключа. Так, для django-auth аннотация ссылается на этот же путь и ищет
# в нём ключ django-auth.json. Поэтому имя пути нейтральное (job-files),
# а не по имени одного из файлов, — иначе оно врёт о содержимом.
# Сам секрет кладёт ansible, vault_app_secrets.
- op: add
path: /spec/values/services/backend/envs/-
value:
name: VAULT_MOUNT_PATH
value:
_default: secrets/data/apps/processing/job-files
# S3 из Vault, как у api.
- op: add
path: /spec/values/services/backend/podAnnotations/_default/vault.hashicorp.com~1agent-inject-secret-processing-s3
value: secrets/data/minio/apps/processing
- op: add
path: /spec/values/services/backend/podAnnotations/_default/vault.hashicorp.com~1agent-inject-template-processing-s3
value: |-
{{- with secret "secrets/data/minio/apps/processing" -}}
{
"host": "{{ index .Data.data "host" }}",
"bucket": "{{ index .Data.data "bucket" }}",
"access_key_id": "{{ index .Data.data "access_key_id" }}",
"secret_access_key": "{{ index .Data.data "secret_access_key" }}",
"region": "{{ index .Data.data "region" }}",
"verify": false
}
{{- end -}}