Compare commits
8 Commits
9a39f4568e
...
5105eee602
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5105eee602 | ||
|
|
714dc55db1 | ||
|
|
a7c97027ae | ||
|
|
934ccbbb73 | ||
|
|
4c4bb6f8a4 | ||
|
|
497ca1342d | ||
|
|
383d19157c | ||
|
|
5f84c8d19b |
@ -72,6 +72,8 @@ SAREX_WORKSPACE_DB=workspace_db
|
|||||||
# Приложение processing (workflows-api + workflows-frontend)
|
# Приложение processing (workflows-api + workflows-frontend)
|
||||||
SAREX_PROCESSING_API_IMAGE=cr.yandex/crp3ccidau046kdj8g9q/workflows-api_prod:075fc0
|
SAREX_PROCESSING_API_IMAGE=cr.yandex/crp3ccidau046kdj8g9q/workflows-api_prod:075fc0
|
||||||
SAREX_PROCESSING_FRONTEND_IMAGE=cr.yandex/crp3ccidau046kdj8g9q/workflows-frontend:ugok2_85f6ce2c
|
SAREX_PROCESSING_FRONTEND_IMAGE=cr.yandex/crp3ccidau046kdj8g9q/workflows-frontend:ugok2_85f6ce2c
|
||||||
|
# workflows-engine (processing) — оркестратор Job'ов в k3s
|
||||||
|
SAREX_WORKFLOWS_ENGINE_IMAGE=cr.yandex/crp3ccidau046kdj8g9q/workflows-endigne_prod:075fc0
|
||||||
|
|
||||||
# Сервис measurements (FastAPI). Django-backend ходит в него по MEASUREMENTS_HOST.
|
# Сервис measurements (FastAPI). Django-backend ходит в него по MEASUREMENTS_HOST.
|
||||||
SAREX_MEASUREMENTS_IMAGE=cr.yandex/crp3ccidau046kdj8g9q/measurements:production_a5bb3e84
|
SAREX_MEASUREMENTS_IMAGE=cr.yandex/crp3ccidau046kdj8g9q/measurements:production_a5bb3e84
|
||||||
|
|||||||
@ -49,6 +49,9 @@ compose_cmd: "docker compose"
|
|||||||
# Сервисы приложения, поднимаемые при sarex_compose_up (depends_on тянет
|
# Сервисы приложения, поднимаемые при sarex_compose_up (depends_on тянет
|
||||||
# зависимости и порядок). k3s/gitea намеренно не поднимаем.
|
# зависимости и порядок). k3s/gitea намеренно не поднимаем.
|
||||||
sarex_services:
|
sarex_services:
|
||||||
|
# k3s + провижининг DNS-моста (нужны engine'у до старта)
|
||||||
|
- k3s-server
|
||||||
|
- processing-k8s-init
|
||||||
- postgres
|
- postgres
|
||||||
- postgres-init
|
- postgres-init
|
||||||
- redis
|
- redis
|
||||||
@ -62,4 +65,5 @@ sarex_services:
|
|||||||
- frontend
|
- frontend
|
||||||
- processing-api
|
- processing-api
|
||||||
- processing-frontend
|
- processing-frontend
|
||||||
|
- engine
|
||||||
- nginx
|
- nginx
|
||||||
|
|||||||
@ -35,6 +35,21 @@
|
|||||||
mode: "0644"
|
mode: "0644"
|
||||||
notify: Recreate backend and celery
|
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:
|
||||||
|
src: "{{ deploy_src_root }}/k3s/manifests/"
|
||||||
|
dest: "{{ deploy_dir }}/k3s/manifests/"
|
||||||
|
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"
|
||||||
|
|
||||||
# --- Секреты: генерация с персистом на control-node (идемпотентно) --------
|
# --- Секреты: генерация с персистом на control-node (идемпотентно) --------
|
||||||
- name: Сгенерировать/загрузить пароли (persist в secrets_store, gitignored)
|
- name: Сгенерировать/загрузить пароли (persist в secrets_store, gitignored)
|
||||||
ansible.builtin.set_fact:
|
ansible.builtin.set_fact:
|
||||||
|
|||||||
@ -62,6 +62,26 @@ services:
|
|||||||
soft: 65535
|
soft: 65535
|
||||||
hard: 65535
|
hard: 65535
|
||||||
|
|
||||||
|
# Одноразовый провижининг 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
|
||||||
|
|
||||||
gitea:
|
gitea:
|
||||||
image: ${GITEA_IMAGE:-gitea/gitea:1.22}
|
image: ${GITEA_IMAGE:-gitea/gitea:1.22}
|
||||||
container_name: gitea
|
container_name: gitea
|
||||||
@ -112,6 +132,10 @@ services:
|
|||||||
timeout: 5s
|
timeout: 5s
|
||||||
retries: 12
|
retries: 12
|
||||||
start_period: 10s
|
start_period: 10s
|
||||||
|
# Статический IP: на него ссылается k8s-Endpoints `postgres` (DNS-мост в k3s).
|
||||||
|
networks:
|
||||||
|
default:
|
||||||
|
ipv4_address: 172.28.0.10
|
||||||
|
|
||||||
# Одноразовый init: на каждое приложение заводит роль (LOGIN+пароль) и базу
|
# Одноразовый init: на каждое приложение заводит роль (LOGIN+пароль) и базу
|
||||||
# данных с этим владельцем. Идемпотентно (по образцу minio-init).
|
# данных с этим владельцем. Идемпотентно (по образцу minio-init).
|
||||||
@ -232,6 +256,10 @@ services:
|
|||||||
MINIO_BROWSER_REDIRECT_URL: ${SAREX_MINIO_CONSOLE_URL:-https://minio.sarex.local}
|
MINIO_BROWSER_REDIRECT_URL: ${SAREX_MINIO_CONSOLE_URL:-https://minio.sarex.local}
|
||||||
volumes:
|
volumes:
|
||||||
- sarex-minio-data:/data
|
- sarex-minio-data:/data
|
||||||
|
# Статический IP: на него ссылается k8s-Endpoints `minio` (DNS-мост в k3s).
|
||||||
|
networks:
|
||||||
|
default:
|
||||||
|
ipv4_address: 172.28.0.11
|
||||||
|
|
||||||
# Одноразовый init: ждёт MinIO и на каждое приложение заводит бакет +
|
# Одноразовый init: ждёт MinIO и на каждое приложение заводит бакет +
|
||||||
# отдельного пользователя со scoped-политикой (доступ только к своему бакету).
|
# отдельного пользователя со scoped-политикой (доступ только к своему бакету).
|
||||||
@ -455,6 +483,62 @@ services:
|
|||||||
depends_on:
|
depends_on:
|
||||||
- processing-api
|
- 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).
|
# measurements — FastAPI, считает измерения по растрам из S3/MinIO (GDAL vsis3).
|
||||||
# БД/воркера нет. Обязателен S3_JSON_SETTINGS. Источник: apps/measurements/base.
|
# БД/воркера нет. Обязателен S3_JSON_SETTINGS. Источник: apps/measurements/base.
|
||||||
@ -515,3 +599,11 @@ volumes:
|
|||||||
sarex-redis-data:
|
sarex-redis-data:
|
||||||
sarex-rabbitmq-data:
|
sarex-rabbitmq-data:
|
||||||
sarex-minio-data:
|
sarex-minio-data:
|
||||||
|
|
||||||
|
# Дефолтной сети задаём фиксированный subnet, чтобы закрепить IP за postgres/minio.
|
||||||
|
# На эти адреса ссылаются k8s-Endpoints DNS-моста (namespace processing в k3s).
|
||||||
|
networks:
|
||||||
|
default:
|
||||||
|
ipam:
|
||||||
|
config:
|
||||||
|
- subnet: 172.28.0.0/16
|
||||||
@ -0,0 +1,499 @@
|
|||||||
|
# workflows-engine через k3s (планирование Job'ов) — Implementation Plan
|
||||||
|
|
||||||
|
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||||||
|
|
||||||
|
**Goal:** Добавить в контур `workflows-engine` как сервис docker-compose, который через kubeconfig-контекст создаёт Job'ы в k3s; Job-поды резолвят `postgres`/`minio` из compose-сети через k8s DNS-мост.
|
||||||
|
|
||||||
|
**Architecture:** engine — обычный compose-контейнер (до `workflow_db` ходит по compose-DNS), в k3s ходит out-of-cluster (`KUBE_CONFIG`+`KUBE_ADDR`). В namespace `processing` k3s заводятся Service+Endpoints `postgres`/`minio` на статические IP compose-контейнеров, чтобы Job-поды достукивались до БД и S3. Поднимаем только `k3s-server`.
|
||||||
|
|
||||||
|
**Tech Stack:** Docker Compose, k3s (rancher/k3s v1.36), kubectl, Ansible (роль `sarex_stack`), Go-сервис workflows-engine (конфиг через env, cleanenv).
|
||||||
|
|
||||||
|
**Спека:** `docs/superpowers/specs/2026-07-30-processing-engine-k3s-scheduling-design.md`
|
||||||
|
|
||||||
|
## Global Constraints
|
||||||
|
|
||||||
|
- Целевой хост — RedOS 8 (SELinux → volume-флаги `:z`/`:ro,z`), деплой из WSL через ansible роль `sarex_stack`.
|
||||||
|
- Все образы параметризуются `${VAR:-default}`; секреты — через `.env`, генерятся ролью.
|
||||||
|
- Только `k3s-server` (без `k3s-worker`). Downstream `ENABLE_*` engine выключены, кроме `ENABLE_S3_STORAGE`.
|
||||||
|
- Статические IP в compose: `postgres` = `172.28.0.10`, `minio` = `172.28.0.11`, subnet `172.28.0.0/16`.
|
||||||
|
- Имена в k8s = compose-имена: `postgres`, `minio`, namespace `processing`.
|
||||||
|
- Образ engine: `${SAREX_WORKFLOWS_ENGINE_IMAGE:-cr.yandex/crp3ccidau046kdj8g9q/workflows-endigne_prod:075fc0}`.
|
||||||
|
- Проверки инфраструктуры — не pytest: валидация `docker compose config -q`, `kubectl --dry-run`, коннект-чек по логам. Каждая задача завершается коммитом.
|
||||||
|
|
||||||
|
## File Structure
|
||||||
|
|
||||||
|
- `iac/docker-compose.yaml` (Modify) — top-level `networks.default` IPAM; static IP у `postgres`/`minio`; сервисы `engine`, `processing-k8s-init`.
|
||||||
|
- `iac/.env.example` (Modify) — `SAREX_WORKFLOWS_ENGINE_IMAGE`.
|
||||||
|
- `iac/k3s/manifests/processing/namespace.yaml` (Create) — namespace `processing`.
|
||||||
|
- `iac/k3s/manifests/processing/bridge-postgres.yaml` (Create) — Service+Endpoints `postgres`.
|
||||||
|
- `iac/k3s/manifests/processing/bridge-minio.yaml` (Create) — Service+Endpoints `minio`.
|
||||||
|
- `iac/backend/yc-s3-service-account.json` → нет; S3 SA кладём в `iac/engine/yc-s3-service-account.json` (Create, плейсхолдер на `http://minio:9000`).
|
||||||
|
- `iac/aero/roles/sarex_stack/tasks/main.yml` (Modify) — копирование `k3s/manifests` и `engine/`.
|
||||||
|
- `iac/aero/roles/sarex_stack/defaults/main.yml` (Modify) — `sarex_services` += `k3s-server`, `processing-k8s-init`, `engine`.
|
||||||
|
- `iac/aero/pyproject.toml` (Modify) — poe-таск проверки k8s-моста (опц.).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Task 1: Параметр образа engine + S3 SA-плейсхолдер
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Modify: `iac/.env.example`
|
||||||
|
- Create: `iac/engine/yc-s3-service-account.json`
|
||||||
|
|
||||||
|
**Interfaces:**
|
||||||
|
- Produces: env-переменная `SAREX_WORKFLOWS_ENGINE_IMAGE`; файл SA `iac/engine/yc-s3-service-account.json`, монтируемый в engine на `/etc/sarex/yc-s3/yc-s3-service-account.json`.
|
||||||
|
|
||||||
|
- [ ] **Step 1: Добавить переменную образа в `.env.example`**
|
||||||
|
|
||||||
|
В секцию образов `iac/.env.example` добавить строку:
|
||||||
|
|
||||||
|
```dotenv
|
||||||
|
# workflows-engine (processing) — оркестратор Job'ов в k3s
|
||||||
|
SAREX_WORKFLOWS_ENGINE_IMAGE=cr.yandex/crp3ccidau046kdj8g9q/workflows-endigne_prod:075fc0
|
||||||
|
```
|
||||||
|
|
||||||
|
- [ ] **Step 2: Создать плейсхолдер S3 service-account JSON**
|
||||||
|
|
||||||
|
`iac/engine/yc-s3-service-account.json` (endpoint на прямой MinIO; app-креды подставит рантайм/ansible — тут плейсхолдер для планирования):
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"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
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
- [ ] **Step 3: Проверка — файл валидный JSON**
|
||||||
|
|
||||||
|
Run: `python -c "import json;json.load(open('iac/engine/yc-s3-service-account.json'));print('ok')"`
|
||||||
|
Expected: `ok`
|
||||||
|
|
||||||
|
- [ ] **Step 4: Commit**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git add iac/.env.example iac/engine/yc-s3-service-account.json
|
||||||
|
git commit -m "feat(engine): образ workflows-engine + S3 SA-плейсхолдер"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Task 2: Compose-сеть со статическими IP для postgres/minio
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Modify: `iac/docker-compose.yaml`
|
||||||
|
|
||||||
|
**Interfaces:**
|
||||||
|
- Produces: `postgres` доступен по `172.28.0.10`, `minio` по `172.28.0.11` в сети `default` (subnet `172.28.0.0/16`). На эти IP ссылаются k8s-Endpoints (Task 4).
|
||||||
|
|
||||||
|
- [ ] **Step 1: Добавить top-level `networks` c IPAM**
|
||||||
|
|
||||||
|
В конец `iac/docker-compose.yaml` (рядом с `volumes:`) добавить:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
networks:
|
||||||
|
default:
|
||||||
|
ipam:
|
||||||
|
config:
|
||||||
|
- subnet: 172.28.0.0/16
|
||||||
|
```
|
||||||
|
|
||||||
|
- [ ] **Step 2: Пин статического IP у `postgres`**
|
||||||
|
|
||||||
|
В сервис `postgres` добавить блок `networks`:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
networks:
|
||||||
|
default:
|
||||||
|
ipv4_address: 172.28.0.10
|
||||||
|
```
|
||||||
|
|
||||||
|
- [ ] **Step 3: Пин статического IP у `minio`**
|
||||||
|
|
||||||
|
В сервис `minio` добавить:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
networks:
|
||||||
|
default:
|
||||||
|
ipv4_address: 172.28.0.11
|
||||||
|
```
|
||||||
|
|
||||||
|
- [ ] **Step 4: Проверка — конфиг валиден и IP на месте**
|
||||||
|
|
||||||
|
Run (в `iac/`): `docker compose --env-file .env.example config | grep -A3 -E "ipv4_address|subnet"`
|
||||||
|
Expected: видно `subnet: 172.28.0.0/16`, `ipv4_address: 172.28.0.10` и `172.28.0.11`.
|
||||||
|
(Если docker недоступен локально — выполнить на сервере в `deploy_dir` после копирования.)
|
||||||
|
|
||||||
|
- [ ] **Step 5: Commit**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git add iac/docker-compose.yaml
|
||||||
|
git commit -m "feat(net): статические IP postgres/minio для k8s-моста"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Task 3: k8s-манифесты DNS-моста (namespace + Service/Endpoints)
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Create: `iac/k3s/manifests/processing/namespace.yaml`
|
||||||
|
- Create: `iac/k3s/manifests/processing/bridge-postgres.yaml`
|
||||||
|
- Create: `iac/k3s/manifests/processing/bridge-minio.yaml`
|
||||||
|
|
||||||
|
**Interfaces:**
|
||||||
|
- Consumes: статические IP из Task 2 (`172.28.0.10`, `172.28.0.11`).
|
||||||
|
- Produces: в namespace `processing` резолвятся имена `postgres:5432` и `minio:9000` (→ compose-контейнеры).
|
||||||
|
|
||||||
|
- [ ] **Step 1: namespace**
|
||||||
|
|
||||||
|
`iac/k3s/manifests/processing/namespace.yaml`:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: processing
|
||||||
|
```
|
||||||
|
|
||||||
|
- [ ] **Step 2: мост postgres (Service без селектора + Endpoints)**
|
||||||
|
|
||||||
|
`iac/k3s/manifests/processing/bridge-postgres.yaml`:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
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
|
||||||
|
```
|
||||||
|
|
||||||
|
- [ ] **Step 3: мост minio**
|
||||||
|
|
||||||
|
`iac/k3s/manifests/processing/bridge-minio.yaml`:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
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
|
||||||
|
```
|
||||||
|
|
||||||
|
- [ ] **Step 4: Проверка — YAML валиден (клиентский dry-run)**
|
||||||
|
|
||||||
|
Run (при наличии kubectl; иначе отложить на сервер):
|
||||||
|
`kubectl apply --dry-run=client -f iac/k3s/manifests/processing/`
|
||||||
|
Expected: `namespace/processing created (dry run)`, `service/postgres ...`, `endpoints/postgres ...`, `service/minio ...`, `endpoints/minio ...`.
|
||||||
|
Fallback без kubectl: `python -c "import glob,yaml; [list(yaml.safe_load_all(open(f))) for f in glob.glob('iac/k3s/manifests/processing/*.yaml')]; print('ok')"` → `ok`.
|
||||||
|
|
||||||
|
- [ ] **Step 5: Commit**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git add iac/k3s/manifests/processing/
|
||||||
|
git commit -m "feat(k3s): DNS-мост postgres/minio в namespace processing"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Task 4: Сервис `processing-k8s-init` (применение манифестов)
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Modify: `iac/docker-compose.yaml`
|
||||||
|
|
||||||
|
**Interfaces:**
|
||||||
|
- Consumes: манифесты `./k3s/manifests/processing/` (Task 3), kubeconfig `./k3s/kubeconfig.yaml` (пишется `k3s-server`).
|
||||||
|
- Produces: applied namespace + мост в k3s; сервис завершается успешно (barrier для engine).
|
||||||
|
|
||||||
|
- [ ] **Step 1: Добавить сервис-хелпер (переиспользуем образ k3s — в нём есть kubectl)**
|
||||||
|
|
||||||
|
В `iac/docker-compose.yaml` (после `k3s-worker`/до `gitea` или рядом с processing-сервисами) добавить:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# Одноразовый провижининг k3s: namespace processing + DNS-мост postgres/minio.
|
||||||
|
# Образ k3s содержит kubectl; server/tls перекрываем на k3s-server:6443.
|
||||||
|
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
|
||||||
|
```
|
||||||
|
|
||||||
|
- [ ] **Step 2: Проверка — конфиг валиден**
|
||||||
|
|
||||||
|
Run (в `iac/`): `docker compose --env-file .env.example config --services | grep processing-k8s-init`
|
||||||
|
Expected: `processing-k8s-init`.
|
||||||
|
|
||||||
|
- [ ] **Step 3: Commit**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git add iac/docker-compose.yaml
|
||||||
|
git commit -m "feat(k3s): processing-k8s-init — применение DNS-моста через kubectl"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Task 5: Сервис `engine` в docker-compose
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Modify: `iac/docker-compose.yaml`
|
||||||
|
|
||||||
|
**Interfaces:**
|
||||||
|
- Consumes: `k3s-server` (kube-API), `processing-k8s-init` (мост applied), `postgres`/`postgres-init` (`workflow_db`), kubeconfig `./k3s/kubeconfig.yaml`, S3 SA `./engine/yc-s3-service-account.json` (Task 1).
|
||||||
|
- Produces: работающий оркестратор, создающий Job'ы в namespace `processing`.
|
||||||
|
|
||||||
|
- [ ] **Step 1: Добавить сервис `engine`**
|
||||||
|
|
||||||
|
В `iac/docker-compose.yaml` рядом с processing-сервисами:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# workflows-engine — оркестратор: читает workflow_db, создаёт Job'ы в k3s.
|
||||||
|
# Ходит в k3s out-of-cluster (KUBE_CONFIG+KUBE_ADDR). K8s-исполнитель; AMQP выкл.
|
||||||
|
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
|
||||||
|
# исполнители
|
||||||
|
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)
|
||||||
|
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
|
||||||
|
ENABLE_S3_STORAGE: "1"
|
||||||
|
S3_SERVICE_ACCOUNT: /etc/sarex/yc-s3/yc-s3-service-account.json
|
||||||
|
# дефолты планирования подов
|
||||||
|
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
|
||||||
|
```
|
||||||
|
|
||||||
|
- [ ] **Step 2: Проверка — конфиг рендерится, образ и зависимости на месте**
|
||||||
|
|
||||||
|
Run (в `iac/`): `docker compose --env-file .env.example config | grep -A2 "container_name: engine"`
|
||||||
|
Expected: сервис `engine` с образом `workflows-endigne_prod`.
|
||||||
|
Run: `docker compose --env-file .env.example config | grep -E "KUBE_ADDR|JOBS_NAMESPACE"`
|
||||||
|
Expected: `KUBE_ADDR: https://k3s-server:6443`, `JOBS_NAMESPACE: processing`.
|
||||||
|
|
||||||
|
- [ ] **Step 3: Commit**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git add iac/docker-compose.yaml
|
||||||
|
git commit -m "feat(engine): сервис workflows-engine (k8s-исполнитель через kubeconfig)"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Task 6: Интеграция в Ansible-роль
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Modify: `iac/aero/roles/sarex_stack/defaults/main.yml`
|
||||||
|
- Modify: `iac/aero/roles/sarex_stack/tasks/main.yml`
|
||||||
|
|
||||||
|
**Interfaces:**
|
||||||
|
- Consumes: файлы Task 1-5 в репозитории `iac/`.
|
||||||
|
- Produces: `poe stack`/`install` копирует манифесты и `engine/`, поднимает `k3s-server`, `processing-k8s-init`, `engine`.
|
||||||
|
|
||||||
|
- [ ] **Step 1: Добавить сервисы в `sarex_services`**
|
||||||
|
|
||||||
|
В `iac/aero/roles/sarex_stack/defaults/main.yml`, список `sarex_services`, добавить (порядок не критичен — `depends_on` рулит; но добавим осмысленно):
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- k3s-server
|
||||||
|
- processing-k8s-init
|
||||||
|
```
|
||||||
|
и после `celery` (или рядом с processing) добавить:
|
||||||
|
```yaml
|
||||||
|
- engine
|
||||||
|
```
|
||||||
|
|
||||||
|
- [ ] **Step 2: Копировать каталог `k3s/manifests` на хост**
|
||||||
|
|
||||||
|
В `iac/aero/roles/sarex_stack/tasks/main.yml`, рядом с копированием nginx/backend, добавить задачу:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- name: Скопировать k3s-манифесты (DNS-мост processing)
|
||||||
|
ansible.builtin.copy:
|
||||||
|
src: "{{ deploy_src_root }}/k3s/manifests/"
|
||||||
|
dest: "{{ deploy_dir }}/k3s/manifests/"
|
||||||
|
mode: "0644"
|
||||||
|
```
|
||||||
|
|
||||||
|
- [ ] **Step 3: Копировать каталог `engine/` (S3 SA) на хост**
|
||||||
|
|
||||||
|
Там же добавить:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- name: Скопировать конфиги engine (S3 service-account)
|
||||||
|
ansible.builtin.copy:
|
||||||
|
src: "{{ deploy_src_root }}/engine/"
|
||||||
|
dest: "{{ deploy_dir }}/engine/"
|
||||||
|
mode: "0644"
|
||||||
|
```
|
||||||
|
|
||||||
|
- [ ] **Step 4: Проверка — YAML роли валиден и сервисы в списке**
|
||||||
|
|
||||||
|
Run (в `iac/aero/`): `uv run python -c "import yaml;d=yaml.safe_load(open('roles/sarex_stack/defaults/main.yml'));assert {'k3s-server','processing-k8s-init','engine'} <= set(d['sarex_services']);print('services ok')"`
|
||||||
|
Expected: `services ok`.
|
||||||
|
Run: `uv run python -c "import yaml;list(yaml.safe_load_all(open('roles/sarex_stack/tasks/main.yml')));print('tasks ok')"`
|
||||||
|
Expected: `tasks ok`.
|
||||||
|
|
||||||
|
- [ ] **Step 5: Commit**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git add iac/aero/roles/sarex_stack/defaults/main.yml iac/aero/roles/sarex_stack/tasks/main.yml
|
||||||
|
git commit -m "feat(ansible): деплой engine + k3s DNS-моста в роли sarex_stack"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Task 7: Развёртывание и проверка планирования на сервере
|
||||||
|
|
||||||
|
**Files:** (нет изменений кода — деплой и верификация)
|
||||||
|
|
||||||
|
**Interfaces:**
|
||||||
|
- Consumes: всё выше, ветка `aero`, доступ к хосту через ansible из WSL.
|
||||||
|
|
||||||
|
- [ ] **Step 1: Задеплоить файлы и поднять стек**
|
||||||
|
|
||||||
|
Run (в `iac/aero/`, WSL): `uv run poe stack`
|
||||||
|
(копирует compose/манифесты/.env, `docker compose up -d` включая `k3s-server`, `processing-k8s-init`, `engine`.)
|
||||||
|
Expected: playbook завершается без ошибок; `changed`.
|
||||||
|
|
||||||
|
- [ ] **Step 2: Проверить, что k3s-server поднялся**
|
||||||
|
|
||||||
|
Run: `uv run poe ps` (или ad-hoc `docker compose ps`)
|
||||||
|
Expected: `k3s-server` в статусе `Up (healthy)`; `processing-k8s-init` — `Exited (0)`; `engine` — `Up`.
|
||||||
|
|
||||||
|
- [ ] **Step 3: Проверить DNS-мост в k3s**
|
||||||
|
|
||||||
|
Run (ad-hoc на хосте): `docker exec k3s-server kubectl -n processing get svc,endpoints`
|
||||||
|
Expected: Service `postgres`, `minio` и Endpoints с адресами `172.28.0.10:5432`, `172.28.0.11:9000`.
|
||||||
|
|
||||||
|
- [ ] **Step 4: Проверить коннект engine к workflow_db и kube-API**
|
||||||
|
|
||||||
|
Run: `uv run poe logs engine --tail 120`
|
||||||
|
Expected: в логах — успешное подключение к Postgres и к kube-API, нет паник (`failed to parse`, `connection refused`, `panic`).
|
||||||
|
Если engine падает на старте — сверить с риском №2 спеки (downstream `ENABLE_*`) и №1 (`KUBE_ADDR` vs правка `server:` в kubeconfig).
|
||||||
|
|
||||||
|
- [ ] **Step 5: Проверить резолв имён из тестового пода в k3s**
|
||||||
|
|
||||||
|
Run:
|
||||||
|
```bash
|
||||||
|
docker exec k3s-server kubectl -n processing run netcheck --rm -it --restart=Never \
|
||||||
|
--image=busybox:1.36 -- sh -c "nslookup postgres; nc -z -w3 postgres 5432 && echo PG_OK; nc -z -w3 minio 9000 && echo S3_OK"
|
||||||
|
```
|
||||||
|
Expected: `postgres` резолвится в ClusterIP, `PG_OK`, `S3_OK` (под достучался до compose-postgres/minio через мост).
|
||||||
|
|
||||||
|
- [ ] **Step 6: Проверить планирование Job'а**
|
||||||
|
|
||||||
|
Инициировать workflow (через processing-api/фронт или тестовую запись в `workflow_db`), затем:
|
||||||
|
Run: `docker exec k3s-server kubectl -n processing get jobs,pods`
|
||||||
|
Expected: появляется Job-объект, под запланирован на ноду (статус `Running`/`ContainerCreating`/`ImagePullBackOff` — любой из них подтверждает планирование; успешный прогон конвертации — вне рамок).
|
||||||
|
|
||||||
|
- [ ] **Step 7: Зафиксировать результат**
|
||||||
|
|
||||||
|
Никаких изменений кода; при необходимости — записать в память проекта факт готовности планирования и оставшиеся follow-up (валидный S3 SA, downstream-сервисы, образы задач).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Self-Review
|
||||||
|
|
||||||
|
**1. Spec coverage:**
|
||||||
|
- Компонент A (engine compose) → Task 1, 5. ✓
|
||||||
|
- Компонент B (только k3s-server) → Task 6 (`sarex_services`), Task 7 (проверка). ✓
|
||||||
|
- Компонент C (DNS-мост postgres/minio) → Task 3, 4. ✓
|
||||||
|
- Сеть/статические IP → Task 2. ✓
|
||||||
|
- Ansible-интеграция → Task 6. ✓
|
||||||
|
- Порядок провижининга → `depends_on` (Task 4, 5) + Task 7. ✓
|
||||||
|
- Риски (KUBE_ADDR, стартовые проверки, S3 SA, образ задачи, cgroup/SELinux) → Task 7 Step 4/6 отсылают к рискам спеки. ✓
|
||||||
|
- Проверка результата (svc/endpoints, логи, jobs) → Task 7. ✓
|
||||||
|
|
||||||
|
**2. Placeholder scan:** S3 SA — намеренный плейсхолдер (задокументирован в спеке как приемлемый для планирования), не «TODO в требовании». Остальное — конкретный контент. ✓
|
||||||
|
|
||||||
|
**3. Type consistency:** имена согласованы сквозняком — `172.28.0.10`/`172.28.0.11`, namespace `processing`, Service/Endpoints `postgres`/`minio`, env `KUBE_ADDR=https://k3s-server:6443`, `JOBS_NAMESPACE=processing`, образ `workflows-endigne_prod:075fc0`. ✓
|
||||||
|
|
||||||
|
**Открытый нюанс для исполнителя:** если engine НЕ принимает `KUBE_ADDR` как override (риск №1), fallback — в `processing-k8s-init`/отдельном шаге sed-правкой заменить `server: https://127.0.0.1:6443` на `https://k3s-server:6443` в `./k3s/kubeconfig.yaml` и снять `KUBE_ADDR`, оставив `KUBE_CONFIG`+`KUBE_CONTEXT`.
|
||||||
@ -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-сервисов.
|
||||||
8
engine/yc-s3-service-account.json
Normal file
8
engine/yc-s3-service-account.json
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"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
|
||||||
|
}
|
||||||
26
k3s/manifests/processing/bridge-minio.yaml
Normal file
26
k3s/manifests/processing/bridge-minio.yaml
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
# 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
|
||||||
26
k3s/manifests/processing/bridge-postgres.yaml
Normal file
26
k3s/manifests/processing/bridge-postgres.yaml
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
# 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
|
||||||
4
k3s/manifests/processing/namespace.yaml
Normal file
4
k3s/manifests/processing/namespace.yaml
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: processing
|
||||||
Loading…
Reference in New Issue
Block a user