Measurements в контуре aero + декларативное заведение бакетов

Django обращается к сервису измерений при MEASUREMENTS_USE_MEASUREMENTS=1
(значение по умолчанию в base), так что без него часть API отвечала ошибкой.

Сервис переименован в measurements-service, как в brusnika-*. В base он
называется measurements-svc, а django ходит на measurements-service —
переименовать сервис дешевле, чем патчить переменную в двух релизах django.

Бакеты теперь заводит Job в infrastructure/minio/aero, а не команда руками.
Чарт MinIO этого не умеет: форк не принимает ни buckets, ни provisioning.
Так бакет django был создан императивно и не пережил бы пересоздание
контура — развернув всё с нуля, получили бы работающий MinIO и приложения,
падающие на отсутствующем бакете. Measurements сломался бы на этом сразу:
имя бакета зашито в его vault-шаблоне. Идемпотентность даёт
mc mb --ignore-existing.

Сайдкар istio у Job отключён: контейнер задачи выходит, envoy продолжает
работать, и под навсегда остаётся Running.
This commit is contained in:
emelinda 2026-08-08 20:41:23 +03:00
parent 237dcb9b28
commit 51b9120797
5 changed files with 123 additions and 5 deletions

View File

@ -85,6 +85,7 @@ registry_secrets:
- {name: regcred, namespace: minio}
# Образы backend и frontend лежат в приватном cr.yandex.
- {name: regcred, namespace: django}
- {name: regcred, namespace: measurements}
# Поднимать стек (docker compose up -d). Требует запущенной службы docker и
# docker login в cr.yandex — по умолчанию выключено.
@ -127,8 +128,9 @@ gitea_sync_paths:
- infrastructure/postgresql
- infrastructure/rabbitmq
- infrastructure/minio
# Прикладной слой: django (backend + frontend).
# Прикладной слой.
- apps/django
- apps/measurements
# Рабочая копия репозитория gitea на хосте (клон, живёт между прогонами).
gitea_sync_workdir: "{{ deploy_dir }}/gitea-sync"
@ -213,6 +215,7 @@ vault_k8s_roles:
- {name: minio, namespaces: [minio]}
- {name: django, namespaces: [django]}
- {name: processing, namespaces: [processing]}
- {name: measurements, namespaces: [measurements]}
# Боевые креды инфраструктурных сервисов. Пути и имена ключей заданы чартами
# (см. vaultRoot у minio и auth.vault у rabbitmq в infrastructure/*/aero) —
@ -263,6 +266,22 @@ vault_app_secrets:
secret_key: "{{ sarex_secrets.SAREX_MINIO_ROOT_PASSWORD }}"
buckets:
- name: "{{ sarex_django_s3_bucket }}"
# --- Секреты приложения measurements ---------------------------------------
# Структура задана vault-шаблоном в apps/measurements/base/backend.yaml: он
# собирает из этих ключей одну переменную S3_JSON_SETTINGS и читает endpoint
# ВЛОЖЕННЫМ ключом .Data.data.client.endpoint — отсюда лишний уровень client.
#
# Бакет measurements зашит в том же шаблоне и заводится Job'ом
# infrastructure/minio/aero/buckets-job.yaml.
#
# Отдельного пользователя MinIO нет — тот же временный компромисс, что и у
# django: берём root-креды.
- path: secrets/minio/apps/measurements
data:
client:
endpoint: http://minio.minio.svc.cluster.local:9000
access_key: "{{ sarex_minio_k8s_user }}"
secret_key: "{{ sarex_secrets.SAREX_MINIO_ROOT_PASSWORD }}"
# Учётка администратора платформы. Её разбирает не приложение, а стартовый
# скрипт пода backend: он экспортирует ключи как DJANGO_SUPERUSER_* — ровно
# те имена, которые ждёт штатная manage.py createsuperuser --noinput.

View File

@ -0,0 +1,26 @@
---
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: measurements
resources:
- ../base
patches:
- target: {kind: HelmRelease, name: measurements}
patch: |
# Имя сервиса приводим к measurements-service, как в brusnika-*.
#
# В base сервис называется measurements-svc, а django ходит на
# MEASUREMENTS_HOST=http://measurements-service.measurements.svc.cluster.local:8000/api
# (apps/django/base/backend.yaml). Переименовать сервис дешевле, чем
# патчить переменную в двух релизах django (backend и celery), и заодно
# совпадает с тем, как это сделано в остальных кластерах.
- op: replace
path: /spec/values/services/backend/service/name/_default
value: measurements-service
# S3 внутри кластера. В base endpoint приезжает из самого секрета
# (.Data.data.client.endpoint), поэтому шаблон править не нужно — адрес
# задаёт ansible в vault_app_secrets. Бакет measurements заводит
# infrastructure/minio/aero/buckets-job.yaml: имя зашито в шаблоне
# аннотации, и без готового бакета приложение не поднимется.

View File

@ -1,9 +1,8 @@
# Слой 3: прикладные сервисы контура.
#
# Первым переезжает django — backend и frontend. Остальные его части
# (celery, srx-admin, s3-proxy) выключены в apps/django/aero и подключатся
# следующим шагом.
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../../apps/django/aero
# Сервис измерений. Django обращается к нему при MEASUREMENTS_USE_MEASUREMENTS=1
# (значение по умолчанию в base), поэтому без него часть API отвечает ошибкой.
- ../../../apps/measurements/aero

View File

@ -0,0 +1,72 @@
---
# Заведение бакетов. Чарт MinIO этого не умеет — форк не принимает ни buckets,
# ни provisioning, — а приложения ждут бакеты готовыми: django падает на
# загрузке файлов, measurements — на старте, потому что имя бакета зашито в
# его vault-шаблоне.
#
# До этого Job'а бакеты заводились руками через mc. Такой бакет не переживает
# пересоздание контура и не виден в репозитории: развернув всё с нуля, ты
# получишь работающий MinIO и приложения, падающие на отсутствующем бакете.
#
# Идемпотентность даёт mc mb --ignore-existing: Job гоняется при каждом
# применении релиза (ttl удаляет завершившийся), повторный запуск на готовых
# бакетах отрабатывает вхолостую и завершается нулём.
apiVersion: batch/v1
kind: Job
metadata:
name: minio-buckets
namespace: minio
annotations:
# Пересоздавать Job при каждой синхронизации: спецификация Job неизменяема,
# и без пересоздания kustomize не смог бы применить правку списка бакетов.
kustomize.toolkit.fluxcd.io/force: "true"
spec:
# Job живёт час после завершения и удаляется. Не 0: если он упадёт, логи
# должны остаться доступными для разбора.
ttlSecondsAfterFinished: 3600
backoffLimit: 6
template:
metadata:
annotations:
# Sidecar istio не даёт Job завершиться: контейнер задачи выходит, а
# envoy продолжает работать, и под навсегда остаётся Running.
sidecar.istio.io/inject: "false"
vault.hashicorp.com/agent-inject: "true"
vault.hashicorp.com/agent-init-first: "true"
vault.hashicorp.com/agent-pre-populate-only: "true"
vault.hashicorp.com/auth-path: auth/kubernetes
vault.hashicorp.com/role: minio
vault.hashicorp.com/agent-inject-secret-admin: secrets/data/minio/admin
vault.hashicorp.com/agent-inject-template-admin: |-
{{- with secret "secrets/data/minio/admin" -}}
MINIO_ROOT_USER={{ index .Data.data "rootUser" }}
MINIO_ROOT_PASSWORD={{ index .Data.data "rootPassword" }}
{{- end -}}
spec:
restartPolicy: OnFailure
serviceAccountName: minio-sa
imagePullSecrets:
- name: regcred
containers:
- name: mc
# Тот же образ, которым бакеты заводил compose-стек (SAREX_MC_IMAGE
# в docker-compose.yaml). Тег фиксированный: latest в приватном
# реестре не публикуется.
image: cr.yandex/crp3ccidau046kdj8g9q/mc:250724
command: ["/bin/sh", "-ec"]
args:
- |
. /vault/secrets/admin
# Ждём готовности API: Job стартует вместе с релизом и обгоняет
# готовность самого MinIO.
until mc alias set contour http://minio.minio.svc.cluster.local:9000 \
"$MINIO_ROOT_USER" "$MINIO_ROOT_PASSWORD" >/dev/null 2>&1; do
echo "жду MinIO..."
sleep 5
done
for b in sarex-media-storage measurements; do
mc mb --ignore-existing "contour/$b"
echo "бакет $b готов"
done

View File

@ -3,6 +3,8 @@ apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../base
# Заведение бакетов: чарт этого не умеет, см. шапку файла.
- buckets-job.yaml
patches:
- path: minio.yaml
target: