docs: spec — workflows-engine в контуре через k3s (планирование Job'ов)
This commit is contained in:
parent
9a39f4568e
commit
5f84c8d19b
@ -0,0 +1,155 @@
|
|||||||
|
# Дизайн: workflows-engine в контуре через k3s (планирование Job'ов)
|
||||||
|
|
||||||
|
Дата: 2026-07-30
|
||||||
|
Ветка: `aero`
|
||||||
|
Статус: согласован, готов к плану реализации
|
||||||
|
|
||||||
|
## Цель и рамки
|
||||||
|
|
||||||
|
Добавить в контур **workflows-engine** — фоновый оркестратор processing-подсистемы,
|
||||||
|
который вычитывает workflow из `workflow_db` и запускает задачи как **Kubernetes Job'ы**.
|
||||||
|
|
||||||
|
**Успех = планирование Job'ов:** engine стартует, подключается к `workflow_db`,
|
||||||
|
получает доступ к kube-API k3s и создаёт Job-объекты в namespace `processing`;
|
||||||
|
Job-поды планируются на ноду и достукиваются до `postgres`/`minio` из compose-сети.
|
||||||
|
|
||||||
|
**Вне рамок (принятые ограничения):**
|
||||||
|
- Полное end-to-end выполнение конвертаций НЕ гарантируется: engine тянет множество
|
||||||
|
downstream-сервисов (documentations/PDM, resources, bim-api-v2, workspace-api,
|
||||||
|
issue-api, comparisons, SMTP/Mailgun), которых в контуре нет. Все их `ENABLE_*`
|
||||||
|
выключаем; включаем только `ENABLE_S3_STORAGE`.
|
||||||
|
- Валидный S3 service-account для рантайма джоб не требуется для *планирования*
|
||||||
|
(S3 нужен на этапе выполнения задачи, не создания Job-объекта) — допускается плейсхолдер.
|
||||||
|
- Только одна нода k3s (`k3s-server`), без `k3s-worker`.
|
||||||
|
|
||||||
|
## Ключевые находки (обоснование дизайна)
|
||||||
|
|
||||||
|
Источники: `apps/processing/base/{api,engine,engine-low}.yaml`,
|
||||||
|
`apps/processing/workflows-engine.CONFIGURATION.md`.
|
||||||
|
|
||||||
|
1. **Джобы НЕ ходят в `workflow_db`.** В списке env, прокидываемых engine в Job-поды
|
||||||
|
(`pkg/kube_services/services.go`, CONFIGURATION.md §«…пробрасываемые в под'ы задач»),
|
||||||
|
`POSTGRES_*` отсутствует. В `workflow_db` ходит только сам engine. Джобам достаётся
|
||||||
|
S3 (через yc-s3 SA JSON при `ENABLE_S3_STORAGE`) и опционально JSON-конфиги прикладных
|
||||||
|
БД (bim/workspace/…) — только при соответствующих `ENABLE_*`.
|
||||||
|
2. **Доступ compose→k3s штатный.** У engine есть `KUBE_CONFIG` (путь; пусто = in-cluster,
|
||||||
|
задан = out-of-cluster), `KUBE_CONTEXT`, `KUBE_ADDR` (адрес apiserver + InsecureSkipTLSVerify),
|
||||||
|
`JOBS_NAMESPACE`. RBAC/ServiceAccount не нужны — аутентификация кредами из kubeconfig.
|
||||||
|
3. **RabbitMQ не нужен.** `pkg/rabbitmq` используется только при `ENABLE_AMQP_EXECUTOR=1`.
|
||||||
|
При K8s-исполнителе брокер не дёргается.
|
||||||
|
4. **`postgres:12-alpine`** генерит `pg_hba` как `host all all all md5` → пускает с любого
|
||||||
|
адреса по паролю. SNAT-источник (IP ноды k3s) не блокируется — нужен лишь верный
|
||||||
|
`processing`/пароль.
|
||||||
|
5. **`k3s-server` в compose уже готов:** `privileged`, `cgroup: host`, `--disable=traefik`,
|
||||||
|
kubeconfig пишется в `./k3s/kubeconfig.yaml`, в общей (default) compose-сети с `postgres`/`minio`.
|
||||||
|
|
||||||
|
## Архитектура
|
||||||
|
|
||||||
|
Три части, все в существующем `iac/docker-compose.yaml` + новые k8s-манифесты.
|
||||||
|
|
||||||
|
### A. engine — сервис docker-compose
|
||||||
|
|
||||||
|
Образ: `${SAREX_WORKFLOWS_ENGINE_IMAGE:-cr.yandex/crp3ccidau046kdj8g9q/workflows-endigne_prod:075fc0}`.
|
||||||
|
|
||||||
|
Ключевой env:
|
||||||
|
- Исполнители: `ENABLE_KUBERNETES_EXECUTOR=1`, `ENABLE_AMQP_EXECUTOR=0`.
|
||||||
|
- Воркеры: `COUNT_RUNNING_WORKERS=1`, `COUNT_CANCELING_WORKERS=1`, `COUNT_HANDLE_JOB_WORKERS=1`
|
||||||
|
(иначе задачи не разбираются).
|
||||||
|
- Доступ в k3s: `KUBE_CONFIG=/kube/config`, `KUBE_CONTEXT=default`,
|
||||||
|
`KUBE_ADDR=https://k3s-server:6443`, `JOBS_NAMESPACE=processing`.
|
||||||
|
(`--tls-san=k3s-server` уже задан у k3s-server; при использовании `KUBE_ADDR` TLS
|
||||||
|
проверка отключается, креды берутся из смонтированного kubeconfig.)
|
||||||
|
- Свой доступ к БД: `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}`, `POSTGRES_SSL_USE=0`.
|
||||||
|
- Хранилища: `ENABLE_S3_STORAGE=1`, `S3_SERVICE_ACCOUNT=/etc/sarex/yc-s3/yc-s3-service-account.json`
|
||||||
|
(JSON указывает на `http://minio:9000` — прямой доступ к S3, мимо s3-proxy).
|
||||||
|
Остальные `ENABLE_*` = 0.
|
||||||
|
- Прочее по умолчанию: `WORKFLOW_PRIORITY=low`, `MAX_WORKFLOWS_LIMIT=5`, `MAX_RUNNING_JOBS`
|
||||||
|
дефолт, ресурсные `DEFAULT_*_REQUESTS`.
|
||||||
|
|
||||||
|
Монтирования:
|
||||||
|
- `./k3s/kubeconfig.yaml:/kube/config:ro,z` — kubeconfig из k3s-server.
|
||||||
|
- yc-s3 SA JSON (плейсхолдер/рабочий) → `/etc/sarex/yc-s3/yc-s3-service-account.json`.
|
||||||
|
|
||||||
|
`depends_on`:
|
||||||
|
- `postgres` (service_healthy), `postgres-init` (service_completed_successfully),
|
||||||
|
- `k3s-server` (service_healthy),
|
||||||
|
- `processing-k8s-init` (service_completed_successfully) — DNS-мост применён до старта engine.
|
||||||
|
|
||||||
|
### B. k3s — только сервер
|
||||||
|
|
||||||
|
Поднимаем существующий `k3s-server` (несёт kubelet → поды планируются на него).
|
||||||
|
`k3s-worker` НЕ поднимаем. Добавляем `k3s-server` (и `processing-k8s-init`, `engine`)
|
||||||
|
в список поднимаемых сервисов ансибла.
|
||||||
|
|
||||||
|
### C. DNS-мост `postgres` + `minio` в k3s
|
||||||
|
|
||||||
|
Чтобы Job-поды резолвили те же имена, что и в compose:
|
||||||
|
- Namespace `processing`.
|
||||||
|
- `Service` (ClusterIP, без селектора) `postgres` и `minio` + ручные `Endpoints`,
|
||||||
|
указывающие на статические IP compose-контейнеров.
|
||||||
|
- Бареме-имена `postgres`/`minio` резолвятся в подах namespace `processing` через
|
||||||
|
search-domain `…processing.svc.cluster.local`.
|
||||||
|
|
||||||
|
Применение — одноразовый helper-контейнер **`processing-k8s-init`** (по образцу `postgres-init`):
|
||||||
|
образ с `kubectl`, монтирует `./k3s/kubeconfig.yaml` и каталог манифестов
|
||||||
|
(`./k3s/manifests/processing/`), выполняет `kubectl --kubeconfig … apply -f`.
|
||||||
|
Идемпотентно, `restart: "no"`. Ждёт `k3s-server` (service_healthy).
|
||||||
|
|
||||||
|
Манифесты (новый каталог `iac/k3s/manifests/processing/`):
|
||||||
|
- `namespace.yaml` — namespace `processing`.
|
||||||
|
- `bridge-postgres.yaml` — Service+Endpoints `postgres` → `172.28.0.10:5432`.
|
||||||
|
- `bridge-minio.yaml` — Service+Endpoints `minio` → `172.28.0.11:9000`.
|
||||||
|
|
||||||
|
## Сеть и стабильность адресов
|
||||||
|
|
||||||
|
Решение: **статические IP в compose** (прочтение «адреса как в docker-compose»).
|
||||||
|
|
||||||
|
- Верхнеуровневой `networks.default` задаём IPAM с фиксированным subnet, напр. `172.28.0.0/16`.
|
||||||
|
- `postgres` → `172.28.0.10`, `minio` → `172.28.0.11` (пиним только их; остальным IP динамический из того же subnet — их не трогаем).
|
||||||
|
- k8s `Endpoints` ссылаются на эти статические IP → не «плывут» при рестарте, декларативно.
|
||||||
|
|
||||||
|
Маршрут Job-под → `postgres`/`minio`:
|
||||||
|
под выходит через ноду `k3s-server` (её интерфейс в той же `172.28.0.0/16`),
|
||||||
|
трафик доходит до контейнера напрямую/по SNAT ноды. Аутентификация postgres —
|
||||||
|
по паролю с любого хоста (см. находку 4). S3 — по app-кредам MinIO.
|
||||||
|
|
||||||
|
## Интеграция с Ansible (`aero/roles/sarex_stack`)
|
||||||
|
|
||||||
|
- `sarex_services`: добавить `k3s-server`, `processing-k8s-init`, `engine`
|
||||||
|
(в правильном порядке; `depends_on` обеспечит последовательность).
|
||||||
|
- Копирование `iac/k3s/manifests/` на хост рядом с compose (в `deploy_dir`).
|
||||||
|
- Секреты: переиспользуем `SAREX_PROCESSING_DB_PASSWORD`, `SAREX_MINIO_APP_USER/PASSWORD`.
|
||||||
|
Новый образ — переменная `SAREX_WORKFLOWS_ENGINE_IMAGE` в `.env.example`.
|
||||||
|
- kubeconfig генерится k3s-server'ом в `./k3s/kubeconfig.yaml` при первом старте —
|
||||||
|
helper и engine его переиспользуют (server-адрес перекрывается `KUBE_ADDR`).
|
||||||
|
|
||||||
|
## Порядок провижининга
|
||||||
|
|
||||||
|
1. `k3s-server` up → healthy (apiserver `/readyz`).
|
||||||
|
2. `processing-k8s-init` → `kubectl apply` namespace + DNS-мост (Service/Endpoints).
|
||||||
|
3. `postgres` healthy + `postgres-init` completed (роль/БД `workflow_db`/`processing`).
|
||||||
|
4. `engine` up → коннектится к `workflow_db` + kube-API, пуллит workflow, создаёт Job'ы.
|
||||||
|
|
||||||
|
## Риски и точки проверки при реализации
|
||||||
|
|
||||||
|
1. **`KUBE_ADDR` vs правка server-URL.** Проверить, что engine с `KUBE_ADDR=https://k3s-server:6443`
|
||||||
|
+ кредами из kubeconfig реально ходит в apiserver (InsecureSkipTLSVerify). Fallback —
|
||||||
|
sed-правка `server:` в kubeconfig на `https://k3s-server:6443` (SAN уже покрывает имя).
|
||||||
|
2. **Стартовые проверки engine.** Убедиться, что engine поднимается с выключенными downstream
|
||||||
|
`ENABLE_*` и не падает на отсутствии их конфигов/URL при старте.
|
||||||
|
3. **Формат yc-s3 SA JSON.** Точная схема, которую ждёт S3-либа engine/джоб. Для *планирования*
|
||||||
|
не критично (S3 нужен в рантайме джобы) — плейсхолдер допустим, помечаем как follow-up.
|
||||||
|
4. **Образ Job-задачи.** Поды задач тянут приватные образы конверторов; при их отсутствии
|
||||||
|
под уйдёт в `ImagePullBackOff`. Для критерия «планирование» это допустимо — важно, что
|
||||||
|
Job-объект создан и под запланирован.
|
||||||
|
5. **cgroup/SELinux на RedOS.** `k3s-server` уже сконфигурен (`privileged`, `cgroup: host`),
|
||||||
|
но первый реальный старт k3s на хосте надо проверить (dmesg/логи kubelet).
|
||||||
|
|
||||||
|
## Проверка результата
|
||||||
|
|
||||||
|
- `kubectl --kubeconfig ./k3s/kubeconfig.yaml -n processing get svc,endpoints` → `postgres`, `minio` присутствуют.
|
||||||
|
- Логи engine: успешный коннект к `workflow_db` и kube-API, нет паник.
|
||||||
|
- Создать/инициировать workflow → `kubectl -n processing get jobs,pods` показывает созданный Job.
|
||||||
|
- (follow-up) end-to-end выполнение — отдельная задача с поднятием downstream-сервисов.
|
||||||
Loading…
Reference in New Issue
Block a user