From c7c194feaa1daac92f25b6e00570fccce0558879 Mon Sep 17 00:00:00 2001 From: emelinda Date: Sat, 8 Aug 2026 20:51:02 +0300 Subject: [PATCH] =?UTF-8?q?Processing=20=D0=B2=20=D0=BA=D0=BE=D0=BD=D1=82?= =?UTF-8?q?=D1=83=D1=80=D0=B5=20aero:=20api=20=D0=B8=20engine-low?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Развёрнут частично, и это осознанно: * 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 уронит сборку явно, а не перезапишет соседнее значение. --- aero/roles/sarex_stack/defaults/main.yml | 40 +++++ apps/django/aero/kustomization.yaml | 29 ++++ apps/processing/aero/kustomization.yaml | 205 +++++++++++++++++++++++ clusters/aero/apps/kustomization.yaml | 3 + 4 files changed, 277 insertions(+) create mode 100644 apps/processing/aero/kustomization.yaml diff --git a/aero/roles/sarex_stack/defaults/main.yml b/aero/roles/sarex_stack/defaults/main.yml index bb35f4d..5091dcd 100644 --- a/aero/roles/sarex_stack/defaults/main.yml +++ b/aero/roles/sarex_stack/defaults/main.yml @@ -86,6 +86,7 @@ registry_secrets: # Образы backend и frontend лежат в приватном cr.yandex. - {name: regcred, namespace: django} - {name: regcred, namespace: measurements} + - {name: regcred, namespace: processing} # Поднимать стек (docker compose up -d). Требует запущенной службы docker и # docker login в cr.yandex — по умолчанию выключено. @@ -131,6 +132,7 @@ gitea_sync_paths: # Прикладной слой. - apps/django - apps/measurements + - apps/processing # Рабочая копия репозитория gitea на хосте (клон, живёт между прогонами). gitea_sync_workdir: "{{ deploy_dir }}/gitea-sync" @@ -266,6 +268,39 @@ vault_app_secrets: secret_key: "{{ sarex_secrets.SAREX_MINIO_ROOT_PASSWORD }}" buckets: - name: "{{ sarex_django_s3_bucket }}" + # --- Секреты приложения processing ------------------------------------------ + # Пути и имена ключей заданы vault-шаблонами в apps/processing/base — + # менять их в отрыве от манифестов нельзя. + # + # Владелец workflow_db в контуре — роль processing (см. contour.databases в + # infrastructure/postgresql/aero). В yc-k8s-test та же база принадлежит роли + # workflow; здесь имя другое, и пароль берётся из соответствующего ключа + # secrets/postgresql/users. + - path: secrets/apps/processing/postgres + data: + host: postgresql.postgresql.svc.cluster.local + port: "5432" + database: "{{ sarex_postgres_processing_db }}" + username: "{{ sarex_postgres_processing_user }}" + password: "{{ sarex_secrets.SAREX_PROCESSING_DB_PASSWORD }}" + # Как и у django — админские креды вместо отдельного пользователя. + # Хост и порт брокера чарт не читает отсюда: они захардкожены внутри + # vault-шаблона в apps/processing/base/engine-low.yaml. + - path: secrets/rabbitmq/apps/processing + data: + username: "{{ sarex_rabbitmq_k8s_user }}" + password: "{{ sarex_secrets.SAREX_RABBITMQ_PASSWORD }}" + # S3 для engine и api. Формат — не пары ключ-значение, а ЦЕЛЫЙ JSON-файл: + # переменная S3_SERVICE_ACCOUNT содержит путь к нему, а не сами креды. + # Набор ключей повторяет engine/yc-s3-service-account.json из compose-стека, + # который точно так же смотрел в MinIO. + - path: secrets/minio/apps/processing + data: + 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 # --- Секреты приложения measurements --------------------------------------- # Структура задана vault-шаблоном в apps/measurements/base/backend.yaml: он # собирает из этих ключей одну переменную S3_JSON_SETTINGS и читает endpoint @@ -317,6 +352,11 @@ sarex_minio_k8s_user: minioadmin sarex_postgres_django_db: sarex_db sarex_postgres_django_user: django +# То же для processing. Должно совпадать с записью workflow_db в +# contour.databases (infrastructure/postgresql/aero). +sarex_postgres_processing_db: workflow_db +sarex_postgres_processing_user: processing + # Бакет медиафайлов django. ВНИМАНИЕ: чарт MinIO бакеты не создаёт — его нужно # завести отдельно, иначе загрузка файлов будет падать. sarex_django_s3_bucket: sarex-media-storage diff --git a/apps/django/aero/kustomization.yaml b/apps/django/aero/kustomization.yaml index f1600d2..11cd372 100644 --- a/apps/django/aero/kustomization.yaml +++ b/apps/django/aero/kustomization.yaml @@ -64,6 +64,35 @@ patches: 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 diff --git a/apps/processing/aero/kustomization.yaml b/apps/processing/aero/kustomization.yaml new file mode 100644 index 0000000..dcb17fd --- /dev/null +++ b/apps/processing/aero/kustomization.yaml @@ -0,0 +1,205 @@ +--- +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 удалён: адреса бэкендов зашиты в образ на этапе сборки через + # __BUILD_ENV__, и ни один из готовых профилей не смотрит на домен контура. + # Подключать его имеет смысл только вместе с пересборкой образа под aero. + - target: {kind: HelmRelease, name: frontend} + patch: | + $patch: delete + apiVersion: helm.toolkit.fluxcd.io/v2 + kind: HelmRelease + metadata: + name: frontend + namespace: processing + + # --- 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/22/name + value: ENABLE_SMTP + - op: replace + path: /spec/values/services/backend/envs/22/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/21/name + value: ENABLE_PDM_STORAGE + - op: replace + path: /spec/values/services/backend/envs/21/value/_default + value: "0" + - op: test + path: /spec/values/services/backend/envs/25/name + value: ENABLE_BIM_API_V2_DB + - op: replace + path: /spec/values/services/backend/envs/25/value/_default + value: "0" + - op: test + path: /spec/values/services/backend/envs/26/name + value: ENABLE_WORKSPACE_API_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_ISSUE_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_RESOURCES_API + - op: replace + path: /spec/values/services/backend/envs/28/value/_default + value: "0" + - op: test + path: /spec/values/services/backend/envs/30/name + value: ENABLE_PDM_API_DB + - op: replace + path: /spec/values/services/backend/envs/30/value/_default + value: "0" + - op: test + path: /spec/values/services/backend/envs/31/name + value: ENABLE_COMPARISONS_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_MAIL_GUN + - op: replace + path: /spec/values/services/backend/envs/32/value/_default + value: "0" + + # Планирование подов задач. engine работает kubernetes-исполнителем и сам + # создаёт Job'ы, подставляя им nodeSelector dedicated=processing и + # соответствующий toleration. Выделенных нод в контуре нет — все три + # равнозначны, — поэтому поды задач висли бы в Pending с + # didn't match Pod's node affinity/selector + # ровно как это было у postgresql (см. postRenderers в его релизе). + - op: test + path: /spec/values/services/backend/envs/66/name + value: ENABLE_TOLERATION + - op: replace + path: /spec/values/services/backend/envs/66/value/_default + value: "0" + - op: test + path: /spec/values/services/backend/envs/69/name + value: DEFAULT_NODE_SELECTOR_KEY + - op: replace + path: /spec/values/services/backend/envs/69/value/_default + value: "" + - op: test + path: /spec/values/services/backend/envs/70/name + value: DEFAULT_NODE_SELECTOR_VALUE + - op: replace + path: /spec/values/services/backend/envs/70/value/_default + value: "" + + # 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 -}} diff --git a/clusters/aero/apps/kustomization.yaml b/clusters/aero/apps/kustomization.yaml index 9d180be..25a8d19 100644 --- a/clusters/aero/apps/kustomization.yaml +++ b/clusters/aero/apps/kustomization.yaml @@ -6,3 +6,6 @@ resources: # Сервис измерений. Django обращается к нему при MEASUREMENTS_USE_MEASUREMENTS=1 # (значение по умолчанию в base), поэтому без него часть API отвечает ошибкой. - ../../../apps/measurements/aero + # Движок workflow. Развёрнут частично: только api и engine-low, без + # собственного фронтенда — подробности в apps/processing/aero. + - ../../../apps/processing/aero