iac/apps/django/aero/kustomization.yaml
emelinda c7c194feaa Processing в контуре aero: api и engine-low
Развёрнут частично, и это осознанно:
  * engine удалён — в base у него replicaCount 0, то есть он выключен и там,
    а образ прибит к тегу с опечаткой в имени (workflows-endigne_prod);
  * frontend удалён — адреса бэкендов зашиты в образ на этапе сборки через
    __BUILD_ENV__, и ни один готовый профиль не смотрит на домен контура.
    Подключать его имеет смысл только вместе с пересборкой образа.

Отключены смежные сервисы, которых в контуре нет: documentations (PDM,
filestream), resources, bim-api, workspace, issues, comparisons, mailgun,
SMTP. Оставлен только S3. Вместе с флагом ENABLE_SMTP убрана аннотация
инжекции secrets/vault/common/smtp_auth — секрета нет, и vault-agent-init
оставил бы под в Init:Error, не дойдя до флага.

S3 приезжает из Vault отдельным файлом: приложение читает по пути из
S3_SERVICE_ACCOUNT целый JSON, а не пару переменных. Набор ключей повторяет
engine/yc-s3-service-account.json из compose-стека, который так же смотрел
в MinIO.

Планирование подов задач: engine работает kubernetes-исполнителем и сам
создаёт Job'ы, подставляя им nodeSelector dedicated=processing. Выделенных
нод в контуре нет, поды висли бы в Pending — как это уже было у postgresql.
ENABLE_TOLERATION и DEFAULT_NODE_SELECTOR_* сняты.

Заодно у celery поправлены четыре адреса на wb.sarex.io — чужой контур,
недостижимый из aero. У backend те же переменные уже вели внутрь кластера;
при WORKFLOWS_USE=1 расхождение давало бы зависания вместо явной ошибки.

Патчи адресуются по индексу env, поэтому перед каждым replace стоит op: test
на имя переменной: смена порядка в base уронит сборку явно, а не перезапишет
соседнее значение.
2026-08-08 20:51:02 +03:00

213 lines
13 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: django
resources:
- ../base
patches:
# Свой nginx.conf вместо базового: в base зашиты upstream'ы на namespace,
# которых в контуре нет, и nginx из-за этого не стартовал. Подробности —
# в шапке nginx-configmap.yaml.
#
# ИМЕННО ПАТЧ, а не resources. Объект с тем же kind+name уже пришёл из
# ../base, и добавление его вторым ресурсом валит сборку целиком:
# may not add resource with an already registered id:
# ConfigMap.v1.[noGrp]/nginx-configmap.django
# Перекрывать базовый ресурс можно только патчем.
- path: nginx-configmap.yaml
target:
kind: ConfigMap
name: nginx-configmap
# --- celery: те же правки, что и у backend --------------------------------
# Worker крутит тот же образ и те же настройки, поэтому и расхождения с base
# у него ровно те же: нет Kafka, нет Zitadel, MinIO живёт внутри кластера.
# Обоснования — в блоке backend ниже, здесь не дублирую.
#
# SERVER_ZITADEL_ENABLED правки не требует: в base у celery он уже "False"
# (в отличие от backend).
- target: {kind: HelmRelease, name: celery}
patch: |
- op: remove
path: /spec/values/services/celery/podAnnotations/_default/vault.hashicorp.com~1agent-inject-secret-django-kafka
- op: remove
path: /spec/values/services/celery/podAnnotations/_default/vault.hashicorp.com~1agent-inject-template-django-kafka
- op: remove
path: /spec/values/services/celery/podAnnotations/_default/vault.hashicorp.com~1agent-inject-secret-django-common
- op: remove
path: /spec/values/services/celery/podAnnotations/_default/vault.hashicorp.com~1agent-inject-template-django-common
- op: replace
path: /spec/values/services/celery/podAnnotations/_default/vault.hashicorp.com~1agent-inject-template-django-s3
value: |-
{{- with secret "secrets/data/minio/apps/django" }}
AWS_S3_ENDPOINT_URL=http://minio.minio.svc.cluster.local:9000
S3_HOST=http://minio.minio.svc.cluster.local:9000
{{- $buckets := index .Data.data "buckets" }}
S3_BUCKET={{ if gt (len $buckets) 0 }}{{ index (index $buckets 0) "name" }}{{ else }}django{{ end }}
S3_LOGIN={{ index .Data.data "access_key" }}
S3_PASSWORD={{ index .Data.data "secret_key" }}
{{- end }}
# Стартовый скрипт без подключения django-kafka: этого секрета в контуре
# нет. migrate и создание администратора сюда НЕ добавляются — схемой
# владеет backend, а два процесса, катящих миграции наперегонки при
# одновременном старте, — это гонка на ровном месте.
- op: replace
path: /spec/values/services/celery/deployment/args/_default/0
value: |
set -a
[ -f /vault/secrets/django-postgresql ] && . /vault/secrets/django-postgresql
[ -f /vault/secrets/django-rabbitmq ] && . /vault/secrets/django-rabbitmq
[ -f /vault/secrets/django-s3 ] && . /vault/secrets/django-s3
[ -f /vault/secrets/django-jwt-private ] && export JWT_PRIVATE_KEY="$(cat /vault/secrets/django-jwt-private)"
[ -f /vault/secrets/django-jwt-public ] && export JWT_PUBLIC_KEY="$(cat /vault/secrets/django-jwt-public)"
set +a
exec celery -A config worker -B -l info -E -Q default -n default_worker.%h --concurrency=2
# Адреса на wb.sarex.io — чужой контур, из aero недостижим. В base их
# четыре, и все четыре у celery: у backend те же переменные уже указывают
# внутрь кластера. WORKFLOWS_USE=1, так что оставить как есть — значит
# получить зависания на недоступном домене вместо явной ошибки.
- op: test
path: /spec/values/services/celery/envs/15/name
value: SERVER_API_HOST
- op: replace
path: /spec/values/services/celery/envs/15/value/_default
value: https://sarex.local.lonsdaleites.ru
- op: test
path: /spec/values/services/celery/envs/16/name
value: SERVER_HOST
- op: replace
path: /spec/values/services/celery/envs/16/value/_default
value: https://sarex.local.lonsdaleites.ru
- op: test
path: /spec/values/services/celery/envs/17/name
value: WORKFLOWS_HOST
- op: replace
path: /spec/values/services/celery/envs/17/value/_default
value: http://backend-svc.processing.svc.cluster.local:80
- op: test
path: /spec/values/services/celery/envs/18/name
value: WORKFLOWS_BASE_HOST
- op: replace
path: /spec/values/services/celery/envs/18/value/_default
value: http://backend-svc.django.svc.cluster.local:80
# Тег образа выравнен с backend. В base у celery production_a96dead0, а у
# backend production_f813140d — worker и web крутили бы разный код, и
# рассинхрон вылезал бы не при старте, а на конкретной задаче: worker
# десериализует аргументы по своей версии модели.
- op: replace
path: /spec/values/services/celery/image/name/_default
value: cr.yandex/crp3ccidau046kdj8g9q/backend:production_f813140d
# --- backend: убираем зависимости, которых в контуре нет ------------------
- target: {kind: HelmRelease, name: backend}
patch: |
# Kafka и Zitadel в контуре не развёрнуты. Само приложение без них живёт:
# * SERVER_KAFKA_ENABLED в base уже "False", а в sarex-backend продюсер
# создаётся только под флагом (config/settings/deps/kafka.py);
# * zitadel_enabled читается ровно в одном месте — update_ams_user()
# в sarex/core/utils.py, которая при выключенном флаге сразу выходит.
# К аутентификации Zitadel отношения не имеет.
#
# Но аннотации инжекции убрать ОБЯЗАТЕЛЬНО: vault-agent-init не отрендерит
# шаблон для несуществующего секрета, упадёт, и под навсегда останется в
# Init:Error — приложение до своих флагов даже не дойдёт.
#
# В JSON Pointer слэш внутри ключа экранируется как ~1, поэтому
# vault.hashicorp.com/agent-... записан как vault.hashicorp.com~1agent-...
- op: remove
path: /spec/values/services/backend/podAnnotations/_default/vault.hashicorp.com~1agent-inject-secret-django-kafka
- op: remove
path: /spec/values/services/backend/podAnnotations/_default/vault.hashicorp.com~1agent-inject-template-django-kafka
- op: remove
path: /spec/values/services/backend/podAnnotations/_default/vault.hashicorp.com~1agent-inject-secret-django-common
- op: remove
path: /spec/values/services/backend/podAnnotations/_default/vault.hashicorp.com~1agent-inject-template-django-common
# S3 внутри кластера, а не через внешний домен. В base шаблон прибит к
# https://minio.contour.infra.sarex.tech — чужому домену, который отсюда
# не резолвится. Через values это не перекрыть: адрес зашит ВНУТРИ
# vault-шаблона аннотации, поэтому заменяем аннотацию целиком.
# Ходим напрямую в сервис MinIO, как это делал compose-стек.
- op: replace
path: /spec/values/services/backend/podAnnotations/_default/vault.hashicorp.com~1agent-inject-template-django-s3
value: |-
{{- with secret "secrets/data/minio/apps/django" }}
AWS_S3_ENDPOINT_URL=http://minio.minio.svc.cluster.local:9000
S3_HOST=http://minio.minio.svc.cluster.local:9000
{{- $buckets := index .Data.data "buckets" }}
S3_BUCKET={{ if gt (len $buckets) 0 }}{{ index (index $buckets 0) "name" }}{{ else }}django{{ end }}
S3_LOGIN={{ index .Data.data "access_key" }}
S3_PASSWORD={{ index .Data.data "secret_key" }}
{{- end }}
# Выключаем Zitadel. Операция test перед replace — страховка от смещения
# индекса: если в base порядок envs изменится, патч упадёт явно, вместо
# того чтобы молча перезаписать соседнюю переменную.
- op: test
path: /spec/values/services/backend/envs/2/name
value: SERVER_ZITADEL_ENABLED
- op: replace
path: /spec/values/services/backend/envs/2/value/_default
value: "False"
# --- Администратор платформы --------------------------------------------
# Учётка приезжает из Vault под именами, которые ждёт штатная
# createsuperuser --noinput. Секрет кладёт ansible
# (vault_app_secrets, secrets/apps/django/superuser).
- op: add
path: /spec/values/services/backend/podAnnotations/_default/vault.hashicorp.com~1agent-inject-secret-django-superuser
value: secrets/data/apps/django/superuser
- op: add
path: /spec/values/services/backend/podAnnotations/_default/vault.hashicorp.com~1agent-inject-template-django-superuser
value: |-
{{- with secret "secrets/data/apps/django/superuser" -}}
DJANGO_SUPERUSER_USERNAME={{ index .Data.data "username" }}
DJANGO_SUPERUSER_EMAIL={{ index .Data.data "email" }}
DJANGO_SUPERUSER_PASSWORD={{ index .Data.data "password" }}
{{- end -}}
# Стартовый скрипт целиком, а не точечная правка: JSON6902 умеет заменять
# только элемент списка, а вся логика запуска — один shell-блок args[0].
# Отличия от base:
# * не подключается django-kafka — этого секрета в контуре нет;
# * добавлены migrate и создание администратора.
#
# Почему migrate здесь, хотя его же делает /opt/sarex/entrypoint.sh:
# там он запущен без set -e, и его падение НИКАК не мешает uwsgi
# стартовать. Именно так контур несколько часов отдавал 200 на /admin/
# с пустой схемой БД, пока backend не мог аутентифицироваться. Здесь
# команда выполняется под set -e из command базы (/bin/sh -ec), поэтому
# неудача валит под в CrashLoopBackOff — то есть становится видимой.
# Повторный прогон внутри entrypoint.sh при уже накатанной схеме
# отрабатывает вхолостую за секунды.
- op: replace
path: /spec/values/services/backend/deployment/args/_default/0
value: |
set -a
[ -f /vault/secrets/django-postgresql ] && . /vault/secrets/django-postgresql
[ -f /vault/secrets/django-rabbitmq ] && . /vault/secrets/django-rabbitmq
[ -f /vault/secrets/django-s3 ] && . /vault/secrets/django-s3
[ -f /vault/secrets/django-superuser ] && . /vault/secrets/django-superuser
[ -f /vault/secrets/django-jwt-private ] && export JWT_PRIVATE_KEY="$(cat /vault/secrets/django-jwt-private)"
[ -f /vault/secrets/django-jwt-public ] && export JWT_PUBLIC_KEY="$(cat /vault/secrets/django-jwt-public)"
set +a
python manage.py migrate --noinput
# Идемпотентно по построению: команда отрабатывает при КАЖДОМ старте
# пода, а на уже существующем логине штатно возвращает
# "That username is already taken" с ненулевым кодом. Ошибка ожидаема
# и гасится веткой else, иначе set -e ронял бы под на втором запуске.
if [ -n "${DJANGO_SUPERUSER_USERNAME:-}" ]; then
if python manage.py createsuperuser --noinput; then
echo "entrypoint: администратор создан"
else
echo "entrypoint: администратор уже существует, пропускаем"
fi
fi
exec /opt/sarex/entrypoint.sh