Measurements пишет в общий бакет контура + перекат нагрузок в ansible
--- Бакет --- В base у measurements имя бакета ЗАШИТО в самом vault-шаблоне: "buckets":["measurements"] Из-за этого он складывал файлы в собственный бакет, тогда как медиахранилище контура одно — sarex-media-storage: туда пишет django и оттуда же раздаёт s3-proxy на маршруте /media/. Ссылка на файл измерения, отданная через django, вела бы в пустоту. Шаблон переопределён в apps/measurements/aero так, чтобы имя бакета читалось из секрета — как уже читается endpoint. Значение задаётся в одном месте, vault_app_secrets, и совпадает с sarex_django_s3_bucket. Заменить пришлось аннотацию целиком: значение внутри шаблона, через values его не перекрыть. Из Job'а бакетов убран measurements. Это не удаление: Job умеет только mc mb --ignore-existing, ранее созданный бакет остаётся на месте — мы лишь перестаём его заводить. Порядок применения безопасен: в platform.yml vault-k8s.yml идёт до gitea-sync.yml, то есть секрет получит ключ bucket раньше, чем Flux пересоздаст под. Иначе vault-agent-init не отрендерил бы шаблон с несуществующим ключом и под ушёл бы в Init:Error. --- Перекат нагрузок --- Единственное действие, которое до сих пор делалось руками мимо роли, — rollout restart после правки ConfigMap. Оно понадобилось дважды (порядок set/rewrite в nginx и auth_type) и оба раза выглядело как «правка не поехала»: Flux рапортует Applied revision, а поведение старое. Причина в том, что у релизов universal-chart в шаблоне пода нет контрольной суммы конфига: ConfigMap меняется, спецификация пода — нет, Kubernetes не видит причин пересоздавать под. Декларативно это здесь не лечится — имя ConfigMap передаётся чарту строкой, монтирует он его сам, а configMapGenerator переименовал бы ресурс, не поправив ссылку внутри чарта, который рендерится уже в кластере. Добавлены tasks/reload.yml, список sarex_reload_workloads в defaults и задача `uv run poe reload`. По умолчанию выключено: перезапуск подов посреди обычного деплоя происходить сам не должен.
This commit is contained in:
parent
0a69d528b3
commit
c750a08f8d
@ -47,6 +47,11 @@ login = "ansible-playbook deploy.yml --tags login"
|
||||
# Показать логин+пароль администратора платформы. Саму учётку создаёт под
|
||||
# backend при старте (apps/django/aero), эта задача только печатает креды.
|
||||
superuser = "ansible-playbook deploy.yml -e sarex_create_superuser=true --tags superuser"
|
||||
# Перекатить нагрузки, конфигурация которых лежит в ConfigMap. Нужно после
|
||||
# правки nginx-configmap: Flux обновит ConfigMap, но под продолжит работать со
|
||||
# старым содержимым — в шаблоне пода нет хеша конфига, спецификация не меняется
|
||||
# и Kubernetes не видит причин его пересоздавать. Список — sarex_reload_workloads.
|
||||
reload = "ansible-playbook deploy.yml -e sarex_reload=true --tags reload"
|
||||
lint = "ansible-lint"
|
||||
|
||||
# --- Операционные задачи на хосте (без полного деплоя) ----------------------
|
||||
|
||||
@ -94,6 +94,28 @@ registry_secrets:
|
||||
sarex_compose_up: false
|
||||
compose_cmd: "docker compose"
|
||||
|
||||
# --- Перекат нагрузок после правки конфигурации -----------------------------
|
||||
# Выключено по умолчанию: перезапуск подов посреди обычного деплоя — не то, что
|
||||
# должно происходить само. Включается задачей `uv run poe reload`.
|
||||
#
|
||||
# Список — это нагрузки, конфигурация которых лежит в ConfigMap и потому НЕ
|
||||
# подхватывается без пересоздания пода: спецификация пода не меняется, значит
|
||||
# Kubernetes не видит причин его перекатывать. Всё остальное перекатывается
|
||||
# само — правка envs или podAnnotations меняет шаблон пода.
|
||||
#
|
||||
# Добавляешь ConfigMap, который читает приложение, — добавь нагрузку сюда,
|
||||
# иначе правка будет уезжать в кластер и не применяться, а выглядеть это будет
|
||||
# как «изменение не сработало».
|
||||
sarex_reload: false
|
||||
sarex_reload_timeout: 240s
|
||||
sarex_reload_workloads:
|
||||
# nginx главного фронтенда: apps/django/aero/nginx-configmap.yaml. Здесь
|
||||
# маршруты на микрофронтенды workspaces и workflows и подмена
|
||||
# /static/config.json, которой выключается Zitadel.
|
||||
- namespace: django
|
||||
deployment: frontend
|
||||
why: nginx-configmap
|
||||
|
||||
# --- GitOps-подложка контура (k3s + gitea + vault + flux) -------------------
|
||||
# Параметры gitea и Flux. Попадают в .env (их читает docker-compose) — менять
|
||||
# нужно здесь, а не в .env.example, иначе перезапишется при следующем деплое.
|
||||
@ -309,8 +331,11 @@ vault_app_secrets:
|
||||
# собирает из этих ключей одну переменную S3_JSON_SETTINGS и читает endpoint
|
||||
# ВЛОЖЕННЫМ ключом .Data.data.client.endpoint — отсюда лишний уровень client.
|
||||
#
|
||||
# Бакет measurements зашит в том же шаблоне и заводится Job'ом
|
||||
# infrastructure/minio/aero/buckets-job.yaml.
|
||||
# Бакет — ОБЩЕЕ медиахранилище контура, то же, куда пишет django и откуда
|
||||
# раздаёт s3-proxy на маршруте /media/. В base у measurements имя бакета
|
||||
# зашито в самом vault-шаблоне ("buckets":["measurements"]), из-за чего он
|
||||
# складывал файлы отдельно и ссылка, отданная через django, вела бы в пустоту.
|
||||
# Шаблон переопределён в apps/measurements/aero, чтобы имя читалось отсюда.
|
||||
#
|
||||
# Отдельного пользователя MinIO нет — тот же временный компромисс, что и у
|
||||
# django: берём root-креды.
|
||||
@ -318,6 +343,7 @@ vault_app_secrets:
|
||||
data:
|
||||
client:
|
||||
endpoint: http://minio.minio.svc.cluster.local:9000
|
||||
bucket: "{{ sarex_django_s3_bucket }}"
|
||||
access_key: "{{ sarex_minio_k8s_user }}"
|
||||
secret_key: "{{ sarex_secrets.SAREX_MINIO_ROOT_PASSWORD }}"
|
||||
# Учётка администратора платформы. Её разбирает не приложение, а стартовый
|
||||
|
||||
@ -194,6 +194,14 @@
|
||||
when: aero_platform_up | bool
|
||||
tags: [platform]
|
||||
|
||||
# --- Перекат нагрузок с изменённой конфигурацией --------------------------
|
||||
# Только по тегу reload: правка ConfigMap сама под не перезапускает, а делать
|
||||
# это на каждом прогоне нельзя. Обоснование — в шапке reload.yml.
|
||||
- name: Перекатить нагрузки с изменённой конфигурацией
|
||||
ansible.builtin.include_tasks: reload.yml
|
||||
when: sarex_reload | bool
|
||||
tags: [reload]
|
||||
|
||||
# --- Поднять сервисы приложения ------------------------------------------
|
||||
- name: Поднять сервисы приложения (docker compose up -d)
|
||||
ansible.builtin.command:
|
||||
|
||||
41
aero/roles/sarex_stack/tasks/reload.yml
Normal file
41
aero/roles/sarex_stack/tasks/reload.yml
Normal file
@ -0,0 +1,41 @@
|
||||
---
|
||||
# Перекат нагрузок, которые не перезапускаются сами при правке конфигурации.
|
||||
#
|
||||
# ЗАЧЕМ ЭТО ОТДЕЛЬНАЯ ЗАДАЧА. Flux обновляет ConfigMap в кластере за пару минут,
|
||||
# но под продолжает работать со старым содержимым: у релизов universal-chart в
|
||||
# шаблоне пода нет контрольной суммы конфига, поэтому спецификация не меняется
|
||||
# и Kubernetes не видит причин пересоздавать под. Всё, что задаётся через
|
||||
# ConfigMap, применяется только после явного переката.
|
||||
#
|
||||
# Так это выглядит на практике: правишь nginx.conf, Flux рапортует Applied
|
||||
# revision, проверяешь — поведение старое. Легко принять за «правка не поехала»
|
||||
# и пойти искать несуществующую ошибку. Дважды так и было: сначала с порядком
|
||||
# set/rewrite, потом с auth_type.
|
||||
#
|
||||
# ПОЧЕМУ НЕ ДЕКЛАРАТИВНО. Правильное лечение — аннотация с хешем конфига в
|
||||
# шаблоне пода, тогда изменение ConfigMap меняет спецификацию и перекат
|
||||
# происходит сам. Здесь так не выходит: имя ConfigMap чарту передаётся строкой,
|
||||
# монтирование он делает сам, и посчитать хеш на этапе kustomize нечем —
|
||||
# configMapGenerator переименовал бы ресурс, но ссылку внутри чарта, который
|
||||
# рендерится уже в кластере, не поправил бы. Так что действие остаётся
|
||||
# императивным, и его место — здесь, а не в чьей-то памяти.
|
||||
#
|
||||
# ЗАПУСК ТОЛЬКО ЯВНЫЙ. Задача не выполняется при обычном прогоне: перекат
|
||||
# нагрузок посреди деплоя — не то, что должно случаться само.
|
||||
# uv run poe reload
|
||||
# либо точечно:
|
||||
# uv run poe reload -- -e "sarex_reload_workloads=[{'namespace':'django','deployment':'frontend'}]"
|
||||
|
||||
- name: Перекатить нагрузки с изменённой конфигурацией
|
||||
ansible.builtin.shell:
|
||||
cmd: >-
|
||||
{{ compose_cmd }} exec -T k3s-server sh -ec '
|
||||
kubectl -n {{ item.namespace }} rollout restart deploy/{{ item.deployment }}
|
||||
kubectl -n {{ item.namespace }} rollout status deploy/{{ item.deployment }} --timeout={{ sarex_reload_timeout }}
|
||||
'
|
||||
chdir: "{{ deploy_dir }}"
|
||||
loop: "{{ sarex_reload_workloads }}"
|
||||
loop_control:
|
||||
label: "{{ item.namespace }}/{{ item.deployment }} — {{ item.why | default('правка конфигурации') }}"
|
||||
changed_when: true
|
||||
tags: [reload]
|
||||
@ -19,8 +19,23 @@ patches:
|
||||
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: имя зашито в шаблоне
|
||||
# аннотации, и без готового бакета приложение не поднимется.
|
||||
# S3: бакет берём из секрета, а не из шаблона.
|
||||
#
|
||||
# В base имя бакета ЗАШИТО прямо в vault-шаблоне — "buckets":["measurements"].
|
||||
# Из-за этого measurements складывал файлы в собственный бакет, тогда как
|
||||
# медиахранилище контура одно и называется sarex-media-storage: туда пишет
|
||||
# django (S3_BUCKET) и оттуда же раздаёт s3-proxy на маршруте /media/.
|
||||
# Разные бакеты означали, что ссылка на файл измерения, отданная через
|
||||
# django, вела бы в пустоту.
|
||||
#
|
||||
# Endpoint в base уже приезжает из секрета (.Data.data.client.endpoint) —
|
||||
# достраиваем до той же схемы и бакет, чтобы имя задавалось в ОДНОМ месте
|
||||
# (vault_app_secrets в aero/roles/sarex_stack/defaults/main.yml), а не
|
||||
# дублировалось в манифесте. Заменить можно только аннотацию целиком:
|
||||
# значение зашито внутри шаблона, через values его не перекрыть.
|
||||
- op: replace
|
||||
path: /spec/values/services/backend/podAnnotations/_default/vault.hashicorp.com~1agent-inject-template-measurements-s3
|
||||
value: |-
|
||||
{{- with secret "secrets/data/minio/apps/measurements" -}}
|
||||
S3_JSON_SETTINGS='{"host":"{{ index .Data.data.client "endpoint" }}","login":"{{ index .Data.data "access_key" }}","password":"{{ index .Data.data "secret_key" }}","verify":false,"buckets":["{{ index .Data.data "bucket" }}"]}'
|
||||
{{- end -}}
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
---
|
||||
# Заведение бакетов. Чарт MinIO этого не умеет — форк не принимает ни buckets,
|
||||
# ни provisioning, — а приложения ждут бакеты готовыми: django падает на
|
||||
# загрузке файлов, measurements — на старте, потому что имя бакета зашито в
|
||||
# его vault-шаблоне.
|
||||
# ни provisioning, — а приложения ждут бакет готовым: django падает на загрузке
|
||||
# файлов, measurements — на старте, если бакета из его vault-шаблона нет.
|
||||
#
|
||||
# До этого Job'а бакеты заводились руками через mc. Такой бакет не переживает
|
||||
# пересоздание контура и не виден в репозитории: развернув всё с нуля, ты
|
||||
@ -66,7 +65,15 @@ spec:
|
||||
sleep 5
|
||||
done
|
||||
|
||||
for b in sarex-media-storage measurements; do
|
||||
# Бакет в контуре ОДИН: в него пишет django, из него раздаёт
|
||||
# s3-proxy на маршруте /media/, туда же переведён measurements.
|
||||
# Раньше у measurements в vault-шаблоне был зашит собственный
|
||||
# бакет, и файл, положенный им, по ссылке из django не отдавался.
|
||||
#
|
||||
# Ранее созданный бакет measurements этой правкой НЕ удаляется:
|
||||
# Job умеет только mc mb --ignore-existing. Убирать его — отдельное
|
||||
# осознанное решение, здесь мы лишь перестаём его заводить.
|
||||
for b in sarex-media-storage; do
|
||||
mc mb --ignore-existing "contour/$b"
|
||||
echo "бакет $b готов"
|
||||
done
|
||||
|
||||
Loading…
Reference in New Issue
Block a user