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

13 KiB
Raw Permalink Blame History

🏗️ Архітектура для 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:

{
  "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. Ротація секретів + прибрати креденшали з документів/репо

  • Видалено паролі з документів
  • Ротація Cohere API key
  • Ротація паролів Postgres/Neo4j
  • Оновлення в Vault

2. Закрити зовнішній доступ до NodePort

  • NodePort закрито для Memory Service NODE1
  • Додати JWT/mTLS auth
  • NetworkPolicy для internal-only

3. Підняти NATS JetStream (Tier A)

  • Створено K8s deployment (3 replicas + PVC + auth)
  • Створено streams definitions (MM_ONLINE, MM_OFFLINE, MM_WRITE, MM_EVENTS)
  • Створено job payload schema (JSON v1)
  • Створено 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