Files
microdao-daarion/ARCHITECTURE-150-NODES.md
Apple 8fe0b58978 🚀 NATS JetStream: K8s deployment + streams + job schema v1
- K8s deployment (2 replicas, PVC, initContainer для server_name)
- Streams definitions (MM_ONLINE, MM_OFFLINE, MM_WRITE, MM_EVENTS)
- Job payload schema (JSON v1 з idempotency)
- Worker contract (capabilities + ack/retry)
- Init streams script
- Оновлено ARCHITECTURE-150-NODES.md (Control-plane vs Data-plane)

TODO: Auth (nkeys), 3+ replicas для prod, worker-daemon implementation
2026-01-10 10:02:25 -08:00

383 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 🏗️ Архітектура для 150 нод — DAARION
**Дата:** 2026-01-10
**Версія:** 1.0.0
---
## 🎯 Принципи архітектури
### Ключова ідея
**Не стандартизувати GPU**, а стандартизувати **контракт виконання**:
- Як задачі розподіляються
- Як воркери звітують
- Як відбувається retry/ack
- Як гарантується однакова якість (модель/версія) та безпека
Різне "залізо" стає різними **tiers** воркерів.
---
## 🎛️ Control-plane vs Data-plane
### Control-plane (людський + командний)
**Matrix Rooms** = контроль, команди, статуси, аудит
**Призначення:**
- Команди користувачів/агентів
- Статуси виконання (progress + summary)
- Ручне керування
- Аудит рішень
- Оповіщення про помилки/алерти
**НЕ використовується для:**
- Високочастотної job-шини
- Масових обчислень
- Real-time streaming даних
### Data-plane (масові таски, fan-out/fan-in)
**NATS JetStream** = черга задач, розподіл обчислень
**Призначення:**
- Розподіл jobs між воркерами
- Fan-out/fan-in обчислень
- Retry/ack механізми
- Пріоритизація (online/offline)
- Idempotency гарантії
**Переваги:**
- Легкий (менше ресурсів ніж Kafka)
- Швидкий (low latency)
- Простіший для старту
- At-least-once delivery
- Підтримка idempotency keys
### State & Index
**PostgreSQL** = state (організації, користувачі, threads, events)
**Qdrant** = retrieval index (semantic search)
**Neo4j** = graph relationships
---
## 📊 Поточна структура БД (що правильно, що треба виправити)
### PostgreSQL
**Зараз:**
- NODE1 = CloudNativePG (K8s) ✅
- NODE2/3 = Docker (dev/edge)
**Правильний фундамент:**
- **Один primary Postgres у Tier A** (NODE1/K8s) + репліки
- NODE2/3 Postgres у Docker — залишити як dev/edge, але **не як "другий прод-primary"**
**Що робити:**
- [ ] Якщо NODE3 потрібен як DR/replica: робіть **стрімінг-репліку** з primary (NODE1) на NODE3
- [ ] Для k8s-primary: тримати репліки теж у k8s (CloudNativePG)
- [ ] NODE3 використовувати для backup/restore і окремих offline задач
### Qdrant
**Зараз:** 3 інсталяції (k8s + 2 docker)
**Правильно:**
- [ ] Один **prod Qdrant cluster** (Tier A) на NODE1
- [ ] Edge Qdrant (NODE2/3) — лише для локального тесту або кешу, але не "істина"
### Neo4j
**Зараз:** Neo4j на всіх нодах (k8s + docker)
**Рекомендація:**
- [ ] Тримати **один Neo4j** у Tier A (NODE1) як прод
- [ ] NODE2/3 — dev
- [ ] Кластеризацію Neo4j відкласти, поки не буде реальної потреби в HA саме графа
---
## 🔄 Паралельні обчислення між нодами
### A) Control-plane (людський + командний) = Matrix rooms
**Призначення:**
- Команди
- Статуси
- Ручне керування
- Аудит рішень
**НЕ використовується для:**
- Високочастотної job-шини
- Масових обчислень
### B) Data-plane (масові таски, fan-out) = NATS JetStream
**Вибір:** **NATS JetStream** (легкий, швидкий, простіший за Kafka для старту)
**Переваги:**
- Легкий (менше ресурсів)
- Швидкий (low latency)
- Простіший для старту
- Підтримує at-least-once delivery
- Підтримує idempotency keys
### C) Capability registry (хто що вміє) = Consul або Postgres
**Кожен воркер реєструється з capabilities:**
```json
{
"node_id": "node-123",
"tier": "A|B|C",
"region": "eu-west",
"trust_zone": "internal",
"hardware": {
"cpu_cores": 32,
"ram_gb": 128,
"gpu": true,
"gpu_model": "RTX 3090",
"vram_gb": 24,
"cuda_version": "13.0"
},
"capabilities": {
"max_batch": 1000,
"max_tokens": 8192,
"models": ["embed-multilingual-v3.0", "llama3:8b"],
"embedding_dim": 1024
},
"status": "ready|busy|maintenance",
"last_heartbeat": "2026-01-10T19:30:00Z"
}
```
---
## 🔗 Зв'язок Matrix rooms з паралельними воркерами
### Правильний потік:
```
1. Команда/подія → Matrix room (кімната агента або оркестратора)
2. Matrix Gateway (сервіс або модуль у Memory Service)
- RBAC перевірка в Postgres
- Створює Job у NATS (з idempotency key)
3. Воркер на відповідній ноді
- Бере job з NATS
- Виконує задачу
- Пише результат у Postgres/Qdrant/Neo4j
4. Gateway публікує статус назад у Matrix
- Progress + summary → Matrix
- Детальні логи → система логів (Loki)
```
**Результат:** "Безперервний діалог" і керування через Matrix, але обчислення реально паралеляться через чергу.
---
## 📦 NATS JetStream: Streams + Consumers
### Streams (4 основні)
#### STREAM `MM_ONLINE`
- **Subjects:** `mm.embed.online`, `mm.retrieve.online`, `mm.summarize.online`
- **Retention:** limits
- **MaxAge:** 30 хв (або 2 год)
- **Ack:** explicit
- **MaxDeliver:** 3
- **Backoff:** 1s, 5s, 30s
- **Replicas:** 3
#### STREAM `MM_OFFLINE`
- **Subjects:** `mm.embed.offline`, `mm.index.offline`, `mm.backfill.offline`
- **Retention:** limits
- **MaxAge:** 7-30 днів
- **MaxDeliver:** 10
- **Backoff:** 10s, 1m, 5m, 30m
- **Replicas:** 3
#### STREAM `MM_WRITE`
- **Subjects:** `mm.qdrant.upsert`, `mm.pg.write`, `mm.neo4j.write`
- **Retention:** limits
- **MaxAge:** 1-7 днів
- **MaxDeliver:** 10
- **Replicas:** 3
#### STREAM `MM_EVENTS`
- **Subjects:** `mm.event.audit`, `mm.event.status`
- **Retention:** limits
- **MaxAge:** 7-30 днів
- **Replicas:** 3
### Consumer Policies
#### Online Consumer (Tier A)
- **Stream:** `MM_ONLINE`
- **Consumer:** `online-worker-tier-a`
- **Ack Wait:** 30s
- **Max Ack Pending:** 5000
- **Concurrency:** 50-200 (per worker)
- **Filter:** `tier=A` AND `needs_gpu=true` (для GPU jobs)
#### Offline Consumer (Tier B)
- **Stream:** `MM_OFFLINE`
- **Consumer:** `offline-worker-tier-b`
- **Ack Wait:** 5-30 хв
- **Max Ack Pending:** 10000
- **Concurrency:** висока, але з backpressure
- **Preemption:** можливе призупинення для online jobs
### Job Payload Schema
Детальна схема: `infrastructure/nats/job-payload-schema.json`
**Ключові поля:**
- `job_id` (ULID)
- `idempotency_key` (SHA256 hash) — обов'язково для safe retries
- `type` (embed|retrieve|summarize|qdrant_upsert|pg_write|neo4j_write|index)
- `priority` (online|offline)
- `requirements` (needs_gpu, min_vram_gb, max_latency_ms, tier)
- `tenant` (org_id, workspace_id)
- `scope` (user_id, agent_id, thread_id)
- `input` (text, model, dims)
- `refs` (event_id, memory_id, artifact_uri)
- `trace` (trace_id, parent_span_id)
- `timestamps` (created_at, deadline)
---
## 🎚️ Використання різних нод (Tier A/B/C)
### Поточна класифікація:
| Node | Hardware | Tier | Призначення |
|------|----------|------|-------------|
| **NODE1** | RTX 4000 Ada 20GB | **A** | Online critical, primary DB |
| **NODE3** | RTX 3090 24GB | **A/B** | Online + offline, heavy jobs |
| **NODE2** | Apple M4 | **C** | Orchestration/dev/offline prep |
### Розподіл задач:
- **Online embeddings/LLM** → NODE1 + NODE3
- **Offline backfill** → NODE3 + інші GPU edge ноди
- **NODE2** → Orchestration, тестування, підготовка чанків, локальні агентні сесії
---
## 🔐 Embeddings: Cohere vs BGE-M3
### Правило:
**Одна колекція Qdrant = один embedding space** (модель + версія + dims)
### Поточна ситуація:
- **Cohere embed-multilingual-v3.0** (1024 dim) — використовується
### Якщо переходите на BGE-M3:
- [ ] Створити нову колекцію: `memories_bge_m3_v1` (1024 dim)
- [ ] Або додати `model_version` і фізично рознести колекції
- [ ] **НЕ змішувати** embedding-простори в одній колекції
---
## 📈 Метрики та Алерти
### NATS JetStream Metrics
- `nats_consumer_lag{stream, consumer}` — backlog по streams
- `nats_redeliveries_total{stream}` — кількість retries
- `nats_ack_pending{stream, consumer}` — jobs в обробці
- `nats_stream_storage_bytes{stream}` — використання диску
### Worker Metrics
- `worker_jobs_processed_total{type, status}` — загальна кількість jobs
- `worker_job_duration_seconds{type, quantile}` — latency (p50, p95, p99)
- `worker_gpu_utilization{node_id}` — використання GPU
- `worker_vram_usage_bytes{node_id}` — використання VRAM
- `worker_errors_total{type, error_type}` — помилки
### Алерти → Matrix Ops Room
**Критичні:**
- `MM_ONLINE backlog > 1000` — SLO порушення
- `redeliveries spike > 100/min` — проблеми з воркерами
- `embed p95 > 500ms` (target: 300ms)
- `disk > 80%` на JetStream PVC
- `worker offline > 2 min` (Tier A)
**Попередження:**
- `MM_OFFLINE backlog > 10000`
- `ack_pending > 80% max_ack_pending`
- `worker_gpu_utilization < 20%` (Tier A, протягом 10+ хв)
---
## 📋 Наступні 7 кроків (по порядку)
### 1. ✅ Ротація секретів + прибрати креденшали з документів/репо
- [x] Видалено паролі з документів
- [ ] Ротація Cohere API key
- [ ] Ротація паролів Postgres/Neo4j
- [ ] Оновлення в Vault
### 2. ✅ Закрити зовнішній доступ до NodePort
- [x] NodePort закрито для Memory Service NODE1
- [ ] Додати JWT/mTLS auth
- [ ] NetworkPolicy для internal-only
### 3. ✅ Підняти NATS JetStream (Tier A)
- [x] Створено K8s deployment (3 replicas + PVC + auth)
- [x] Створено streams definitions (MM_ONLINE, MM_OFFLINE, MM_WRITE, MM_EVENTS)
- [x] Створено job payload schema (JSON v1)
- [x] Створено worker contract (capabilities + ack/retry)
- [ ] Застосувати deployment в K8s
- [ ] Налаштувати operator JWT + system account
- [ ] Створити streams через NATS CLI або API
### 4. Додати worker-daemon на кожну ноду
- [ ] Heartbeat до capability registry
- [ ] Capabilities (hardware, models, tier)
- [ ] Підписка на черги NATS
- [ ] Job execution + результат
### 5. Matrix Gateway
- [ ] Команди/статуси ↔ jobs у NATS
- [ ] RBAC перевірка
- [ ] Публікація результатів назад у Matrix
### 6. Рознести embedding-простори
- [ ] Визначити стратегію (Cohere vs BGE-M3)
- [ ] Створити окремі колекції або міграцію
### 7. Postgres: визначити один primary + репліки
- [ ] NODE1 = primary (CloudNativePG)
- [ ] NODE3 = streaming replica (якщо потрібен DR)
- [ ] Backup/restore стратегія
---
## 📁 Структура файлів
```
infrastructure/
├── nats/
│ ├── deployment.yaml # NATS JetStream в K8s
│ ├── streams.yaml # Конфігурація streams
│ └── accounts.yaml # NATS accounts (якщо потрібно)
├── worker-daemon/
│ ├── deployment.yaml # Worker daemon для кожної ноди
│ ├── capability-registry.py # Реєстрація capabilities
│ └── job-executor.py # Виконання jobs
└── matrix-gateway/
├── deployment.yaml # Matrix Gateway service
├── gateway.py # Matrix ↔ NATS bridge
└── rbac.py # RBAC перевірка
```
---
*Документ створено: 2026-01-10 19:30 CET*