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 новых замечаний не даёт.
This commit is contained in:
parent
da2a0b33a7
commit
75d1fba14a
@ -50,8 +50,9 @@ uv run poe install
|
|||||||
```
|
```
|
||||||
|
|
||||||
Последовательность: `sync` → `galaxy` → **`provision`** (базовые пакеты + docker
|
Последовательность: `sync` → `galaxy` → **`provision`** (базовые пакеты + docker
|
||||||
и запуск службы) → **`stack`** (деплой конфигурации + `docker compose up -d`
|
и запуск службы) → **`platform`** (деплой конфигурации + подъём подложки:
|
||||||
сервисов приложения) → **`superuser`** (генерация и создание Django-админа).
|
k3s, gitea, vault, bootstrap Flux) → **`superuser`** (показать учётные данные
|
||||||
|
администратора платформы). Приложения после этого разворачивает Flux сам.
|
||||||
Перед запуском впишите хосты в [inventory.ini](inventory.ini) и убедитесь, что
|
Перед запуском впишите хосты в [inventory.ini](inventory.ini) и убедитесь, что
|
||||||
на control-node есть SSH-ключ и `~/.ssh/local/authorized_key.json` для входа в
|
на control-node есть SSH-ключ и `~/.ssh/local/authorized_key.json` для входа в
|
||||||
реестр.
|
реестр.
|
||||||
@ -62,19 +63,21 @@ uv run poe install
|
|||||||
| --- | --- |
|
| --- | --- |
|
||||||
| `uv run poe ping` | проверка SSH + sudo |
|
| `uv run poe ping` | проверка SSH + sudo |
|
||||||
| `uv run poe provision` | базовые пакеты + docker/containerd + запуск службы |
|
| `uv run poe provision` | базовые пакеты + docker/containerd + запуск службы |
|
||||||
| `uv run poe deploy` | деплой конфигурации: файлы, `.env`, сертификаты, `docker login` |
|
| `uv run poe deploy` | деплой конфигурации: файлы, `.env`, `docker login` |
|
||||||
| `uv run poe platform` | деплой + поднять GitOps-подложку (k3s + gitea + vault + Flux) |
|
| `uv run poe platform` | деплой + поднять GitOps-подложку (k3s + gitea + vault + Flux) |
|
||||||
| `uv run poe stack` | деплой + поднять стек (`docker compose up -d`) |
|
|
||||||
| `uv run poe gen-env` | только сгенерировать пароли и `.env` |
|
| `uv run poe gen-env` | только сгенерировать пароли и `.env` |
|
||||||
| `uv run poe login` | только `docker login` в реестр по ключу |
|
| `uv run poe login` | только `docker login` в реестр по ключу |
|
||||||
| `uv run poe superuser` | сгенерировать логин+пароль и создать Django-суперпользователя |
|
| `uv run poe superuser` | показать логин+пароль администратора платформы |
|
||||||
|
| `uv run poe dbsync` | досоздать базы, появившиеся после запуска СУБД |
|
||||||
|
| `uv run poe reload` | перекатить нагрузки, конфигурация которых в ConfigMap |
|
||||||
| `uv run poe flux-status` | состояние FluxCD в k3s |
|
| `uv run poe flux-status` | состояние FluxCD в k3s |
|
||||||
| `uv run poe vault-status` | состояние Vault (инициализирован / распечатан) |
|
| `uv run poe vault-status` | состояние Vault (инициализирован / распечатан) |
|
||||||
| `uv run poe check` / `deploy-check` | dry-run (`--check --diff`) |
|
| `uv run poe check` / `deploy-check` | dry-run (`--check --diff`) |
|
||||||
|
|
||||||
Поднимаемые сервисы задаются в `sarex_services` (роль `sarex_stack`) —
|
`docker compose` поднимает **только подложку** — k3s, gitea, vault и одноразовые
|
||||||
`postgres(+init)`, `redis`, `rabbitmq`, `minio(+init)`, `measurements`,
|
установщики. Прикладные сервисы разворачивает Flux внутри k3s по манифестам из
|
||||||
`backend`, `celery`, `frontend`, `nginx` (k3s/gitea/processing не поднимаются).
|
`apps/` и `infrastructure/`, и отдельной команды для них нет: достаточно
|
||||||
|
запушить изменения в репозиторий контура.
|
||||||
|
|
||||||
> `ANSIBLE_CONFIG` и `UV_LINK_MODE` заданы в `[tool.poe.env]` — на диске `C:`
|
> `ANSIBLE_CONFIG` и `UV_LINK_MODE` заданы в `[tool.poe.env]` — на диске `C:`
|
||||||
> (через `/mnt/c`) права `0777`, и ansible игнорирует `ansible.cfg` в
|
> (через `/mnt/c`) права `0777`, и ansible игнорирует `ansible.cfg` в
|
||||||
@ -87,20 +90,25 @@ uv run poe install
|
|||||||
раскаткой занимается FluxCD.
|
раскаткой занимается FluxCD.
|
||||||
|
|
||||||
```
|
```
|
||||||
docker compose k3s (4 ноды в контейнерах)
|
docker compose k3s (3 ноды в контейнерах)
|
||||||
├── k3s-server ──► нода ┐
|
├── k3s-server ──► нода ┐
|
||||||
├── k3s-worker-1..3 ──► ноды ├─► flux-system (controllers)
|
├── k3s-worker-1..2 ──► ноды ├─► flux-system (controllers)
|
||||||
├── gitea (172.28.0.12) ◄────── ┘ и всё, что опишем в clusters/aero
|
├── gitea (172.28.0.12) ◄────── ┘ и всё, что описано в clusters/aero:
|
||||||
│ └── infra/iac.git
|
│ └── infra/iac.git istio, cert-manager, postgresql, minio,
|
||||||
├── vault (+init)
|
├── vault (172.28.0.13) ◄─────────── rabbitmq, django, processing, workspaces,
|
||||||
|
│ └── vault-init (unseal-цикл) measurements, bim
|
||||||
|
├── gitea-init ──► админ, организация, пустой репозиторий
|
||||||
├── flux-k8s-init ──► namespace flux-system + Service-мост до gitea
|
├── flux-k8s-init ──► namespace flux-system + Service-мост до gitea
|
||||||
└── flux-bootstrap ──► ставит Flux в k3s и привязывает к gitea
|
└── flux-bootstrap ──► ставит Flux в k3s и привязывает к gitea
|
||||||
```
|
```
|
||||||
|
|
||||||
|
В compose — только это. Прикладные сервисы и их зависимости (СУБД, очереди,
|
||||||
|
объектное хранилище) живут в k3s и описаны в `apps/` и `infrastructure/`.
|
||||||
|
|
||||||
**Мост до gitea.** Контроллеры Flux работают внутри k3s, где резолвит CoreDNS,
|
**Мост до gitea.** Контроллеры Flux работают внутри k3s, где резолвит CoreDNS,
|
||||||
а имён compose-сети там нет. Поэтому `flux-k8s-init` заводит в namespace
|
а имён compose-сети там нет. Поэтому `flux-k8s-init` заводит в namespace
|
||||||
`flux-system` Service без селектора + Endpoints на статический IP gitea — тем же
|
`flux-system` Service без селектора + Endpoints на статический IP gitea — тем же
|
||||||
приёмом, что `bridge-postgres`/`bridge-minio` для processing. Источник в
|
приёмом, каким заведён мост до Vault (`k3s/manifests/vault`). Источник в
|
||||||
`GitRepository` указан именем `gitea.flux-system.svc.cluster.local`, а адрес
|
`GitRepository` указан именем `gitea.flux-system.svc.cluster.local`, а адрес
|
||||||
задан ровно в одном месте — переменной `GITEA_BRIDGE_IP` (она же `ipv4_address`
|
задан ровно в одном месте — переменной `GITEA_BRIDGE_IP` (она же `ipv4_address`
|
||||||
сервиса `gitea`). Контейнер `flux-bootstrap` резолвит то же имя через
|
сервиса `gitea`). Контейнер `flux-bootstrap` резолвит то же имя через
|
||||||
@ -121,18 +129,18 @@ docker compose k3s (4 ноды в контейнерах)
|
|||||||
{{ deploy_dir }}/k3s-storage/
|
{{ deploy_dir }}/k3s-storage/
|
||||||
├── server/ ← PVC, севшие на k3s-server
|
├── server/ ← PVC, севшие на k3s-server
|
||||||
├── worker-1/
|
├── worker-1/
|
||||||
├── worker-2/
|
└── worker-2/
|
||||||
└── worker-3/
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Файлы лежат на хосте обычными каталогами: переживают пересоздание контейнера
|
Файлы лежат на хосте обычными каталогами: переживают пересоздание контейнера
|
||||||
k3s и `docker compose down -v`, бэкапятся штатными средствами.
|
k3s и `docker compose down -v`, бэкапятся штатными средствами.
|
||||||
|
|
||||||
> **Следствие для stateful-сервисов.** Хранилище **node-local**: PVC привязан к
|
> **Следствие для stateful-сервисов.** Хранилище **node-local**: PVC привязан к
|
||||||
> той ноде, где под запустился первым. При переезде postgres/redis/rabbitmq/minio
|
> той ноде, где под запустился первым. postgresql, minio и rabbitmq уже работают
|
||||||
> в k3s их нужно явно прибивать к конкретной ноде (`nodeSelector`), иначе данные
|
> в k3s, поэтому их данные лежат в каталоге той ноды, куда сел под, — потеря
|
||||||
> размажутся по четырём каталогам, а потеря ноды сделает том недоступным.
|
> ноды делает том недоступным, а `kubectl delete pod` с последующим переездом
|
||||||
> Бэкап должен покрывать все каталоги `k3s-storage/*`.
|
> на другую ноду выглядит как «база опустела». Бэкап должен покрывать все
|
||||||
|
> каталоги `k3s-storage/*`.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
uv run poe platform # поднять подложку
|
uv run poe platform # поднять подложку
|
||||||
@ -162,26 +170,14 @@ uv run poe flux-status # убедиться, что Flux реконсил
|
|||||||
остальные — в `aero/.secrets/<host>/`. Unseal-ключ и root-токен Vault лежат на
|
остальные — в `aero/.secrets/<host>/`. Unseal-ключ и root-токен Vault лежат на
|
||||||
отдельном docker-томе `sarex-vault-init` с правами `600` и **в git не попадают**.
|
отдельном docker-томе `sarex-vault-init` с правами `600` и **в git не попадают**.
|
||||||
|
|
||||||
#### Границы текущего этапа
|
### Развёртывание (роль `sarex_stack`)
|
||||||
|
|
||||||
Сделана только подложка. Осознанно **не** сделано:
|
Копирует `docker-compose.yaml`, конфигурацию Vault и k3s-манифесты DNS-мостов в
|
||||||
|
|
||||||
- Репозиторий в gitea содержит лишь `clusters/aero/flux-system` — то, что запушил
|
|
||||||
bootstrap. Наполнение (`apps/`, `infrastructure/`) и перенос прикладных сервисов
|
|
||||||
из compose в k3s — следующий этап.
|
|
||||||
- Vault поднят и распечатан, но **kubernetes auth не настроен**: для него нужен
|
|
||||||
Vault Agent Injector внутри k3s, а он приедет уже через Flux. Пока в Vault
|
|
||||||
можно только класть секреты, поды их ещё не читают.
|
|
||||||
- Прикладной стек (`sarex_services`) не тронут и продолжает работать в compose.
|
|
||||||
|
|
||||||
### Развёртывание sarex-стека (роль `sarex_stack`)
|
|
||||||
|
|
||||||
Копирует `docker-compose.yaml`, `nginx/templates` и `backend/uwsgi.ini` в
|
|
||||||
`/root/sarex`, рендерит `.env` из `.env.example` со **сгенерированными паролями**
|
`/root/sarex`, рендерит `.env` из `.env.example` со **сгенерированными паролями**
|
||||||
и доменами `*.sarex.local.lonsdaleites.ru`, генерирует самоподписанный
|
и доменами `*.sarex.local.lonsdaleites.ru`, логинится в реестр, кладёт секреты в
|
||||||
TLS-сертификат на все три домена (`nginx/certs/selfsigned.{crt,key}`), логинится
|
Vault и поднимает подложку тремя волнами (`uv run poe platform`). Дальше за дело
|
||||||
в реестр и (при `sarex_compose_up=true`) поднимает сервисы приложения.
|
берётся Flux: базы, бакеты, очереди и сами приложения появляются в k3s из
|
||||||
Роли/базы и MinIO-бакеты создаются одноразовыми `postgres-init`/`minio-init`.
|
`apps/` и `infrastructure/`.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
uv run ansible-playbook deploy.yml --check --diff # dry-run
|
uv run ansible-playbook deploy.yml --check --diff # dry-run
|
||||||
@ -196,11 +192,13 @@ uv run ansible-playbook deploy.yml # подготовка фа
|
|||||||
uv run poe gen-env # сгенерировать/обновить .env
|
uv run poe gen-env # сгенерировать/обновить .env
|
||||||
rm -rf .secrets/<host> && uv run poe gen-env # перегенерировать пароли заново
|
rm -rf .secrets/<host> && uv run poe gen-env # перегенерировать пароли заново
|
||||||
```
|
```
|
||||||
- Стек по умолчанию **не поднимается** (`sarex_compose_up: false`). Образы —
|
- Образы приложений приватные (`cr.yandex`), поэтому нужен `docker login` —
|
||||||
приватные (`cr.yandex`), поэтому сперва `docker login cr.yandex` на хосте,
|
его делает `uv run poe login`, а в кластер доступ приезжает секретами
|
||||||
затем `cd /root/sarex && docker compose up -d` (или прогон с
|
`regcred`/`yc-cr-auth` (`registry_secrets` в роли).
|
||||||
`-e sarex_compose_up=true`).
|
|
||||||
- Домены нужно завести в DNS/hosts, чтобы они резолвились на хост.
|
- Домены нужно завести в DNS/hosts, чтобы они резолвились на хост.
|
||||||
|
- TLS-сертификат выписывает cert-manager внутри кластера
|
||||||
|
(`infrastructure/istio-config/aero`); самоподписанного сертификата на хосте
|
||||||
|
больше нет — он был нужен верхнему nginx, а тот заменён istio ingressgateway.
|
||||||
|
|
||||||
### Galaxy-коллекции (опционально)
|
### Galaxy-коллекции (опционально)
|
||||||
|
|
||||||
|
|||||||
@ -34,8 +34,6 @@ check = "ansible-playbook site.yml --check --diff"
|
|||||||
# Деплой конфигурации: файлы, .env с паролями, сертификаты, docker login
|
# Деплой конфигурации: файлы, .env с паролями, сертификаты, docker login
|
||||||
deploy = "ansible-playbook deploy.yml"
|
deploy = "ansible-playbook deploy.yml"
|
||||||
deploy-check = "ansible-playbook deploy.yml --check --diff"
|
deploy-check = "ansible-playbook deploy.yml --check --diff"
|
||||||
# Деплой + поднять стек приложения (docker compose up -d)
|
|
||||||
stack = "ansible-playbook deploy.yml -e sarex_compose_up=true"
|
|
||||||
# Деплой + поднять GitOps-подложку: k3s + gitea + vault + bootstrap FluxCD.
|
# Деплой + поднять GitOps-подложку: k3s + gitea + vault + bootstrap FluxCD.
|
||||||
# Без --tags намеренно: подложке нужны .env, docker-compose.yaml и vault/config,
|
# Без --tags намеренно: подложке нужны .env, docker-compose.yaml и vault/config,
|
||||||
# которые кладут нетегированные задачи роли (при --tags они были бы пропущены).
|
# которые кладут нетегированные задачи роли (при --tags они были бы пропущены).
|
||||||
@ -60,9 +58,6 @@ dbsync = "ansible-playbook deploy.yml -e sarex_dbsync=true --tags dbsync"
|
|||||||
lint = "ansible-lint"
|
lint = "ansible-lint"
|
||||||
|
|
||||||
# --- Операционные задачи на хосте (без полного деплоя) ----------------------
|
# --- Операционные задачи на хосте (без полного деплоя) ----------------------
|
||||||
# Поднять/пересоздать сервисы приложения (docker compose up -d sarex_services).
|
|
||||||
# Только тег up: не трогает файлы/.env/сертификаты/login, лишь применяет стек.
|
|
||||||
up = "ansible-playbook deploy.yml -e sarex_compose_up=true --tags up"
|
|
||||||
|
|
||||||
[tool.poe.tasks.ps]
|
[tool.poe.tasks.ps]
|
||||||
cmd = "ansible docker_hosts -m ansible.builtin.shell -a 'docker compose ps chdir=/root/sarex'"
|
cmd = "ansible docker_hosts -m ansible.builtin.shell -a 'docker compose ps chdir=/root/sarex'"
|
||||||
@ -108,6 +103,7 @@ required = true
|
|||||||
[tool.poe.tasks.setup]
|
[tool.poe.tasks.setup]
|
||||||
sequence = ["sync", "galaxy"]
|
sequence = ["sync", "galaxy"]
|
||||||
|
|
||||||
# Установка с чистого листа: окружение → docker → деплой+стек → суперпользователь
|
# Установка с чистого листа: окружение → docker → подложка (k3s+gitea+vault+Flux,
|
||||||
|
# дальше приложения разворачивает Flux сам) → показать учётку администратора.
|
||||||
[tool.poe.tasks.install]
|
[tool.poe.tasks.install]
|
||||||
sequence = ["sync", "galaxy", "provision", "stack", "superuser"]
|
sequence = ["sync", "galaxy", "provision", "platform", "superuser"]
|
||||||
|
|||||||
@ -24,15 +24,15 @@ aero_kernel_modules:
|
|||||||
# Источник файлов — корень репозитория iac (playbook лежит в aero/)
|
# Источник файлов — корень репозитория iac (playbook лежит в aero/)
|
||||||
deploy_src_root: "{{ playbook_dir }}/.."
|
deploy_src_root: "{{ playbook_dir }}/.."
|
||||||
|
|
||||||
# Домены верхнего nginx (попадают в .env и в SAN сертификата)
|
# Домены контура. Сертификаты им выписывает cert-manager внутри кластера
|
||||||
|
# (infrastructure/istio-config/aero, Certificate contour-tls), самоподписанного
|
||||||
|
# сертификата на хосте больше нет — он был нужен верхнему nginx, а тот уехал в
|
||||||
|
# istio ingressgateway. Эти же имена продублированы в dnsNames сертификата;
|
||||||
|
# добавляешь домен — правь оба места.
|
||||||
platform_domain: sarex.local.lonsdaleites.ru
|
platform_domain: sarex.local.lonsdaleites.ru
|
||||||
admin_domain: admin.sarex.local.lonsdaleites.ru
|
admin_domain: admin.sarex.local.lonsdaleites.ru
|
||||||
minio_domain: minio.sarex.local.lonsdaleites.ru
|
minio_domain: minio.sarex.local.lonsdaleites.ru
|
||||||
|
|
||||||
# Самоподписанный TLS-сертификат
|
|
||||||
cert_days: 365
|
|
||||||
cert_dir: "{{ deploy_dir }}/nginx/certs"
|
|
||||||
|
|
||||||
# Переменные-пароли: им генерируются стойкие значения взамен слабых дефолтов.
|
# Переменные-пароли: им генерируются стойкие значения взамен слабых дефолтов.
|
||||||
sarex_secret_vars:
|
sarex_secret_vars:
|
||||||
- K3S_TOKEN
|
- K3S_TOKEN
|
||||||
@ -97,9 +97,6 @@ registry_secrets:
|
|||||||
# Содержимое то же, что у regcred, — доступ в тот же cr.yandex.
|
# Содержимое то же, что у regcred, — доступ в тот же cr.yandex.
|
||||||
- {name: dockerhub, namespace: processing}
|
- {name: dockerhub, namespace: processing}
|
||||||
|
|
||||||
# Поднимать стек (docker compose up -d). Требует запущенной службы docker и
|
|
||||||
# docker login в cr.yandex — по умолчанию выключено.
|
|
||||||
sarex_compose_up: false
|
|
||||||
compose_cmd: "docker compose"
|
compose_cmd: "docker compose"
|
||||||
|
|
||||||
# --- Перекат нагрузок после правки конфигурации -----------------------------
|
# --- Перекат нагрузок после правки конфигурации -----------------------------
|
||||||
@ -553,28 +550,6 @@ sarex_postgres_bim_user: bim
|
|||||||
# завести отдельно, иначе загрузка файлов будет падать.
|
# завести отдельно, иначе загрузка файлов будет падать.
|
||||||
sarex_django_s3_bucket: sarex-media-storage
|
sarex_django_s3_bucket: sarex-media-storage
|
||||||
|
|
||||||
# Сервисы приложения, поднимаемые при sarex_compose_up (depends_on тянет
|
|
||||||
# зависимости и порядок). k3s/gitea намеренно не поднимаем.
|
|
||||||
sarex_services:
|
|
||||||
# k3s + провижининг DNS-моста (нужны engine'у до старта)
|
|
||||||
- k3s-server
|
|
||||||
- processing-k8s-init
|
|
||||||
- postgres
|
|
||||||
- postgres-init
|
|
||||||
- redis
|
|
||||||
- rabbitmq
|
|
||||||
- minio
|
|
||||||
- minio-init
|
|
||||||
- measurements
|
|
||||||
- s3-proxy
|
|
||||||
- backend
|
|
||||||
- celery
|
|
||||||
- frontend
|
|
||||||
- processing-api
|
|
||||||
- processing-frontend
|
|
||||||
- engine
|
|
||||||
- nginx
|
|
||||||
|
|
||||||
# Namespace прикладного слоя django в k3s. Используется задачей создания
|
# Namespace прикладного слоя django в k3s. Используется задачей создания
|
||||||
# суперпользователя (tasks/main.yml) — backend переехал из compose в кластер.
|
# суперпользователя (tasks/main.yml) — backend переехал из compose в кластер.
|
||||||
django_namespace: django
|
django_namespace: django
|
||||||
|
|||||||
@ -1,20 +0,0 @@
|
|||||||
---
|
|
||||||
# Пересоздание контейнеров при изменении их bind-mount конфигов.
|
|
||||||
# docker compose up -d НЕ пересоздаёт контейнер, если поменялся только
|
|
||||||
# смонтированный файл (шаблон nginx, production.py) — контент тома он не
|
|
||||||
# отслеживает. Поэтому на изменение конфига форсим --force-recreate конкретного
|
|
||||||
# сервиса. Срабатывает только когда стек реально поднимается (sarex_compose_up),
|
|
||||||
# иначе на обычном deploy без up мы бы стартовали контейнеры.
|
|
||||||
- name: Recreate nginx
|
|
||||||
ansible.builtin.command:
|
|
||||||
cmd: "{{ compose_cmd }} up -d --force-recreate --no-deps nginx"
|
|
||||||
chdir: "{{ deploy_dir }}"
|
|
||||||
when: sarex_compose_up | bool
|
|
||||||
|
|
||||||
- name: Recreate backend and celery
|
|
||||||
# Оба монтируют ./backend/production.py (celery — ещё и через тот же файл),
|
|
||||||
# поэтому пересоздаём вместе.
|
|
||||||
ansible.builtin.command:
|
|
||||||
cmd: "{{ compose_cmd }} up -d --force-recreate --no-deps backend celery"
|
|
||||||
chdir: "{{ deploy_dir }}"
|
|
||||||
when: sarex_compose_up | bool
|
|
||||||
@ -28,41 +28,15 @@
|
|||||||
dest: "{{ deploy_dir }}/docker-compose.yaml"
|
dest: "{{ deploy_dir }}/docker-compose.yaml"
|
||||||
mode: "0640"
|
mode: "0640"
|
||||||
|
|
||||||
# nginx монтирует ./nginx/templates и ./nginx/certs — без шаблонов nginx не
|
# k3s-манифесты DNS-мостов: flux-system → gitea (монтирует flux-k8s-init) и
|
||||||
# стартует, поэтому копируем конфигурацию рядом с compose.
|
# vault → Vault в compose (применяет vault-k8s.yml). Оба нужны потому, что у
|
||||||
# Изменение шаблона → handler пересоздаёт nginx (envsubst рендерит на старте).
|
# кластера своя DNS и compose-имена в ней не резолвятся.
|
||||||
- name: Скопировать шаблоны nginx
|
- name: Скопировать k3s-манифесты (DNS-мосты gitea и vault)
|
||||||
ansible.builtin.copy:
|
|
||||||
src: "{{ deploy_src_root }}/nginx/templates/"
|
|
||||||
dest: "{{ deploy_dir }}/nginx/templates/"
|
|
||||||
mode: "0644"
|
|
||||||
notify: Recreate nginx
|
|
||||||
|
|
||||||
# backend монтирует ./backend/uwsgi.ini (http-socket + 4 воркера) и
|
|
||||||
# ./backend/production.py (классическая JWT-аутентификация).
|
|
||||||
# Изменение конфигов → handler пересоздаёт backend и celery.
|
|
||||||
- name: Скопировать конфиги backend (uwsgi.ini, production.py)
|
|
||||||
ansible.builtin.copy:
|
|
||||||
src: "{{ deploy_src_root }}/backend/"
|
|
||||||
dest: "{{ deploy_dir }}/backend/"
|
|
||||||
mode: "0644"
|
|
||||||
notify: Recreate backend and celery
|
|
||||||
|
|
||||||
# k3s-манифесты DNS-моста (namespace processing + Service/Endpoints postgres/minio).
|
|
||||||
# processing-k8s-init монтирует ./k3s/manifests/processing и применяет их kubectl'ом.
|
|
||||||
- name: Скопировать k3s-манифесты (DNS-мост processing)
|
|
||||||
ansible.builtin.copy:
|
ansible.builtin.copy:
|
||||||
src: "{{ deploy_src_root }}/k3s/manifests/"
|
src: "{{ deploy_src_root }}/k3s/manifests/"
|
||||||
dest: "{{ deploy_dir }}/k3s/manifests/"
|
dest: "{{ deploy_dir }}/k3s/manifests/"
|
||||||
mode: "0644"
|
mode: "0644"
|
||||||
|
|
||||||
# engine монтирует ./engine/yc-s3-service-account.json (доступ Job-подов к S3).
|
|
||||||
- name: Скопировать конфиги engine (S3 service-account)
|
|
||||||
ansible.builtin.copy:
|
|
||||||
src: "{{ deploy_src_root }}/engine/"
|
|
||||||
dest: "{{ deploy_dir }}/engine/"
|
|
||||||
mode: "0644"
|
|
||||||
|
|
||||||
# vault монтирует ./vault/config как :ro — без конфига сервер не стартует.
|
# vault монтирует ./vault/config как :ro — без конфига сервер не стартует.
|
||||||
- name: Скопировать конфигурацию Vault
|
- name: Скопировать конфигурацию Vault
|
||||||
ansible.builtin.copy:
|
ansible.builtin.copy:
|
||||||
@ -161,24 +135,6 @@
|
|||||||
no_log: true
|
no_log: true
|
||||||
tags: [env]
|
tags: [env]
|
||||||
|
|
||||||
# --- Самоподписанный TLS-сертификат для трёх доменов ----------------------
|
|
||||||
- name: Создать каталог для сертификатов
|
|
||||||
ansible.builtin.file:
|
|
||||||
path: "{{ cert_dir }}"
|
|
||||||
state: directory
|
|
||||||
mode: "0750"
|
|
||||||
|
|
||||||
- name: Сгенерировать самоподписанный сертификат (SAN на все домены)
|
|
||||||
ansible.builtin.shell:
|
|
||||||
# umask 077 → приватный ключ создаётся сразу с правами 0600
|
|
||||||
cmd: >-
|
|
||||||
umask 077 && openssl req -x509 -nodes -newkey rsa:2048 -days {{ cert_days }}
|
|
||||||
-keyout {{ cert_dir }}/selfsigned.key
|
|
||||||
-out {{ cert_dir }}/selfsigned.crt
|
|
||||||
-subj "/CN={{ platform_domain }}"
|
|
||||||
-addext "subjectAltName=DNS:{{ platform_domain }},DNS:{{ admin_domain }},DNS:{{ minio_domain }}"
|
|
||||||
creates: "{{ cert_dir }}/selfsigned.crt"
|
|
||||||
|
|
||||||
# --- Доступ к приватному реестру (docker на хосте + registries.yaml нод) ---
|
# --- Доступ к приватному реестру (docker на хосте + registries.yaml нод) ---
|
||||||
# Обязательно ДО подъёма k3s: registries.yaml монтируется в ноды, и k3s читает
|
# Обязательно ДО подъёма k3s: registries.yaml монтируется в ноды, и k3s читает
|
||||||
# его только при старте.
|
# его только при старте.
|
||||||
@ -209,15 +165,6 @@
|
|||||||
when: sarex_reload | bool
|
when: sarex_reload | bool
|
||||||
tags: [reload]
|
tags: [reload]
|
||||||
|
|
||||||
# --- Поднять сервисы приложения ------------------------------------------
|
|
||||||
- name: Поднять сервисы приложения (docker compose up -d)
|
|
||||||
ansible.builtin.command:
|
|
||||||
cmd: "{{ compose_cmd }} up -d {{ sarex_services | join(' ') }}"
|
|
||||||
chdir: "{{ deploy_dir }}"
|
|
||||||
when: sarex_compose_up | bool
|
|
||||||
changed_when: true
|
|
||||||
tags: [up]
|
|
||||||
|
|
||||||
# --- Django-суперпользователь ----------------------------------------------
|
# --- Django-суперпользователь ----------------------------------------------
|
||||||
# Самого создания здесь больше нет — его делает под backend при каждом старте
|
# Самого создания здесь больше нет — его делает под backend при каждом старте
|
||||||
# (apps/django/aero/kustomization.yaml, args стартового скрипта). Так учётка
|
# (apps/django/aero/kustomization.yaml, args стартового скрипта). Так учётка
|
||||||
|
|||||||
@ -1,7 +1,8 @@
|
|||||||
---
|
---
|
||||||
# Подъём GitOps-подложки контура: k3s + gitea + vault + bootstrap FluxCD.
|
# Подъём GitOps-подложки контура: k3s + gitea + vault + bootstrap FluxCD.
|
||||||
# Отделено от прикладного стека (sarex_services) намеренно: здесь только
|
# Это единственное, что поднимается через docker compose. Прикладной стек
|
||||||
# публичные образы, docker login в приватный реестр не требуется.
|
# разворачивает Flux внутри k3s по манифестам из apps/ и infrastructure/ —
|
||||||
|
# compose его больше не описывает.
|
||||||
#
|
#
|
||||||
# Порядок важен и поэтому разбит на две волны: flux-bootstrap монтирует
|
# Порядок важен и поэтому разбит на две волны: flux-bootstrap монтирует
|
||||||
# ./k3s/kubeconfig.yaml, который k3s-server создаёт только при первом старте.
|
# ./k3s/kubeconfig.yaml, который k3s-server создаёт только при первом старте.
|
||||||
|
|||||||
@ -1,141 +0,0 @@
|
|||||||
from .base import *
|
|
||||||
|
|
||||||
from logging.handlers import SysLogHandler
|
|
||||||
|
|
||||||
ALLOWED_HOSTS = env.list('ALLOWED_HOSTS')
|
|
||||||
|
|
||||||
FILE_UPLOAD_PERMISSIONS = 0o644
|
|
||||||
|
|
||||||
DEBUG = False
|
|
||||||
|
|
||||||
CSRF_COOKIE_SECURE = True
|
|
||||||
SESSION_COOKIE_SECURE = True
|
|
||||||
SECURE_SSL_REDIRECT = False
|
|
||||||
|
|
||||||
# STATIC_ROOT = env('STATIC_ROOT')
|
|
||||||
# MEDIA_ROOT = env('MEDIA_ROOT')
|
|
||||||
|
|
||||||
# --- Media / объектное хранилище S3 -----------------------------------------
|
|
||||||
# Файлы (ортофото, облака точек, вложения) складываются в S3/MinIO кастомным
|
|
||||||
# storage-бэкендом; иначе Django пишет их на локальный диск контейнера.
|
|
||||||
DEFAULT_FILE_STORAGE = 'sarex.core.storages.CustomS3Boto3Storage'
|
|
||||||
# CustomS3Boto3Storage.url() отдаёт абсолютный URL = HOST + MEDIA_URL + key.
|
|
||||||
# В base.py HOST захардкожен на https://lk.sarex.io — переопределяем на наш
|
|
||||||
# домен платформы (из SERVER_HOST env), иначе media-ссылки уйдут на чужой хост.
|
|
||||||
# Верхний nginx проксирует /media/ в s3-proxy (тот отдаёт объекты из бакета).
|
|
||||||
HOST = SERVER_HOST
|
|
||||||
|
|
||||||
# SECRET_KEY = env('SECRET_KEY')
|
|
||||||
SECRET_KEY = 't2=9+($2f%7ptsdy4!rby$)mcfl1l%o2e@vs^d(g&(wwi&%k1v'
|
|
||||||
|
|
||||||
# DATABASE CONFIGURATION START
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
POSTGRES_DATABASE = env('DJANGO_POSTGRES_DATABASE')
|
|
||||||
POSTGRES_USER = env('DJANGO_POSTGRES_USER')
|
|
||||||
POSTGRES_PASSWORD = env('DJANGO_POSTGRES_PASSWORD')
|
|
||||||
POSTGRES_HOST = env('DJANGO_POSTGRES_HOST')
|
|
||||||
POSTGRES_PORTS = env('DJANGO_POSTGRES_PORTS', default="5432")
|
|
||||||
|
|
||||||
DATABASES = {
|
|
||||||
'default': {
|
|
||||||
'ENGINE': 'django_prometheus.db.backends.postgresql',
|
|
||||||
'NAME': POSTGRES_DATABASE,
|
|
||||||
'USER': POSTGRES_USER,
|
|
||||||
'PASSWORD': POSTGRES_PASSWORD,
|
|
||||||
'HOST': POSTGRES_HOST,
|
|
||||||
'PORT': POSTGRES_PORTS,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# DATABASE CONFIGURATION END
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
LOGGING = {
|
|
||||||
'version': 1,
|
|
||||||
'disable_existing_loggers': False,
|
|
||||||
'filters': {
|
|
||||||
'require_debug_false': {
|
|
||||||
'()': 'django.utils.log.RequireDebugFalse'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
'formatters': {
|
|
||||||
'verbose': {
|
|
||||||
'format': '[contactor] %(levelname)s %(asctime)s %(message)s'
|
|
||||||
},
|
|
||||||
},
|
|
||||||
'handlers': {
|
|
||||||
# Send all messages to console
|
|
||||||
'console': {
|
|
||||||
'level': 'DEBUG',
|
|
||||||
'class': 'logging.StreamHandler',
|
|
||||||
},
|
|
||||||
# critical errors are logged to sentry
|
|
||||||
'sentry': {
|
|
||||||
'level': 'ERROR',
|
|
||||||
'filters': ['require_debug_false'],
|
|
||||||
'class': 'logging.StreamHandler',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
'loggers': {
|
|
||||||
# This is the "catch all" logger
|
|
||||||
'': {
|
|
||||||
'handlers': ['console', 'sentry'],
|
|
||||||
'level': 'DEBUG',
|
|
||||||
'propagate': False,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
COMPARATOR_SECTION = env("COMPARATOR_SECTION", default="sarex-production-storage")
|
|
||||||
|
|
||||||
SIMPLE_JWT = {
|
|
||||||
# 'ACCESS_TOKEN_LIFETIME': timedelta(minutes=5),
|
|
||||||
'ACCESS_TOKEN_LIFETIME': timedelta(hours=1),
|
|
||||||
'REFRESH_TOKEN_LIFETIME': timedelta(days=1),
|
|
||||||
'ROTATE_REFRESH_TOKENS': True,
|
|
||||||
'BLACKLIST_AFTER_ROTATION': False,
|
|
||||||
'UPDATE_LAST_LOGIN': False,
|
|
||||||
|
|
||||||
'ALGORITHM': 'RS512',
|
|
||||||
'SIGNING_KEY': env.str("JWT_PRIVATE_KEY").replace("\\n", "\n"),
|
|
||||||
'VERIFYING_KEY': env.str("JWT_PUBLIC_KEY").replace("\\n", "\n"),
|
|
||||||
'AUDIENCE': None,
|
|
||||||
'ISSUER': SIMPLE_JWT_ISSUER,
|
|
||||||
|
|
||||||
'AUTH_HEADER_TYPES': ('Bearer',),
|
|
||||||
'AUTH_HEADER_NAME': 'HTTP_AUTHORIZATION',
|
|
||||||
'USER_ID_FIELD': 'id',
|
|
||||||
'USER_ID_CLAIM': 'user_id',
|
|
||||||
|
|
||||||
'AUTH_TOKEN_CLASSES': ('rest_framework_simplejwt.tokens.AccessToken',),
|
|
||||||
'TOKEN_TYPE_CLAIM': 'token_type',
|
|
||||||
|
|
||||||
'JTI_CLAIM': 'jti',
|
|
||||||
|
|
||||||
'SLIDING_TOKEN_REFRESH_EXP_CLAIM': 'refresh_exp',
|
|
||||||
# 'SLIDING_TOKEN_LIFETIME': timedelta(minutes=5),
|
|
||||||
'SLIDING_TOKEN_LIFETIME': timedelta(hours=1),
|
|
||||||
'SLIDING_TOKEN_REFRESH_LIFETIME': timedelta(days=1),
|
|
||||||
}
|
|
||||||
|
|
||||||
os.environ["DJANGO_ALLOW_ASYNC_UNSAFE"] = "true"
|
|
||||||
|
|
||||||
COMPARISON_API_URL = f"{WORKFLOWSSETTINGS.host}/comparisons"
|
|
||||||
DOCUMENTATION_API_URL = f"{WORKFLOWSSETTINGS.host}/documentations"
|
|
||||||
PDM_FILES_API_URL = f"{WORKFLOWSSETTINGS.host}/files"
|
|
||||||
|
|
||||||
# --- Override для self-hosted (auth_type=original) --------------------------
|
|
||||||
# В base.py классическая SimpleJWT-аутентификация закомментирована (образ собран
|
|
||||||
# под Zitadel), поэтому Bearer-токен от /api/token/ отвергается защищёнными
|
|
||||||
# эндпоинтами. Возвращаем её первым классом; Session — для админки.
|
|
||||||
REST_FRAMEWORK["DEFAULT_AUTHENTICATION_CLASSES"] = [
|
|
||||||
"rest_framework_simplejwt.authentication.JWTAuthentication",
|
|
||||||
"rest_framework.authentication.SessionAuthentication",
|
|
||||||
"rest_framework.authentication.BasicAuthentication",
|
|
||||||
]
|
|
||||||
|
|
||||||
# --- Оставляем в сайдбаре только модуль «Съёмки» ----------------------------
|
|
||||||
# Фронт показывает модуль, только если его uri есть в modules_list (= SAREX_MODULES).
|
|
||||||
SAREX_MODULES = [
|
|
||||||
{"name": "Съёмки", "uri": "/targets"},
|
|
||||||
]
|
|
||||||
@ -1,24 +0,0 @@
|
|||||||
[uwsgi]
|
|
||||||
log-format = {"time": "%(time)", "method": "%(method)", "uri": "%(uri)", "status": "%(status)", "size": "%(size)", "addr": "%(addr)", "user": "%(user)", "proto": "%(proto)", "user_agent": "%(uagent)", "referer": "%(referer)", "trace_id": "%(trace_id)", "span_id": "%(span_id)"}
|
|
||||||
module = config.wsgi:application
|
|
||||||
DJANGO_SETTINGS_MODULE = config.settings.production
|
|
||||||
# HTTP-протокол вместо uwsgi (nginx проксирует через proxy_pass, доступен напрямую)
|
|
||||||
http-socket = 0.0.0.0:8000
|
|
||||||
processes = 4
|
|
||||||
master = true
|
|
||||||
vacuum = true
|
|
||||||
die-on-term = true
|
|
||||||
enable-threads = true
|
|
||||||
buffer-size = 65535
|
|
||||||
stats = :3031
|
|
||||||
stats-http = true
|
|
||||||
memory-report = true
|
|
||||||
lazy-apps = true
|
|
||||||
listen = 1024
|
|
||||||
disable-write-exception= 0
|
|
||||||
harakiri = 300
|
|
||||||
socket-timeout = 300
|
|
||||||
chunked-input-timeout = 300
|
|
||||||
http-timeout = 300
|
|
||||||
worker-reload-mercy = 240
|
|
||||||
mule-reload-mercy = 240
|
|
||||||
@ -1,4 +1,23 @@
|
|||||||
# Общая конфигурация воркер-нод k3s — см. сервисы k3s-worker-1..3.
|
# GitOps-ПОДЛОЖКА КОНТУРА, И ТОЛЬКО ОНА.
|
||||||
|
#
|
||||||
|
# Здесь описано ровно то, что не может жить внутри кластера, потому что кластер
|
||||||
|
# на этом и стоит: сами ноды k3s, git-репозиторий-источник (gitea), хранилище
|
||||||
|
# секретов (vault) и одноразовые установщики, доводящие всё это до состояния,
|
||||||
|
# в котором за дело берётся Flux.
|
||||||
|
#
|
||||||
|
# ПРИКЛАДНОГО СТЕКА ЗДЕСЬ НЕТ И БЫТЬ НЕ ДОЛЖНО. Django, celery, frontend,
|
||||||
|
# processing, measurements, bim, а также postgres, redis, rabbitmq и minio
|
||||||
|
# развёрнуты в k3s и описаны декларативно в apps/ и infrastructure/; источник
|
||||||
|
# правды для них — репозиторий в gitea, а не этот файл. Раньше они дублировались
|
||||||
|
# и здесь; дубликат удалён, потому что расходился с кластером и вводил в
|
||||||
|
# заблуждение. Возвращать их сюда не надо: nginx конфликтовал бы с k3s-server за
|
||||||
|
# порты 80/443 (их занимает istio ingressgateway внутри контейнера ноды), а
|
||||||
|
# вторая копия СУБД тихо разъехалась бы с той, где лежат данные.
|
||||||
|
#
|
||||||
|
# Поднимает всё это ansible-роль sarex_stack тремя волнами — см. aero/roles/
|
||||||
|
# sarex_stack/tasks/platform.yml, порядок там значим.
|
||||||
|
|
||||||
|
# Общая конфигурация воркер-нод k3s — см. сервисы k3s-worker-1..2.
|
||||||
# У каждой ноды СВОЙ том состояния и СВОЙ каталог PVC-хранилища: провижинер
|
# У каждой ноды СВОЙ том состояния и СВОЙ каталог PVC-хранилища: провижинер
|
||||||
# local-path кладёт данные на ту ноду, где под запустился первым, и через
|
# local-path кладёт данные на ту ноду, где под запустился первым, и через
|
||||||
# nodeAffinity навсегда привязывает к ней PV.
|
# nodeAffinity навсегда привязывает к ней PV.
|
||||||
@ -59,7 +78,8 @@ services:
|
|||||||
- "80:80" # ingress http
|
- "80:80" # ingress http
|
||||||
- "443:443" # ingress https
|
- "443:443" # ingress https
|
||||||
# kube-apiserver наружу НЕ публикуем: доступ к нему — только изнутри
|
# kube-apiserver наружу НЕ публикуем: доступ к нему — только изнутри
|
||||||
# compose-сети (engine ходит по KUBE_ADDR=https://k3s-server:6443).
|
# compose-сети, по имени k3s-server:6443 (так к нему ходят flux-bootstrap
|
||||||
|
# и одноразовые init-контейнеры).
|
||||||
# Если понадобится внешний kubectl — раскомментируй и ОБЯЗАТЕЛЬНО
|
# Если понадобится внешний kubectl — раскомментируй и ОБЯЗАТЕЛЬНО
|
||||||
# ограничь фаерволом до доверенных адресов.
|
# ограничь фаерволом до доверенных адресов.
|
||||||
# - "6443:6443"
|
# - "6443:6443"
|
||||||
@ -112,26 +132,6 @@ services:
|
|||||||
- ./k3s-storage/worker-2:/var/lib/rancher/k3s/storage:z
|
- ./k3s-storage/worker-2:/var/lib/rancher/k3s/storage:z
|
||||||
- ./k3s/registries.yaml:/etc/rancher/k3s/registries.yaml:ro,z
|
- ./k3s/registries.yaml:/etc/rancher/k3s/registries.yaml:ro,z
|
||||||
|
|
||||||
# Одноразовый провижининг k3s: namespace processing + DNS-мост postgres/minio.
|
|
||||||
# Образ k3s содержит kubectl; server/tls перекрываем на k3s-server:6443
|
|
||||||
# (kubeconfig из /output даёт клиентские креды, адрес/TLS переопределяем флагами).
|
|
||||||
processing-k8s-init:
|
|
||||||
image: ${K3S_IMAGE:-rancher/k3s:v1.36.2-k3s1}
|
|
||||||
container_name: processing-k8s-init
|
|
||||||
restart: "no"
|
|
||||||
depends_on:
|
|
||||||
k3s-server:
|
|
||||||
condition: service_healthy
|
|
||||||
entrypoint: ["/bin/sh", "-ec"]
|
|
||||||
command:
|
|
||||||
- |
|
|
||||||
kubectl --kubeconfig /kube/config \
|
|
||||||
--server https://k3s-server:6443 --insecure-skip-tls-verify \
|
|
||||||
apply -f /manifests/
|
|
||||||
volumes:
|
|
||||||
- ./k3s/kubeconfig.yaml:/kube/config:ro,z
|
|
||||||
- ./k3s/manifests/processing:/manifests:ro,z
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# GitOps-подложка контура: gitea (источник) + vault (секреты) + flux (в k3s).
|
# GitOps-подложка контура: gitea (источник) + vault (секреты) + flux (в k3s).
|
||||||
# Порядок: gitea → gitea-init (админ/орг/репо) → flux-bootstrap (ставит Flux
|
# Порядок: gitea → gitea-init (админ/орг/репо) → flux-bootstrap (ставит Flux
|
||||||
@ -396,494 +396,6 @@ services:
|
|||||||
--allow-insecure-http \
|
--allow-insecure-http \
|
||||||
--interval=2m
|
--interval=2m
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
|
||||||
# Инфраструктурные зависимости apps/django (sarex-backend).
|
|
||||||
# Django деплоится в k3s и ходит сюда — про связность k3s→compose см. README.
|
|
||||||
# Креды/версии взяты из sarex-backend/docker-compose.yaml и apps/django/.env.example.
|
|
||||||
# ---------------------------------------------------------------------------
|
|
||||||
postgres:
|
|
||||||
image: ${POSTGRES_IMAGE:-postgres:12-alpine}
|
|
||||||
container_name: postgres
|
|
||||||
restart: unless-stopped
|
|
||||||
environment:
|
|
||||||
# суперпользователь (администрирование)
|
|
||||||
POSTGRES_DB: ${SAREX_POSTGRES_DB:-sarex_db}
|
|
||||||
POSTGRES_USER: ${SAREX_POSTGRES_USER:-sarex}
|
|
||||||
POSTGRES_PASSWORD: ${SAREX_POSTGRES_PASSWORD:-sarex}
|
|
||||||
# роли приложений с паролями — читаются init-скриптом 00-init.sh
|
|
||||||
DJANGO_DB: ${SAREX_POSTGRES_DB:-sarex_db}
|
|
||||||
DJANGO_DB_USER: ${SAREX_DJANGO_DB_USER:-django}
|
|
||||||
DJANGO_DB_PASSWORD: ${SAREX_DJANGO_DB_PASSWORD:-django-secret}
|
|
||||||
PROC_DB: ${SAREX_PROCESSING_DB:-workflow_db}
|
|
||||||
PROC_DB_USER: ${SAREX_PROCESSING_DB_USER:-processing}
|
|
||||||
PROC_DB_PASSWORD: ${SAREX_PROCESSING_DB_PASSWORD:-processing-secret}
|
|
||||||
volumes:
|
|
||||||
- sarex-postgres-data:/var/lib/postgresql/data
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD-SHELL", "pg_isready -U ${SAREX_POSTGRES_USER:-sarex} -d ${SAREX_POSTGRES_DB:-sarex_db}"]
|
|
||||||
interval: 10s
|
|
||||||
timeout: 5s
|
|
||||||
retries: 12
|
|
||||||
start_period: 10s
|
|
||||||
# Статический IP: на него ссылается k8s-Endpoints `postgres` (DNS-мост в k3s).
|
|
||||||
networks:
|
|
||||||
default:
|
|
||||||
ipv4_address: 172.28.0.10
|
|
||||||
|
|
||||||
# Одноразовый init: на каждое приложение заводит роль (LOGIN+пароль) и базу
|
|
||||||
# данных с этим владельцем. Идемпотентно (по образцу minio-init).
|
|
||||||
postgres-init:
|
|
||||||
image: ${POSTGRES_IMAGE:-postgres:12-alpine}
|
|
||||||
depends_on:
|
|
||||||
postgres:
|
|
||||||
condition: service_healthy
|
|
||||||
entrypoint:
|
|
||||||
- /bin/sh
|
|
||||||
- -c
|
|
||||||
- |
|
|
||||||
set -e
|
|
||||||
until psql -h postgres -U "$$SUPER_USER" -d "$$SUPER_DB" -c 'SELECT 1' >/dev/null 2>&1; do
|
|
||||||
echo 'waiting for postgres...'; sleep 2;
|
|
||||||
done
|
|
||||||
|
|
||||||
q() { psql -v ON_ERROR_STOP=1 -h postgres -U "$$SUPER_USER" -d "$$SUPER_DB" "$$@"; }
|
|
||||||
|
|
||||||
# provision <db> <user> <password>
|
|
||||||
provision() {
|
|
||||||
q -tc "SELECT 1 FROM pg_roles WHERE rolname='$$2'" | grep -q 1 \
|
|
||||||
|| q -c "CREATE ROLE \"$$2\" LOGIN PASSWORD '$$3'"
|
|
||||||
q -c "ALTER ROLE \"$$2\" WITH LOGIN PASSWORD '$$3'"
|
|
||||||
q -tc "SELECT 1 FROM pg_database WHERE datname='$$1'" | grep -q 1 \
|
|
||||||
|| q -c "CREATE DATABASE \"$$1\" OWNER \"$$2\""
|
|
||||||
q -c "ALTER DATABASE \"$$1\" OWNER TO \"$$2\""
|
|
||||||
q -c "GRANT ALL PRIVILEGES ON DATABASE \"$$1\" TO \"$$2\""
|
|
||||||
echo "db $$1 + user $$2 ready"
|
|
||||||
}
|
|
||||||
|
|
||||||
provision "$$DJANGO_DB" "$$DJANGO_USER" "$$DJANGO_PASSWORD"
|
|
||||||
provision "$$PROC_DB" "$$PROC_USER" "$$PROC_PASSWORD"
|
|
||||||
provision "$$BIM_DB" "$$BIM_USER" "$$BIM_PASSWORD"
|
|
||||||
provision "$$WORKSPACE_DB" "$$WORKSPACE_USER" "$$WORKSPACE_PASSWORD"
|
|
||||||
|
|
||||||
# Расширения PostgreSQL в базе django: CREATE EXTENSION может только
|
|
||||||
# суперпользователь. Django-миграции (CreateExtension) идут с IF NOT
|
|
||||||
# EXISTS → после этого станут no-op и не упадут на правах.
|
|
||||||
for ext in $$DJANGO_EXTENSIONS; do
|
|
||||||
q -c "CREATE EXTENSION IF NOT EXISTS \"$$ext\"" && echo "extension $$ext ready in $$DJANGO_DB"
|
|
||||||
done
|
|
||||||
|
|
||||||
# Расширения для processing (workflow_db) — ОТДЕЛЬНАЯ база, поэтому явно
|
|
||||||
# -d PROC_DB. Роль processing не суперпользователь → CREATE EXTENSION в
|
|
||||||
# её миграциях (uuid-ossp/ltree/hstore) падает; заводим суперпользователем.
|
|
||||||
for ext in $$PROC_EXTENSIONS; do
|
|
||||||
psql -v ON_ERROR_STOP=1 -h postgres -U "$$SUPER_USER" -d "$$PROC_DB" \
|
|
||||||
-c "CREATE EXTENSION IF NOT EXISTS \"$$ext\"" && echo "extension $$ext ready in $$PROC_DB"
|
|
||||||
done
|
|
||||||
environment:
|
|
||||||
PGPASSWORD: ${SAREX_POSTGRES_PASSWORD:-sarex}
|
|
||||||
SUPER_USER: ${SAREX_POSTGRES_USER:-sarex}
|
|
||||||
SUPER_DB: ${SAREX_POSTGRES_DB:-sarex_db}
|
|
||||||
# django (использует основную базу SAREX_POSTGRES_DB)
|
|
||||||
DJANGO_DB: ${SAREX_POSTGRES_DB:-sarex_db}
|
|
||||||
DJANGO_USER: ${SAREX_DJANGO_DB_USER:-django}
|
|
||||||
DJANGO_PASSWORD: ${SAREX_DJANGO_DB_PASSWORD:-django-secret}
|
|
||||||
DJANGO_EXTENSIONS: ${SAREX_DJANGO_DB_EXTENSIONS:-ltree}
|
|
||||||
# processing
|
|
||||||
PROC_DB: ${SAREX_PROCESSING_DB:-workflow_db}
|
|
||||||
PROC_USER: ${SAREX_PROCESSING_DB_USER:-processing}
|
|
||||||
PROC_PASSWORD: ${SAREX_PROCESSING_DB_PASSWORD:-processing-secret}
|
|
||||||
PROC_EXTENSIONS: ${SAREX_PROCESSING_DB_EXTENSIONS:-uuid-ossp ltree hstore}
|
|
||||||
# bim
|
|
||||||
BIM_DB: ${SAREX_BIM_DB:-bim_db}
|
|
||||||
BIM_USER: ${SAREX_BIM_DB_USER:-bim}
|
|
||||||
BIM_PASSWORD: ${SAREX_BIM_DB_PASSWORD:-bim-secret}
|
|
||||||
# workspace
|
|
||||||
WORKSPACE_DB: ${SAREX_WORKSPACE_DB:-workspace_db}
|
|
||||||
WORKSPACE_USER: ${SAREX_WORKSPACE_DB_USER:-workspace}
|
|
||||||
WORKSPACE_PASSWORD: ${SAREX_WORKSPACE_DB_PASSWORD:-workspace-secret}
|
|
||||||
restart: "no"
|
|
||||||
|
|
||||||
redis:
|
|
||||||
image: ${SAREX_REDIS_IMAGE:-cr.yandex/crp3ccidau046kdj8g9q/redis:7.0.10}
|
|
||||||
container_name: redis
|
|
||||||
restart: unless-stopped
|
|
||||||
# protected-mode no: redis только во внутренней docker-сети (порт наружу не
|
|
||||||
# публикуется), иначе бэкенд/celery из других контейнеров отбиваются "DENIED"
|
|
||||||
command: ["redis-server", "--save", "60", "1", "--loglevel", "warning", "--protected-mode", "no", "--stop-writes-on-bgsave-error", "no"]
|
|
||||||
volumes:
|
|
||||||
- sarex-redis-data:/data
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD", "redis-cli", "ping"]
|
|
||||||
interval: 10s
|
|
||||||
timeout: 5s
|
|
||||||
retries: 12
|
|
||||||
start_period: 5s
|
|
||||||
|
|
||||||
rabbitmq:
|
|
||||||
image: ${SAREX_RABBITMQ_IMAGE:-cr.yandex/crp3ccidau046kdj8g9q/rabbimtq:3.11.23}
|
|
||||||
container_name: rabbitmq
|
|
||||||
restart: unless-stopped
|
|
||||||
environment:
|
|
||||||
RABBITMQ_VHOST: ${SAREX_RABBITMQ_VHOST:-api}
|
|
||||||
RABBITMQ_USERNAME: ${SAREX_RABBITMQ_USER:-rabbit}
|
|
||||||
RABBITMQ_PASSWORD: ${SAREX_RABBITMQ_PASSWORD:-rabbit}
|
|
||||||
RABBITMQ_DISK_FREE_ABSOLUTE_LIMIT: 200MB
|
|
||||||
volumes:
|
|
||||||
- sarex-rabbitmq-data:/bitnami/rabbitmq/mnesia
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD", "rabbitmq-diagnostics", "-q", "ping"]
|
|
||||||
interval: 15s
|
|
||||||
timeout: 10s
|
|
||||||
retries: 12
|
|
||||||
start_period: 30s
|
|
||||||
|
|
||||||
minio:
|
|
||||||
image: ${SAREX_MINIO_IMAGE:-cr.yandex/crp3ccidau046kdj8g9q/minio:250724}
|
|
||||||
container_name: minio
|
|
||||||
restart: unless-stopped
|
|
||||||
command: ["server", "/data", "--console-address", ":9001"]
|
|
||||||
environment:
|
|
||||||
MINIO_ROOT_USER: ${SAREX_MINIO_ROOT_USER:-minioadmin}
|
|
||||||
MINIO_ROOT_PASSWORD: ${SAREX_MINIO_ROOT_PASSWORD:-minioadmin}
|
|
||||||
# Консоль отдаётся через верхний nginx с корня minio-домена
|
|
||||||
MINIO_BROWSER_REDIRECT_URL: ${SAREX_MINIO_CONSOLE_URL:-https://minio.sarex.local}
|
|
||||||
volumes:
|
|
||||||
- sarex-minio-data:/data
|
|
||||||
# Статический IP: на него ссылается k8s-Endpoints `minio` (DNS-мост в k3s).
|
|
||||||
networks:
|
|
||||||
default:
|
|
||||||
ipv4_address: 172.28.0.11
|
|
||||||
|
|
||||||
# Одноразовый init: ждёт MinIO и на каждое приложение заводит бакет +
|
|
||||||
# отдельного пользователя со scoped-политикой (доступ только к своему бакету).
|
|
||||||
minio-init:
|
|
||||||
image: ${SAREX_MC_IMAGE:-cr.yandex/crp3ccidau046kdj8g9q/mc:250724}
|
|
||||||
depends_on:
|
|
||||||
- minio
|
|
||||||
entrypoint:
|
|
||||||
- /bin/sh
|
|
||||||
- -c
|
|
||||||
- |
|
|
||||||
until mc alias set local http://minio:9000 "$$MINIO_ROOT_USER" "$$MINIO_ROOT_PASSWORD"; do
|
|
||||||
echo 'waiting for minio...'; sleep 2;
|
|
||||||
done
|
|
||||||
|
|
||||||
# provision <bucket> <user> <password> <policy>
|
|
||||||
provision() {
|
|
||||||
mc mb -p "local/$$1"
|
|
||||||
mc admin user add local "$$2" "$$3"
|
|
||||||
printf '{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Action":["s3:*"],"Resource":["arn:aws:s3:::%s","arn:aws:s3:::%s/*"]}]}' "$$1" "$$1" > /tmp/policy.json
|
|
||||||
mc admin policy create local "$$4" /tmp/policy.json || true
|
|
||||||
mc admin policy attach local "$$4" --user "$$2" || true
|
|
||||||
echo "bucket $$1 + user $$2 ready"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Единый бакет на все приложения (processing/measurements тоже сюда)
|
|
||||||
provision "$$MINIO_BUCKET" "$$MINIO_APP_USER" "$$MINIO_APP_PASSWORD" "$$MINIO_APP_POLICY"
|
|
||||||
environment:
|
|
||||||
MINIO_ROOT_USER: ${SAREX_MINIO_ROOT_USER:-minioadmin}
|
|
||||||
MINIO_ROOT_PASSWORD: ${SAREX_MINIO_ROOT_PASSWORD:-minioadmin}
|
|
||||||
# единый бакет/пользователь приложения
|
|
||||||
MINIO_BUCKET: ${SAREX_MINIO_BUCKET:-sarex-media-storage}
|
|
||||||
MINIO_APP_USER: ${SAREX_MINIO_APP_USER:-sarex-app}
|
|
||||||
MINIO_APP_PASSWORD: ${SAREX_MINIO_APP_PASSWORD:-sarex-app-secret}
|
|
||||||
MINIO_APP_POLICY: ${SAREX_MINIO_APP_POLICY:-sarex-app-rw}
|
|
||||||
restart: "no"
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
|
||||||
# Приложение sarex (backend + celery + frontend).
|
|
||||||
# Образы приватные (cr.yandex) — нужен `docker login cr.yandex`.
|
|
||||||
# Для локальной сборки backend раскомментируй build (репозиторий — соседний).
|
|
||||||
# ---------------------------------------------------------------------------
|
|
||||||
backend:
|
|
||||||
image: ${SAREX_BACKEND_IMAGE:-cr.yandex/crp3ccidau046kdj8g9q/backend:production_80d1d847}
|
|
||||||
# build:
|
|
||||||
# context: ../../generic/sarex-backend
|
|
||||||
# dockerfile: Dockerfile
|
|
||||||
container_name: sarex-backend
|
|
||||||
restart: unless-stopped
|
|
||||||
environment: &sarex-backend-env
|
|
||||||
ALLOWED_HOSTS: "*"
|
|
||||||
DJANGO_SETTINGS_MODULE: config.settings.production
|
|
||||||
JWT_PRIVATE_KEY: ${SAREX_JWT_PRIVATE_KEY:-JWT}
|
|
||||||
JWT_PUBLIC_KEY: ${SAREX_JWT_PUBLIC_KEY:-JPK}
|
|
||||||
DJANGO_POSTGRES_HOST: postgres
|
|
||||||
DJANGO_POSTGRES_DATABASE: ${SAREX_POSTGRES_DB:-sarex_db}
|
|
||||||
DJANGO_POSTGRES_USER: ${SAREX_DJANGO_DB_USER:-django}
|
|
||||||
DJANGO_POSTGRES_PASSWORD: ${SAREX_DJANGO_DB_PASSWORD:-django-secret}
|
|
||||||
# celery: брокер rabbitmq + result backend redis (pydantic env_prefix CELERY_*)
|
|
||||||
CELERY_RABBITMQ_HOST: rabbitmq
|
|
||||||
CELERY_RABBITMQ_USER: ${SAREX_RABBITMQ_USER:-rabbit}
|
|
||||||
CELERY_RABBITMQ_PASSWORD: ${SAREX_RABBITMQ_PASSWORD:-rabbit}
|
|
||||||
CELERY_RABBITMQ_VHOST: ${SAREX_RABBITMQ_VHOST:-api}
|
|
||||||
CELERY_REDIS_HOST: redis
|
|
||||||
# S3 / объектное хранилище → MinIO (сервис minio)
|
|
||||||
S3_HOST: http://minio:9000
|
|
||||||
AWS_S3_ENDPOINT_URL: http://minio:9000
|
|
||||||
S3_LOGIN: ${SAREX_MINIO_APP_USER:-sarex-app}
|
|
||||||
S3_PASSWORD: ${SAREX_MINIO_APP_PASSWORD:-sarex-app-secret}
|
|
||||||
S3_BUCKET: ${SAREX_MINIO_BUCKET:-sarex-media-storage}
|
|
||||||
S3_REGION: ${SAREX_MINIO_REGION:-us-east-1}
|
|
||||||
# Сервис measurements (MeasurementSettings, env_prefix MEASUREMENTS_)
|
|
||||||
MEASUREMENTS_HOST: ${SAREX_MEASUREMENTS_HOST:-http://measurements:8000/}
|
|
||||||
# Домен платформы. HOST/SERVER_HOST → абсолютные URL, включая media
|
|
||||||
# (CustomS3Boto3Storage.url = HOST + /media/ + key). Без этого base.py
|
|
||||||
# берёт дефолт lk.sarex.io и media-ссылки уходят на чужой хост.
|
|
||||||
SERVER_HOST: https://${PLATFORM_DOMAIN:-sarex.local}
|
|
||||||
SERVER_API_HOST: https://${PLATFORM_DOMAIN:-sarex.local}
|
|
||||||
# Media: django-storage (S3). Backend отдаёт /media/<key>, верхний nginx
|
|
||||||
# проксирует их в s3-proxy (CORS+Range). Из apps/django/base/backend-deployment.yaml.
|
|
||||||
SERVER_USE_DJANGO_STORAGE: "1"
|
|
||||||
SERVER_DJANGO_URLS: "1"
|
|
||||||
# processing (workflows-api): backend ходит в processing-api за workflow'ами.
|
|
||||||
# WORKFLOWSSETTINGS.host строит COMPARISON/DOCUMENTATION/PDM_FILES_API_URL.
|
|
||||||
# По умолчанию use=False и host=api.sarex.io — переопределяем на наш стек.
|
|
||||||
WORKFLOWS_USE: "1"
|
|
||||||
WORKFLOWS_HOST: http://processing-api:8080
|
|
||||||
WORKFLOWS_BASE_HOST: http://backend:8000
|
|
||||||
WORKFLOWS_PREFIX: /internal/v1
|
|
||||||
tty: true
|
|
||||||
ports:
|
|
||||||
- "8000:8000" # HTTP API (uWSGI http-socket), migrate выполняется в entrypoint
|
|
||||||
volumes:
|
|
||||||
# свой uwsgi.ini поверх образного: http-socket + 4 воркера (:z — SELinux/RedOS)
|
|
||||||
- ./backend/uwsgi.ini:/opt/sarex/uwsgi.ini:ro,z
|
|
||||||
# production.py с включённой классической JWT-аутентификацией
|
|
||||||
- ./backend/production.py:/opt/sarex/config/settings/production.py:ro,z
|
|
||||||
depends_on:
|
|
||||||
postgres:
|
|
||||||
condition: service_healthy
|
|
||||||
postgres-init:
|
|
||||||
condition: service_completed_successfully
|
|
||||||
redis:
|
|
||||||
condition: service_healthy
|
|
||||||
rabbitmq:
|
|
||||||
condition: service_healthy
|
|
||||||
minio-init:
|
|
||||||
condition: service_completed_successfully
|
|
||||||
|
|
||||||
celery:
|
|
||||||
image: ${SAREX_BACKEND_IMAGE:-cr.yandex/crp3ccidau046kdj8g9q/backend:production_80d1d847}
|
|
||||||
container_name: sarex-celery
|
|
||||||
restart: unless-stopped
|
|
||||||
entrypoint: celery -A config worker -l info -E -Q default -n default_worker.%h --concurrency=1 -B
|
|
||||||
environment:
|
|
||||||
<<: *sarex-backend-env
|
|
||||||
volumes:
|
|
||||||
- ./backend/production.py:/opt/sarex/config/settings/production.py:ro,z
|
|
||||||
depends_on:
|
|
||||||
postgres:
|
|
||||||
condition: service_healthy
|
|
||||||
postgres-init:
|
|
||||||
condition: service_completed_successfully
|
|
||||||
redis:
|
|
||||||
condition: service_healthy
|
|
||||||
rabbitmq:
|
|
||||||
condition: service_healthy
|
|
||||||
minio-init:
|
|
||||||
condition: service_completed_successfully
|
|
||||||
|
|
||||||
frontend:
|
|
||||||
image: ${SAREX_FRONTEND_IMAGE:-cr.yandex/crp3ccidau046kdj8g9q/frontend:contour_42138486}
|
|
||||||
container_name: sarex-frontend
|
|
||||||
restart: unless-stopped
|
|
||||||
ports:
|
|
||||||
- "8080:80" # web UI
|
|
||||||
depends_on:
|
|
||||||
- backend
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
|
||||||
# s3-proxy — отдаёт объекты MinIO/S3 браузеру с CORS и поддержкой Range (media).
|
|
||||||
# В k8s креды приходят из Vault в /vault/secrets/s3; здесь Vault нет, поэтому
|
|
||||||
# entrypoint из манифеста gracefully пропускает отсутствующий файл, а
|
|
||||||
# AWS_*-переменные подставляем напрямую (MinIO app-пользователь + бакет).
|
|
||||||
# Источник: apps/django/base/s3-proxy.yaml.
|
|
||||||
# ---------------------------------------------------------------------------
|
|
||||||
s3-proxy:
|
|
||||||
image: ${SAREX_S3_PROXY_IMAGE:-cr.yandex/crp3ccidau046kdj8g9q/s3-proxy:vault_6e586217}
|
|
||||||
container_name: s3-proxy
|
|
||||||
restart: unless-stopped
|
|
||||||
entrypoint: ["/bin/sh", "-ec"]
|
|
||||||
command:
|
|
||||||
- |
|
|
||||||
set -a
|
|
||||||
[ -f /vault/secrets/s3 ] && . /vault/secrets/s3
|
|
||||||
set +a
|
|
||||||
exec /s3-proxy
|
|
||||||
environment:
|
|
||||||
ACCESS_LOG: "true"
|
|
||||||
CORS_ALLOW_HEADERS: "Content-Type, Accept-Ranges, Content-Range, Content-Encoding"
|
|
||||||
# Замена Vault-секрета /vault/secrets/s3 прямыми значениями:
|
|
||||||
AWS_API_ENDPOINT: http://minio:9000
|
|
||||||
AWS_S3_BUCKET: ${SAREX_MINIO_BUCKET:-sarex-media-storage}
|
|
||||||
AWS_ACCESS_KEY_ID: ${SAREX_MINIO_APP_USER:-sarex-app}
|
|
||||||
AWS_SECRET_ACCESS_KEY: ${SAREX_MINIO_APP_PASSWORD:-sarex-app-secret}
|
|
||||||
# Порт наружу не публикуем — доступ только через верхний nginx (/media/),
|
|
||||||
# как ClusterIP в k8s. Внутренняя docker-сеть резолвит s3-proxy:80.
|
|
||||||
depends_on:
|
|
||||||
minio-init:
|
|
||||||
condition: service_completed_successfully
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
|
||||||
# Приложение processing (workflows-api + workflows-frontend).
|
|
||||||
# Образы приватные (cr.yandex). БД — отдельная workflow_db в общем postgres.
|
|
||||||
# Версии/env взяты из apps/processing/base/*.yaml.
|
|
||||||
# ---------------------------------------------------------------------------
|
|
||||||
processing-api:
|
|
||||||
image: ${SAREX_PROCESSING_API_IMAGE:-cr.yandex/crp3ccidau046kdj8g9q/workflows-api_prod:075fc0}
|
|
||||||
# Локальная сборка (Go, cmd/httpserver). Исходник — на dev-машине:
|
|
||||||
# build:
|
|
||||||
# context: /mnt/c/Users/user/PycharmProjects/platform/workflows-api
|
|
||||||
# dockerfile: Dockerfile
|
|
||||||
container_name: processing-api
|
|
||||||
restart: unless-stopped
|
|
||||||
entrypoint: ["/httpserver"]
|
|
||||||
command: ["migrate"] # в манифесте: /httpserver migrate (миграции + сервер на :8080)
|
|
||||||
environment:
|
|
||||||
HTTP_HOST: 0.0.0.0:8080
|
|
||||||
POSTGRES_ADDRESS: postgres
|
|
||||||
POSTGRES_PORT: "5432"
|
|
||||||
POSTGRES_DB: ${SAREX_PROCESSING_DB:-workflow_db}
|
|
||||||
POSTGRES_USER: ${SAREX_PROCESSING_DB_USER:-processing}
|
|
||||||
POSTGRES_PASSWORD: ${SAREX_PROCESSING_DB_PASSWORD:-processing-secret}
|
|
||||||
POSTGRES_POOL_SIZE: "3"
|
|
||||||
POSTGRES_SSL_USE: "0"
|
|
||||||
ENABLE_SQL_QUERY: "0"
|
|
||||||
# JWT public key (общий с backend) — единственная интеграция, ей
|
|
||||||
# workflows-api проверяет Bearer-токен на /api. Больше код ничего не читает
|
|
||||||
# (ни S3, ни DJANGO_HOST — они в манифесте были мёртвыми).
|
|
||||||
PUBLIC_KEY: ${SAREX_JWT_PUBLIC_KEY:-JPK}
|
|
||||||
# Порт наружу не публикуем — доступ через верхний nginx (/workflows/api/).
|
|
||||||
depends_on:
|
|
||||||
postgres:
|
|
||||||
condition: service_healthy
|
|
||||||
postgres-init:
|
|
||||||
condition: service_completed_successfully
|
|
||||||
|
|
||||||
processing-frontend:
|
|
||||||
image: ${SAREX_PROCESSING_FRONTEND_IMAGE:-cr.yandex/crp3ccidau046kdj8g9q/workflows-frontend:ugok2_85f6ce2c}
|
|
||||||
# Локальная сборка (node, npm run build-module). Исходник — на dev-машине.
|
|
||||||
# Нужны build-args BUILD_ENV=contour и NPM_NEXUS_TOKEN (приватный npm).
|
|
||||||
# build:
|
|
||||||
# context: /mnt/c/Users/user/WebstormProjects/platform/workflows-frontend
|
|
||||||
# dockerfile: Dockerfile
|
|
||||||
# args:
|
|
||||||
# BUILD_ENV: contour
|
|
||||||
# NPM_NEXUS_TOKEN: ${NPM_NEXUS_TOKEN:-}
|
|
||||||
container_name: processing-frontend
|
|
||||||
restart: unless-stopped
|
|
||||||
# Порт наружу не публикуем — доступ через верхний nginx (/workflows/).
|
|
||||||
depends_on:
|
|
||||||
- processing-api
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
|
||||||
# workflows-engine — оркестратор processing: читает workflow_db, создаёт Job'ы
|
|
||||||
# в k3s (K8s-исполнитель; AMQP выкл). В кластер ходит out-of-cluster через
|
|
||||||
# kubeconfig (KUBE_CONFIG+KUBE_ADDR). Job-поды резолвят postgres/minio через
|
|
||||||
# DNS-мост namespace processing. Источник: apps/processing/base/engine*.yaml.
|
|
||||||
# ---------------------------------------------------------------------------
|
|
||||||
engine:
|
|
||||||
image: ${SAREX_WORKFLOWS_ENGINE_IMAGE:-cr.yandex/crp3ccidau046kdj8g9q/workflows-endigne_prod:075fc0}
|
|
||||||
container_name: engine
|
|
||||||
restart: unless-stopped
|
|
||||||
entrypoint: ["/engine"]
|
|
||||||
environment:
|
|
||||||
APP_NAME: workflows-engine
|
|
||||||
LOG_LEVEL: info
|
|
||||||
ENVIRONMENT: contour
|
|
||||||
# исполнители: только Kubernetes
|
|
||||||
ENABLE_KUBERNETES_EXECUTOR: "1"
|
|
||||||
ENABLE_AMQP_EXECUTOR: "0"
|
|
||||||
COUNT_RUNNING_WORKERS: "1"
|
|
||||||
COUNT_CANCELING_WORKERS: "1"
|
|
||||||
COUNT_HANDLE_JOB_WORKERS: "1"
|
|
||||||
WORKFLOW_PRIORITY: low
|
|
||||||
MAX_WORKFLOWS_LIMIT: "5"
|
|
||||||
# доступ в k3s (out-of-cluster): kubeconfig + перекрытый адрес apiserver
|
|
||||||
KUBE_CONFIG: /kube/config
|
|
||||||
KUBE_CONTEXT: default
|
|
||||||
KUBE_ADDR: https://k3s-server:6443
|
|
||||||
JOBS_NAMESPACE: processing
|
|
||||||
# свой доступ к workflow_db по compose-DNS
|
|
||||||
POSTGRES_ADDRESS: postgres
|
|
||||||
POSTGRES_PORT: "5432"
|
|
||||||
POSTGRES_DB: ${SAREX_PROCESSING_DB:-workflow_db}
|
|
||||||
POSTGRES_USER: ${SAREX_PROCESSING_DB_USER:-processing}
|
|
||||||
POSTGRES_PASSWORD: ${SAREX_PROCESSING_DB_PASSWORD:-processing-secret}
|
|
||||||
POSTGRES_POOL_SIZE: "20"
|
|
||||||
POSTGRES_SSL_USE: "0"
|
|
||||||
# хранилища: только S3, напрямую в minio (yc-s3 SA JSON смонтирован)
|
|
||||||
ENABLE_S3_STORAGE: "1"
|
|
||||||
S3_SERVICE_ACCOUNT: /etc/sarex/yc-s3/yc-s3-service-account.json
|
|
||||||
# дефолты планирования Job-подов
|
|
||||||
DEFAULT_IMAGE_PULL_POLICY: IfNotPresent
|
|
||||||
DEFAULT_CPU_REQUESTS: 100m
|
|
||||||
DEFAULT_MEMORY_REQUESTS: 64Mi
|
|
||||||
volumes:
|
|
||||||
- ./k3s/kubeconfig.yaml:/kube/config:ro,z
|
|
||||||
- ./engine/yc-s3-service-account.json:/etc/sarex/yc-s3/yc-s3-service-account.json:ro,z
|
|
||||||
depends_on:
|
|
||||||
postgres:
|
|
||||||
condition: service_healthy
|
|
||||||
postgres-init:
|
|
||||||
condition: service_completed_successfully
|
|
||||||
k3s-server:
|
|
||||||
condition: service_healthy
|
|
||||||
processing-k8s-init:
|
|
||||||
condition: service_completed_successfully
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
|
||||||
# measurements — FastAPI, считает измерения по растрам из S3/MinIO (GDAL vsis3).
|
|
||||||
# БД/воркера нет. Обязателен S3_JSON_SETTINGS. Источник: apps/measurements/base.
|
|
||||||
# ---------------------------------------------------------------------------
|
|
||||||
measurements:
|
|
||||||
image: ${SAREX_MEASUREMENTS_IMAGE:-cr.yandex/crp3ccidau046kdj8g9q/measurements:production_a5bb3e84}
|
|
||||||
container_name: measurements
|
|
||||||
restart: unless-stopped
|
|
||||||
entrypoint: ["/opt/entrypoint.sh"]
|
|
||||||
environment:
|
|
||||||
# host http:// → GDAL переключается на AWS_HTTPS=NO (см. CONFIGURATION.md)
|
|
||||||
S3_JSON_SETTINGS: '{"host":"http://minio:9000","login":"${SAREX_MINIO_APP_USER:-sarex-app}","password":"${SAREX_MINIO_APP_PASSWORD:-sarex-app-secret}","verify":false,"buckets":["${SAREX_MINIO_BUCKET:-sarex-media-storage}"]}'
|
|
||||||
LOG_LEVEL: INFO
|
|
||||||
TRACING_USE: "false"
|
|
||||||
AUTH: "0"
|
|
||||||
DJANGO_HOST: http://backend:8000
|
|
||||||
# порт наружу не публикуем — доступ только из backend по http://measurements:8000/
|
|
||||||
depends_on:
|
|
||||||
minio-init:
|
|
||||||
condition: service_completed_successfully
|
|
||||||
|
|
||||||
# Верхний reverse-proxy: 3 домена → платформа / rabbitmq (admin) / minio
|
|
||||||
nginx:
|
|
||||||
image: ${NGINX_IMAGE:-nginx:1.27-alpine}
|
|
||||||
container_name: sarex-nginx
|
|
||||||
restart: unless-stopped
|
|
||||||
ports:
|
|
||||||
- "80:80" # http
|
|
||||||
- "443:443" # https (самоподписанный сертификат)
|
|
||||||
environment:
|
|
||||||
# подставляются envsubst'ом в шаблон при старте контейнера
|
|
||||||
PLATFORM_DOMAIN: ${PLATFORM_DOMAIN:-sarex.local}
|
|
||||||
ADMIN_DOMAIN: ${ADMIN_DOMAIN:-admin.sarex.local}
|
|
||||||
MINIO_DOMAIN: ${MINIO_DOMAIN:-minio.sarex.local}
|
|
||||||
volumes:
|
|
||||||
- ./nginx/templates:/etc/nginx/templates:ro,z # :z — SELinux label для RedOS
|
|
||||||
- ./nginx/certs:/etc/nginx/certs:ro,z # TLS-сертификаты
|
|
||||||
depends_on:
|
|
||||||
# - backend # TODO: закомментированы в шаблоне nginx, пока в работе
|
|
||||||
# - frontend
|
|
||||||
- minio
|
|
||||||
- rabbitmq
|
|
||||||
- s3-proxy
|
|
||||||
- processing-api
|
|
||||||
- processing-frontend
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD", "wget", "-qO-", "http://127.0.0.1/healthz"]
|
|
||||||
interval: 10s
|
|
||||||
timeout: 5s
|
|
||||||
retries: 6
|
|
||||||
start_period: 10s
|
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
k3s-server-data:
|
k3s-server-data:
|
||||||
k3s-worker-1-data:
|
k3s-worker-1-data:
|
||||||
@ -891,13 +403,12 @@ volumes:
|
|||||||
gitea-data:
|
gitea-data:
|
||||||
sarex-vault-data: # file-хранилище Vault
|
sarex-vault-data: # file-хранилище Vault
|
||||||
sarex-vault-init: # unseal-ключ и root-токен (только для vault-init)
|
sarex-vault-init: # unseal-ключ и root-токен (только для vault-init)
|
||||||
sarex-postgres-data:
|
|
||||||
sarex-redis-data:
|
|
||||||
sarex-rabbitmq-data:
|
|
||||||
sarex-minio-data:
|
|
||||||
|
|
||||||
# Дефолтной сети задаём фиксированный subnet, чтобы закрепить IP за postgres/minio.
|
# Дефолтной сети задаём фиксированный subnet, чтобы закрепить IP за gitea и vault.
|
||||||
# На эти адреса ссылаются k8s-Endpoints DNS-моста (namespace processing в k3s).
|
# На эти адреса ссылаются k8s-Endpoints DNS-мостов внутри k3s (namespace
|
||||||
|
# flux-system и vault): у кластера своя DNS, и имена compose-сети в ней не
|
||||||
|
# резолвятся, а поды дотягиваются до 172.28.0.0/16 через SNAT на ноде.
|
||||||
|
# Данные PVC (postgres, minio, rabbitmq) живут в k3s и томов здесь не имеют.
|
||||||
networks:
|
networks:
|
||||||
default:
|
default:
|
||||||
ipam:
|
ipam:
|
||||||
|
|||||||
@ -1,8 +0,0 @@
|
|||||||
{
|
|
||||||
"host": "http://minio:9000",
|
|
||||||
"bucket": "sarex-media-storage",
|
|
||||||
"access_key_id": "sarex-app",
|
|
||||||
"secret_access_key": "sarex-app-secret",
|
|
||||||
"region": "us-east-1",
|
|
||||||
"verify": false
|
|
||||||
}
|
|
||||||
@ -1,26 +0,0 @@
|
|||||||
# DNS-мост: имя `minio` в namespace processing → compose-контейнер minio
|
|
||||||
# (статический IP 172.28.0.11, прямой S3 на :9000). Service без селектора + Endpoints.
|
|
||||||
apiVersion: v1
|
|
||||||
kind: Service
|
|
||||||
metadata:
|
|
||||||
name: minio
|
|
||||||
namespace: processing
|
|
||||||
spec:
|
|
||||||
ports:
|
|
||||||
- name: s3
|
|
||||||
port: 9000
|
|
||||||
targetPort: 9000
|
|
||||||
protocol: TCP
|
|
||||||
---
|
|
||||||
apiVersion: v1
|
|
||||||
kind: Endpoints
|
|
||||||
metadata:
|
|
||||||
name: minio
|
|
||||||
namespace: processing
|
|
||||||
subsets:
|
|
||||||
- addresses:
|
|
||||||
- ip: 172.28.0.11
|
|
||||||
ports:
|
|
||||||
- name: s3
|
|
||||||
port: 9000
|
|
||||||
protocol: TCP
|
|
||||||
@ -1,26 +0,0 @@
|
|||||||
# DNS-мост: имя `postgres` в namespace processing → compose-контейнер postgres
|
|
||||||
# (статический IP 172.28.0.10). Service без селектора + ручной Endpoints.
|
|
||||||
apiVersion: v1
|
|
||||||
kind: Service
|
|
||||||
metadata:
|
|
||||||
name: postgres
|
|
||||||
namespace: processing
|
|
||||||
spec:
|
|
||||||
ports:
|
|
||||||
- name: pg
|
|
||||||
port: 5432
|
|
||||||
targetPort: 5432
|
|
||||||
protocol: TCP
|
|
||||||
---
|
|
||||||
apiVersion: v1
|
|
||||||
kind: Endpoints
|
|
||||||
metadata:
|
|
||||||
name: postgres
|
|
||||||
namespace: processing
|
|
||||||
subsets:
|
|
||||||
- addresses:
|
|
||||||
- ip: 172.28.0.10
|
|
||||||
ports:
|
|
||||||
- name: pg
|
|
||||||
port: 5432
|
|
||||||
protocol: TCP
|
|
||||||
@ -1,4 +0,0 @@
|
|||||||
apiVersion: v1
|
|
||||||
kind: Namespace
|
|
||||||
metadata:
|
|
||||||
name: processing
|
|
||||||
@ -1,36 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
# Генерация самоподписанного TLS-сертификата для верхнего nginx.
|
|
||||||
#
|
|
||||||
# Использование:
|
|
||||||
# ./nginx/gen-cert.sh # домены по умолчанию
|
|
||||||
# ./nginx/gen-cert.sh sarex.local api.sarex.local # свои домены (первый → CN)
|
|
||||||
# DAYS=730 ./nginx/gen-cert.sh # свой срок действия
|
|
||||||
#
|
|
||||||
# Результат: nginx/certs/selfsigned.{crt,key} (в .gitignore).
|
|
||||||
# MSYS_NO_PATHCONV=1 нужен для Git Bash на Windows; на Linux он безвреден.
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
CERT_DIR="$(cd "$(dirname "$0")" && pwd)/certs"
|
|
||||||
DAYS="${DAYS:-365}"
|
|
||||||
|
|
||||||
if [ "$#" -gt 0 ]; then
|
|
||||||
DOMAINS=("$@")
|
|
||||||
else
|
|
||||||
DOMAINS=(sarex.local admin.sarex.local minio.sarex.local)
|
|
||||||
fi
|
|
||||||
|
|
||||||
# subjectAltName из списка доменов, CN — первый домен
|
|
||||||
SAN=""
|
|
||||||
for d in "${DOMAINS[@]}"; do SAN="${SAN}${SAN:+,}DNS:${d}"; done
|
|
||||||
CN="${DOMAINS[0]}"
|
|
||||||
|
|
||||||
mkdir -p "$CERT_DIR"
|
|
||||||
cd "$CERT_DIR" # пишем относительными именами: не ломается конверсия путей в Git Bash
|
|
||||||
MSYS_NO_PATHCONV=1 openssl req -x509 -nodes -newkey rsa:2048 -days "$DAYS" \
|
|
||||||
-keyout selfsigned.key \
|
|
||||||
-out selfsigned.crt \
|
|
||||||
-subj "/CN=${CN}" \
|
|
||||||
-addext "subjectAltName=${SAN}"
|
|
||||||
|
|
||||||
echo "OK: сертификат на ${DAYS} дней → $CERT_DIR/selfsigned.{crt,key}"
|
|
||||||
echo "SAN: ${SAN}"
|
|
||||||
@ -1,166 +0,0 @@
|
|||||||
# Рендерится образом nginx: envsubst подставляет ${PLATFORM_DOMAIN} и т.п.
|
|
||||||
# из окружения и кладёт результат в /etc/nginx/conf.d/default.conf (внутри http{}).
|
|
||||||
# Переменные вида $host / $http_upgrade — НЕ окруженческие, envsubst их не трогает.
|
|
||||||
|
|
||||||
large_client_header_buffers 8 128k;
|
|
||||||
client_max_body_size 5000M; # крупные загрузки (снимки, облака точек)
|
|
||||||
tcp_nopush on;
|
|
||||||
|
|
||||||
# TLS (самоподписанный сертификат на все домены). Задаём на http-уровне —
|
|
||||||
# наследуется всеми server-блоками. Файлы монтируются из ./nginx/certs.
|
|
||||||
ssl_certificate /etc/nginx/certs/selfsigned.crt;
|
|
||||||
ssl_certificate_key /etc/nginx/certs/selfsigned.key;
|
|
||||||
ssl_protocols TLSv1.2 TLSv1.3;
|
|
||||||
ssl_ciphers HIGH:!aNULL:!MD5;
|
|
||||||
ssl_session_cache shared:SSL:10m;
|
|
||||||
http2 on;
|
|
||||||
|
|
||||||
gzip on;
|
|
||||||
gzip_vary on;
|
|
||||||
gzip_proxied any;
|
|
||||||
gzip_comp_level 6;
|
|
||||||
gzip_types text/plain text/css application/json application/javascript text/xml application/xml;
|
|
||||||
|
|
||||||
map $http_upgrade $connection_upgrade {
|
|
||||||
default upgrade;
|
|
||||||
'' close;
|
|
||||||
}
|
|
||||||
|
|
||||||
upstream backend { server backend:8000; }
|
|
||||||
upstream frontend { server frontend:80; }
|
|
||||||
upstream minio_s3 { server minio:9000; }
|
|
||||||
upstream minio_console { server minio:9001; }
|
|
||||||
upstream rabbitmq_mgmt { server rabbitmq:15672; }
|
|
||||||
upstream s3_proxy { server s3-proxy:80; } # media (/media/) с CORS+Range
|
|
||||||
upstream processing_api { server processing-api:8080; }
|
|
||||||
upstream processing_frontend { server processing-frontend:8080; }
|
|
||||||
|
|
||||||
# Общие проксирующие заголовки. ВАЖНО: если в location задан свой proxy_set_header,
|
|
||||||
# эти НЕ наследуются — там заголовки продублированы явно.
|
|
||||||
proxy_set_header Host $host;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
|
||||||
|
|
||||||
# ============================ Платформа (основной домен) ====================
|
|
||||||
server {
|
|
||||||
listen 80 default_server;
|
|
||||||
listen 443 ssl default_server;
|
|
||||||
server_name ${PLATFORM_DOMAIN};
|
|
||||||
|
|
||||||
location = /healthz {
|
|
||||||
access_log off;
|
|
||||||
add_header Content-Type text/plain;
|
|
||||||
return 200 "ok\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
# Рантайм-конфиг фронта. Прод-сборка по умолчанию уходит в zitadel, которого
|
|
||||||
# тут нет, — форсим классический вход через backend (auth_type=original).
|
|
||||||
# Отдаём сами: в образе frontend этого файла нет (был бы 404).
|
|
||||||
location = /static/config.json {
|
|
||||||
default_type application/json;
|
|
||||||
add_header Cache-Control "no-store";
|
|
||||||
return 200 '{"auth_type":"original"}';
|
|
||||||
}
|
|
||||||
|
|
||||||
# Django backend: REST API + админка
|
|
||||||
location /api/ { proxy_pass http://backend; }
|
|
||||||
location /admin/ { proxy_pass http://backend; }
|
|
||||||
|
|
||||||
# --- processing (workflows) под /workflows ---
|
|
||||||
# Префикс /workflows срезаем: api ждёт пути /api/v1/..., фронт — от корня.
|
|
||||||
location = /workflows { return 301 /workflows/; }
|
|
||||||
|
|
||||||
location /workflows/api/ {
|
|
||||||
rewrite ^/workflows/(.*)$ /$1 break;
|
|
||||||
proxy_pass http://processing_api;
|
|
||||||
}
|
|
||||||
|
|
||||||
location /workflows/ {
|
|
||||||
rewrite ^/workflows/(.*)$ /$1 break;
|
|
||||||
proxy_http_version 1.1;
|
|
||||||
proxy_set_header Host $host;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
|
||||||
proxy_set_header Upgrade $http_upgrade;
|
|
||||||
proxy_set_header Connection $connection_upgrade;
|
|
||||||
proxy_pass http://processing_frontend;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Media: s3-proxy раздаёт объекты S3/MinIO по URI /media/ (CORS + Range).
|
|
||||||
# Префикс /media/ передаём как есть — s3-proxy сам мапит его на бакет.
|
|
||||||
location /media/ {
|
|
||||||
proxy_set_header Host $host;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
|
||||||
proxy_http_version 1.1;
|
|
||||||
proxy_set_header Connection "";
|
|
||||||
proxy_set_header Range $http_range;
|
|
||||||
proxy_set_header If-Range $http_if_range;
|
|
||||||
proxy_buffering off;
|
|
||||||
proxy_request_buffering off;
|
|
||||||
proxy_max_temp_file_size 0;
|
|
||||||
proxy_pass http://s3_proxy;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Frontend SPA (host-приложение само отдаёт статику и роутинг)
|
|
||||||
location / {
|
|
||||||
proxy_set_header Host $host;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
|
||||||
proxy_http_version 1.1;
|
|
||||||
proxy_set_header Upgrade $http_upgrade;
|
|
||||||
proxy_set_header Connection $connection_upgrade;
|
|
||||||
proxy_pass http://frontend;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# ======================= Admin: RabbitMQ management UI ======================
|
|
||||||
server {
|
|
||||||
listen 80;
|
|
||||||
listen 443 ssl;
|
|
||||||
server_name ${ADMIN_DOMAIN};
|
|
||||||
|
|
||||||
location / {
|
|
||||||
proxy_set_header Host $host;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
|
||||||
proxy_http_version 1.1;
|
|
||||||
proxy_set_header Upgrade $http_upgrade;
|
|
||||||
proxy_set_header Connection $connection_upgrade;
|
|
||||||
proxy_pass http://rabbitmq_mgmt;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# ============================== MinIO (отдельный домен) =====================
|
|
||||||
# Консоль отдаётся с КОРНЯ домена (порт 9001) — так её статика (/static, /api,
|
|
||||||
# websocket) резолвится без сабпути. У сервиса minio:
|
|
||||||
# MINIO_BROWSER_REDIRECT_URL = https://<MINIO_DOMAIN>
|
|
||||||
# S3 API (:9000) здесь НЕ публикуется: backend ходит в minio:9000 по внутренней
|
|
||||||
# сети. Понадобится S3 наружу — заведи отдельный домен (напр. s3.<...>) на minio_s3.
|
|
||||||
server {
|
|
||||||
listen 80;
|
|
||||||
listen 443 ssl;
|
|
||||||
server_name ${MINIO_DOMAIN};
|
|
||||||
|
|
||||||
location / {
|
|
||||||
proxy_set_header Host $host;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
|
||||||
proxy_http_version 1.1;
|
|
||||||
proxy_set_header Upgrade $http_upgrade;
|
|
||||||
proxy_set_header Connection $connection_upgrade;
|
|
||||||
proxy_set_header X-NginX-Proxy true;
|
|
||||||
chunked_transfer_encoding off;
|
|
||||||
# крупные загрузки объектов через консоль
|
|
||||||
proxy_buffering off;
|
|
||||||
proxy_request_buffering off;
|
|
||||||
proxy_max_temp_file_size 0;
|
|
||||||
proxy_pass http://minio_console;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Loading…
Reference in New Issue
Block a user