# État réel du cluster Funk — snapshot vérifié

> Relevé **2026-06-23** directement sur les machines (SSH s01/g01 + `kubectl`). Ce document
> reflète l'état **observé**, pas l'état *souhaité* de l'IaC — en cas d'écart, les écarts connus
> sont signalés (⚠️). Pour la procédure de relevé, voir la fin du fichier.
>
> 🔁 **Depuis le 21/06** : ajout de **SearXNG** (recherche web in-cluster, ns `ai`) ; le STT‑server
> est devenu **agentique** (contexte `asa` par défaut : function calling — doc, état live, web,
> actions Hermes). Détails : `admin/ia/stt.md`.

---

## Machines

| Machine | IP | OS / kernel | Uptime relevé | Rôle |
|---|---|---|---|---|
| storage-01 | 192.168.10.1 (LAN) / 192.168.1.200 (WAN) | AlmaLinux **9.8** (Olive Jaguar), `5.14.0-687.5.3.el9_8` | 20 j | Passerelle + bastion + données + IA hors-cluster |
| gpu-01 | 192.168.10.20 | AlmaLinux **9.8**, `5.14.0-687.5.3.el9_8` | — | llama-server (RX 6700XT, ROCm 7.x) hors-cluster |
| compute-01 | 192.168.10.11 | Talos v1.13 / **k8s v1.33.1** | 40 j | k8s control-plane |
| compute-02 | 192.168.10.12 | Talos v1.13 / **k8s v1.33.1** | 40 j | k8s worker |
| compute-03 | 192.168.10.13 | Talos v1.13 / **k8s v1.33.1** | 40 j | k8s worker |

> ⚠️ `CLAUDE.md` indiquait AlmaLinux **9.7** pour s01/g01 — la réalité est **9.8**.

---

## storage-01 — services actifs (systemd)

| Service | Port(s) écoute | Rôle |
|---|---|---|
| `litellm` | `0.0.0.0:4000` | Proxy multi-modèles (Hermes + ask-agent + STT-server) |
| `llm-heartbeat` | — | **Anti-502** : garde chaud le tuyau LiteLLM↔llama-server (rôle `litellm`) |
| `hermes-agent` | (pas de port WAN) | Agent Hermes — appli **TUI**, **pas d'API HTTP** (le « gateway :8080 » de la doc historique n'écoute pas) |
| `hermes-auto-improve` | `0.0.0.0:9095` | Trigger HTTP analyse doc quotidienne |
| `hermes-exec` | `0.0.0.0:9096` | Exécuteur d'actions vocales `hermes -z --yolo` (jeton Bearer) — assistant STT |
| `qdrant` | `0.0.0.0:6333` / `:6334` | Base vectorielle (RAG `funk-docs` + mémoire STT `stt-memory`) |
| `postgresql-16` | `192.168.10.1:5432` | PostgreSQL 16 (8 bases, cf. plus bas) |
| `dnsmasq` | `192.168.10.1:53` | DNS + wildcard `*.lab.local` |
| `nfs-*` (mountd/idmapd/statd) | `:2049 :111 :20048` | Export NFS modèles + PVCs k8s |
| `node_exporter` | `:9100` | Métriques Prometheus |
| `alertmanager-webhook` | `0.0.0.0:9093` | Pont AlertManager → Hermes monitor |
| `postfix` | `:25` | Relais SMTP sortant (Gmail App Password) |

> Note : `:9093` côté s01 = **alertmanager-webhook** (storage-01), à ne pas confondre avec
> l'Alertmanager k8s (`alertmanager.lab.local`, in-cluster).

---

## gpu-01 — services llama-server (systemd)

| Service | Port | État relevé | Rôle |
|---|---|---|---|
| `llama-server` | `:1234` | ✅ actif | Chat principal **qwen3-8b** (GPU, ROCm) |
| `llama-embed` | `:1238` | ✅ actif | Embeddings dédiés **nomic-embed-text** (**CPU**, dim 768, `--ubatch-size 2048`) |
| `llama-embed-heartbeat` | — | ✅ actif | Garde chaud le slot embeddings :1238 |
| `llama-watchdog` | — | ✅ actif | **Auto-réparation** du llama-server figé (bug ROCm gfx1031) |
| llama-server CPU `:1236` | `:1236` | ⚠️ **éteint** | Instance manuelle (profil Hermes `system`) — **non gérée par IaC** |
| llama-server CPU `:1237` | `:1237` | ⚠️ **éteint** | Instance manuelle (profil Hermes `monitor`) — **non gérée par IaC** |

> ⚠️ Au relevé, **seuls `:1234` et `:1238` écoutent**. Les instances CPU `:1236`/`:1237` sont
> **arrêtées** → les profils Hermes `system` et `monitor` (qui pointent dessus) sont actuellement
> **dégradés**. Ce sont des services manuels (gap IaC connu, cf. `ansible/roles/llama_server/README.md`).
>
> ⚠️ GPU : `rocminfo` rapporte `gfx1030` (et non `gfx1031`) — c'est l'effet attendu de
> `HSA_OVERRIDE_GFX_VERSION=10.3.0`, indispensable car la RX 6700XT (gfx1031) n'est pas
> officiellement supportée par ROCm.

---

## LiteLLM — modèles exposés (`:4000`)

| Alias | Backend |
|---|---|
| `hermes-default` | Alias consommé par Hermes (bascule via `hermes-switch`) |
| `qwen3-8b` | llama-server GPU gpu-01 `:1234` |
| `claude-sonnet-4-6` | API Anthropic (profil `brain`, facturé) |
| `claude-opus-4-7` | API Anthropic (facturé) |

---

## Cluster k8s — workloads

**Nœuds** : compute-01/02/03 tous `Ready`, k8s `v1.33.1` (40 j d'uptime).

**Namespaces & pods** (tous `Running` au relevé) :

| Namespace | Workloads |
|---|---|
| `ai` | ghostfolio, ghostfolio-redis, n8n, open-webui, **stt-server**, **searxng** |
| `argocd` | application-controller, applicationset, notifications, redis, repo-server, server |
| `infra` | **traefik** (LB `192.168.10.200`), **registry** (registry Docker in-cluster) |
| `monitoring` | kube-prometheus-stack (Prometheus, Alertmanager, Grafana **13.0.1**, kube-state-metrics, operator, node-exporters) |
| `metallb-system` | controller + speakers |
| `nfs-provisioner` | nfs-subdir-external-provisioner |
| `kube-system` | coredns, flannel, kube-proxy, control-plane statiques |
| **`sacrifice`** | **`sacrifice-web`** (`sacrifice.lab.local`) + CronJob `sacrifice-assign-renfort` |

> ⚠️ **Namespace `sacrifice` non documenté** dans `CLAUDE.md`. C'est le projet de jeu FPS
> [Sacrifice](https://github.com/Alkatrazz24/Sacrifice) (monorepo séparé). Déployé **hors du repo
> Funk-lab** et **hors ArgoCD** (absent de la liste des Applications) — sa propre chaîne le pousse.
> Il possède aussi sa base PostgreSQL `sacrifice` sur storage-01.

**ArgoCD Applications** (toutes `Synced` / `Healthy`) :
`root` · `ghostfolio` · `n8n` · `open-webui` · `stt` · `searxng` · `monitoring` ·
`kube-prometheus-stack` · `nfs-provisioner` · `nfs-subdir-external-provisioner`.

**Exposition HTTP** :

| Type | Hôtes |
|---|---|
| `Ingress` standard | `argocd.lab.local`, `grafana.lab.local`, `prometheus.lab.local`, `alertmanager.lab.local`, `sacrifice.lab.local` |
| `IngressRoute` (CRD Traefik) | `ai/open-webui`, `ai/n8n`, `ai/ghostfolio`, `ai/stt-server`, `ai/searxng`, `infra/traefik-dashboard` |

> Les services du namespace `ai` (openwebui, n8n, ghostfolio, stt) passent par des **IngressRoute
> Traefik** (CRD), pas par des `Ingress` standards.

---

## PostgreSQL 16 (storage-01) — bases

`hermes` · `litellm` · `n8n` · `openwebui` · `ghostfolio` · `grafana` · `sacrifice` · `postgres`

> ⚠️ Bases non listées dans `CLAUDE.md` : **`grafana`** (Grafana k8s utilise un PG externe sur s01)
> et **`sacrifice`** (projet hors-repo).

---

## RAG / Qdrant — état

| Collection | Points | Statut | Dim / distance |
|---|---|---|---|
| `funk-docs` | **436** | 🟢 green | 768 / Cosine |
| `stt-memory` | — | 🟢 | 768 / Cosine |

> ✅ **`funk-docs` reconstruite et complète (436 chunks, 0 erreur)** — le warning « collection
> supprimée le 2026-06-17, re-ingest requis » de `CLAUDE.md`/`README`/`admin/ia/rag.md` est
> **périmé**. Embeddings via **nomic-embed-text** (`:1238`, dim 768), **plus** qwen3-8b.
>
> 🐛 **Fix de ce lot — embeddings tronqués à 512 tokens** : le relevé initial montrait 389 points
> avec **~46 chunks manquants** (HTTP 500 `input too large to process. increase the physical batch
> size (current: 512)`). Cause : `llama-embed` (:1238) tournait avec l'**ubatch llama.cpp par
> défaut (512)**, or en mode `--embeddings`+pooling toute l'entrée doit tenir dans un seul ubatch
> → tout chunk > 512 tokens échouait (CHUNK_MAX=2000 chars ≈ 700 tokens). **Corrigé** : `--batch-size`
> /`--ubatch-size = 2048` (= ctx) → ré-ingestion **436/436, 0 erreur**. Fix durable dans le rôle
> `llama_server` (`llama_embed_ubatch_size`) — **réconcilié le 2026-06-22** : l'unit `llama-embed`
> rendu par le rôle porte désormais les flags, drop-in systemd temporaire **supprimé**.
> `rag-ingest` gagne aussi un retry sur 5xx transitoires.
>
> ⚠️ Drift IaC mineur (corrigé) : `ansible/roles/rag/defaults/main.yml` mentionnait encore
> `embed_url: :1234` / `embed_model: qwen3-8b` (variables **mortes** — les scripts déployés
> hardcodent nomic `:1238`).

---

## Comment régénérer ce snapshot

Depuis le poste perso (accès `ssh storage-01` = user `ansible` ; g01 via `root@192.168.10.20` ;
kubeconfig `/home/ansible/.kube/config` sur s01) :

```bash
# Services + ports s01
ssh storage-01 'systemctl list-units --type=service --state=running | grep -iE "litellm|hermes|qdrant|postgres|nfs|dnsmasq|node_exporter|alertmanager|postfix"; ss -tlnp'
# gpu-01
ssh storage-01 'ssh root@192.168.10.20 "systemctl list-units llama* ; ss -tlnp | grep :12"'
# k8s
ssh storage-01 'KUBECONFIG=/home/ansible/.kube/config kubectl get nodes,pods,ingress,ingressroute -A'
ssh storage-01 'KUBECONFIG=/home/ansible/.kube/config kubectl get applications -n argocd'
# Bases PG + Qdrant + LiteLLM
ssh storage-01 'sudo -u postgres psql -tAc "SELECT datname FROM pg_database WHERE datistemplate=false"'
ssh storage-01 'curl -s localhost:6333/collections | python3 -m json.tool'
ssh storage-01 'curl -s localhost:4000/v1/models -H "Authorization: Bearer lm-studio" | python3 -m json.tool'
```
