iac/aero/roles/sarex_stack/tasks/platform.yml
emelinda 75d1fba14a Compose: убран прикладной стек — он давно переехал в k3s
В docker-compose.yaml описывались 25 сервисов, а на хосте существовали
контейнеры только для 9. Остальные 16 — django, celery, frontend, s3-proxy,
processing-api/frontend, engine, measurements, nginx и их зависимости
(postgres, redis, rabbitmq, minio с init-контейнерами) — развёрнуты в k3s и
описаны в apps/ и infrastructure/. Дубликат не просто лежал мёртвым грузом,
а расходился с кластером и вводил в заблуждение.

Что это был именно мёртвый груз, а не «выключенный на время» стек:

  * контейнеров не существовало вовсе — не Exited, а не создавались;
  * именованных томов sarex-postgres-data, sarex-redis-data,
    sarex-rabbitmq-data, sarex-minio-data в docker volume ls нет;
  * стек был взаимно несовместим: nginx публиковал 80/443, те же порты
    публикует k3s-server (внутри его контейнера на них сидит istio
    ingressgateway), и docker compose up nginx упал бы на bind;
  * подъём был выключен по умолчанию (sarex_compose_up: false).

Заодно убрано всё, что обслуживало только удалённые сервисы:

  * sarex_services, sarex_compose_up, задача up и poe-таски stack/up;
  * оба handler'а (пересоздание nginx/backend/celery) — файл handlers
    остался пустым и удалён;
  * генерация самоподписанного сертификата и cert_dir: TLS выписывает
    cert-manager внутри кластера, верхнего nginx больше нет;
  * каталоги nginx/, backend/, engine/ и задачи их копирования;
  * k3s/manifests/processing — DNS-мост на IP compose-postgres/minio,
    которых больше не существует (в кластере он и не был создан).

poe install теперь идёт через platform, а не через удалённый stack — это
заодно чинит старую дыру, из-за которой install не поднимал подложку.

Проверено: docker compose config отдаёт ровно 9 сервисов, совпадающих с
docker ps на aero-01; ansible-lint новых замечаний не даёт.
2026-08-10 12:55:04 +03:00

132 lines
7.4 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.

---
# Подъём GitOps-подложки контура: k3s + gitea + vault + bootstrap FluxCD.
# Это единственное, что поднимается через docker compose. Прикладной стек
# разворачивает Flux внутри k3s по манифестам из apps/ и infrastructure/ —
# compose его больше не описывает.
#
# Порядок важен и поэтому разбит на две волны: flux-bootstrap монтирует
# ./k3s/kubeconfig.yaml, который k3s-server создаёт только при первом старте.
# Если поднять всё одной командой, docker может создать на месте отсутствующего
# файла директорию, и bootstrap упадёт с невнятной ошибкой.
- name: Волна 1 — поднять k3s-server и gitea
ansible.builtin.command:
cmd: "{{ compose_cmd }} up -d {{ aero_platform_services_wave1 | join(' ') }}"
chdir: "{{ deploy_dir }}"
changed_when: true
- name: Дождаться kubeconfig от k3s-server
ansible.builtin.wait_for:
path: "{{ deploy_dir }}/k3s/kubeconfig.yaml"
state: present
timeout: "{{ aero_kubeconfig_timeout }}"
# Пустой файл означает, что k3s-server ещё дописывает kubeconfig. Без этой
# проверки flux-bootstrap может стартовать с нулевым конфигом.
- name: Убедиться, что kubeconfig не пустой
ansible.builtin.wait_for:
path: "{{ deploy_dir }}/k3s/kubeconfig.yaml"
search_regex: "clusters:"
timeout: 60
# Секреты реестра — до bootstrap: без yc-cr-auth в flux-system source-controller
# не сможет скачать ни один OCI-чарт, и вся первая волна инфраструктуры встанет.
- name: Создать секреты доступа к реестру в кластере
ansible.builtin.include_tasks: registry-secrets.yml
# Секреты-файлы для подов, которые создаёт сам движок workflows. Идут сразу за
# секретами реестра: намеренно ДО Flux, потому что namespace задач манифест
# создаёт сам — ждать слой apps незачем.
- name: Создать секреты-файлы для подов задач
ansible.builtin.include_tasks: app-secrets.yml
- name: Волна 2 — gitea-init, flux-k8s-init и vault(+init)
ansible.builtin.command:
cmd: "{{ compose_cmd }} up -d {{ aero_platform_services_wave2 | join(' ') }}"
chdir: "{{ deploy_dir }}"
changed_when: true
# vault-init инициализирует и распечатывает Vault в цикле с шагом 10 секунд,
# поэтому сразу после `up -d` root-токена ещё нет. Он нужен следующему шагу,
# который настраивает auth/kubernetes.
- name: Дождаться инициализации Vault (появления root-токена)
ansible.builtin.command:
cmd: "{{ compose_cmd }} exec -T vault-init test -s /vault/init/root.token"
chdir: "{{ deploy_dir }}"
register: aero_vault_ready
until: aero_vault_ready.rc == 0
retries: 30
delay: 5
changed_when: false
# Метод auth/kubernetes: Vault учится валидировать токены подов k3s, а поды
# получают секреты файлами через vault-agent-injector (ставится Flux'ом).
- name: Настроить интеграцию Vault с k3s
ansible.builtin.include_tasks: vault-k8s.yml
tags: [vault]
# Наполнение gitea — ДО bootstrap: Flux начинает реконсиляцию сразу после
# привязки, и репозиторий к этому моменту должен содержать clusters/aero
# вместе со всем, на что тот ссылается.
- name: Синхронизировать репозиторий контура в gitea
ansible.builtin.include_tasks: gitea-sync.yml
tags: [sync]
- name: Волна 3 — bootstrap Flux
ansible.builtin.command:
cmd: "{{ compose_cmd }} up -d {{ aero_platform_services_wave3 | join(' ') }}"
chdir: "{{ deploy_dir }}"
changed_when: true
# flux-bootstrap одноразовый: успех = код 0. Забираем его явно, иначе ошибка
# bootstrap'а останется незамеченной — `compose up -d` о ней не сообщает.
#
# `docker compose wait` здесь не годится: для уже завершившегося контейнера он
# возвращает rc=1 и "no containers for project". Так как `up -d` не дожидается
# одноразового сервиса, состояние гоночное — поэтому опрашиваем `ps -a`,
# который корректно отвечает и для running, и для exited.
#
# Формат обёрнут в {% raw %}: это Go-шаблон docker'а, и без raw Jinja попыталась
# бы раскрыть {{.State.Status}} как свою переменную. Аргументы передаём списком —
# у `command` нет шелла, и строка со скобками разбилась бы по пробелу.
- name: Дождаться завершения flux-bootstrap
ansible.builtin.command:
argv:
- "{{ compose_cmd.split()[0] }}"
- inspect
- "-f"
- "{% raw %}{{.State.Status}} {{.State.ExitCode}}{% endraw %}"
- flux-bootstrap
register: aero_flux_bootstrap
changed_when: false
retries: 30
delay: 10
until: aero_flux_bootstrap.stdout | trim is not match('^running')
- name: Показать логи flux-bootstrap при ошибке
ansible.builtin.command:
cmd: "{{ compose_cmd }} logs --no-color --tail 50 flux-bootstrap"
chdir: "{{ deploy_dir }}"
register: aero_flux_logs
changed_when: false
when: aero_flux_bootstrap.stdout.split() | last != "0"
- name: Прервать деплой, если bootstrap не удался
ansible.builtin.fail:
msg: |
flux bootstrap завершился с кодом {{ aero_flux_bootstrap.stdout.split() | last }}.
Логи контейнера:
{{ aero_flux_logs.stdout | default('(недоступны)') }}
when: aero_flux_bootstrap.stdout.split() | last != "0"
- name: Итог
ansible.builtin.debug:
msg:
- "gitea: http://{{ ansible_host }}:3000 (пользователь {{ gitea_admin_user }}, пароль в aero/.secrets/{{ inventory_hostname }}/GITEA_ADMIN_PASSWORD)"
- "Flux реконсилирует {{ gitea_org }}/{{ gitea_repo }} → {{ aero_flux_path }}"
- "Слои: infra-controllers (istio, cert-manager, vault-injector, local-path, rabbitmq, minio) → infra-configs → apps"
- "Состояние Flux: docker compose exec k3s-server kubectl -n flux-system get kustomizations,helmreleases -A"
- "Dashboard: https://dashboard.{{ platform_domain }}"
- "RabbitMQ: https://rabbitmq.{{ platform_domain }} (пользователь {{ sarex_rabbitmq_k8s_user }}, пароль в aero/.secrets/{{ inventory_hostname }}/SAREX_RABBITMQ_PASSWORD)"
- "MinIO UI: https://minio.{{ platform_domain }}/console/ (пользователь {{ sarex_minio_k8s_user }}, пароль в aero/.secrets/{{ inventory_hostname }}/SAREX_MINIO_ROOT_PASSWORD)"