mirror of
https://github.com/Alkatrazz24/Funk-lab.git
synced 2026-07-09 00:24:41 +02:00
Aligne la documentation sur l'état réel du cluster au 2026-06-18 : - Qdrant : crash-loop résolu le 17/06 (statut « HS / EN COURS » corrigé dans CLAUDE.md, README, admin/ia/rag.md, admin/incidents.md, admin/ia/stt.md). Précision : collection funk-docs supprimée lors de la réparation → re-ingest RAG encore à faire (pas de surévaluation du statut). - STT (assistant vocal « Jarvis ») : ajouté partout (était déployé mais non documenté). - Ghostfolio : ajouté partout (était déployé mais non documenté). - Embeddings dédiés nomic-embed-text :1238 : marqués opérationnels (roadmap README disait encore « TODO »). - llama-server : ×3 → ×4 (instance embeddings) ; gap IaC précisé (embeddings géré par le rôle, seules les 2 instances CPU restent manuelles). - Structure k8s/ corrigée dans CLAUDE.md : ajout stt/ + ghostfolio/, suppression des sous-dossiers traefik/ + metallb/ inexistants (installés via helm au bootstrap). - Namespaces et liste des secrets Vault (vault_pg_ghostfolio_password) complétés. - admin/README.md : index complété (~10 docs manquants : email, n8n, open-webui, ghostfolio, k9s, stt, rag, hermes-voice/souls/auto-improve, alertmanager-webhook). - Funk/ (conception d'origine : LM Studio + agents Goose, obsolète) déplacé sous archive/ avec bandeau « obsolète » + archive/README.md (historique git préservé). Claude-Session: https://claude.ai/code/session_017Qjq5jHiqNepnobJpHYpCa Co-authored-by: Claude <noreply@anthropic.com>
830 lines
35 KiB
Markdown
830 lines
35 KiB
Markdown
# Homelab IA — Architecture et plan de déploiement
|
||
|
||
> ## ⚠️ DOCUMENT OBSOLÈTE — ARCHIVE HISTORIQUE
|
||
>
|
||
> Ceci est la **conception d'origine** du homelab (pré-`Funk-lab`). Il décrit des choix
|
||
> **abandonnés** : inférence via **LM Studio** (remplacée par llama-server / ROCm) et agents
|
||
> **Goose** (remplacés par **Hermes Agent**). **Ce document ne fait plus foi.**
|
||
>
|
||
> 👉 Référence à jour : [`CLAUDE.md`](../../CLAUDE.md) et la base de connaissance [`admin/`](../../admin/).
|
||
> Conservé pour mémoire uniquement — voir [`archive/README.md`](../README.md).
|
||
|
||
> Document de référence consolidé pour le déploiement d'un homelab IA combinant
|
||
> un cluster Kubernetes (Talos) pour les services applicatifs et deux hôtes
|
||
> Linux dédiés pour l'inférence LLM (LM Studio) et l'agent autonome (Hermes Agent).
|
||
> Stack IaC complète : Ansible + talhelper + ArgoCD, GitOps de bout en bout.
|
||
> À utiliser comme contexte pour Claude Code.
|
||
|
||
---
|
||
|
||
## 1. Objectifs
|
||
|
||
- Faire tourner **Hermes Agent** (Nous Research) comme agent autonome
|
||
auto-amélioré, alimenté par **LM Studio** comme serveur d'inférence local.
|
||
- Apprendre Kubernetes en environnement réaliste (cluster multi-nœuds, GitOps)
|
||
pour les services applicatifs (Open WebUI, n8n, monitoring...).
|
||
- Apprendre Talos Linux (OS immuable, API-only, pensé pour Kubernetes).
|
||
- Maximiser l'utilisation du GPU AMD RX 6700XT pour l'inférence LLM.
|
||
- Tout gérer en Infrastructure as Code (versionné dans Git).
|
||
|
||
## 2. Priorités (par ordre)
|
||
|
||
1. Facilité d'administration
|
||
2. Apprentissage / montée en compétences
|
||
3. Performance brute (utiliser le 6700XT au max)
|
||
4. Haute disponibilité / résilience
|
||
|
||
## 3. Vision long terme
|
||
|
||
- Cible : ~10 machines à 2-3 ans, mix Talos (cluster k8s) + AlmaLinux (services natifs)
|
||
- Tout doit être reproductible depuis Git (réinstall complète possible en quelques heures)
|
||
- BlueBanquise reste une option à reconsidérer si on dépasse 25+ hôtes Linux classiques
|
||
ou si on ajoute du HPC/Slurm
|
||
|
||
---
|
||
|
||
## 4. Inventaire matériel
|
||
|
||
| Machine | CPU | RAM | Stockage | Réseau | Rôle |
|
||
|---|---|---|---|---|---|
|
||
| **storage-01** | AMD Ryzen 3 3200G (Zen+, 2019) | 32 GB DDR4 | 1× SSD OS + 4×1 TB RAID5 (2.7 TB exploitables) | 1× Gigabit | Hors cluster — passerelle + admin + stockage + Hermes Agent |
|
||
| **compute-01** | AMD A10-9700E (Excavator, 2016) | 16 GB DDR3 | SSD SATA | 1× Gigabit (r8169) | k8s control-plane (Talos) |
|
||
| **compute-02** | AMD A10-9700E | 8 GB DDR3 | SSD SATA | 1× Gigabit (r8169) | k8s worker (Talos) |
|
||
| **compute-03** | AMD A10-9700E | 8 GB DDR3 | SSD SATA | 1× Gigabit (r8169) | k8s worker (Talos) |
|
||
| **gpu-01** | AMD Ryzen 9 5950X (16 cœurs) | 32 GB DDR4 | NVMe 1 TB | 1× Gigabit | **Hors cluster** — hôte LM Studio dédié — RX 6700XT 12 GB |
|
||
| **switch** | Netgear GS308EV4 (8 ports Gigabit, managé Plus, VLAN 802.1Q) | — | — | — | Switch principal |
|
||
|
||
**Validation Talos déjà effectuée** : compute-01 boote correctement avec
|
||
Talos v1.13.0 en mode maintenance, IP DHCP obtenue, chipset r8169 reconnu nativement.
|
||
|
||
---
|
||
|
||
## 5. Architecture réseau
|
||
|
||
### 5.1. Topologie physique
|
||
|
||
```
|
||
Internet
|
||
│
|
||
┌───────────┐
|
||
│ Freebox │ 192.168.1.254 (gateway + DHCP LAN domestique)
|
||
└─────┬─────┘
|
||
│
|
||
│ VLAN 1 (port 1)
|
||
│
|
||
┌─────┴────────────────────────────────────────┐
|
||
│ Switch Netgear GS308EV4 │
|
||
│ P1 P2 P3 P4 P5 P6 P7 P8 │
|
||
│ V1 V1 V10 V10 V10 V10 V10 V1 │
|
||
└──┬───┬───┬───┬───┬───┬───┬───┬──────────────┘
|
||
│ │ │ │ │ │ │ └── PC perso (192.168.1.x)
|
||
│ │ │ │ │ │ └────── storage-01 NIC2 (192.168.10.1) ← LAN cluster
|
||
│ │ │ │ │ └────────── compute-03 (.10.13)
|
||
│ │ │ │ └────────────── compute-02 (.10.12)
|
||
│ │ │ └────────────────── compute-01 (.10.11)
|
||
│ │ └────────────────────── gpu-01 (.10.20)
|
||
│ └────────────────────────── storage-01 NIC1 (192.168.1.200) ← WAN
|
||
└────────────────────────────── Freebox
|
||
|
||
┌──────────────────────────────┐
|
||
│ storage-01 (AlmaLinux 9.7) │
|
||
│ - NIC1 (port 2) : 192.168.1.200 ← WAN / LAN domestique
|
||
│ - NIC2 (port 7) : 192.168.10.1 ← LAN cluster + gateway + NAT
|
||
└─────┬────────────────────────┘
|
||
│ (routage + NAT entre les deux interfaces)
|
||
│
|
||
┌────┴────┬──────────┬──────────┐
|
||
│ │ │ │
|
||
compute-01 compute-02 compute-03 gpu-01
|
||
.10.11 .10.12 .10.13 .10.20
|
||
(Talos) (Talos) (Talos) (AlmaLinux + LM Studio)
|
||
```
|
||
|
||
### 5.2. Vue logique des composants IA
|
||
|
||
```
|
||
┌──────────────────────────────────────────────────────────────────────┐
|
||
│ Cluster Kubernetes (Talos) │
|
||
│ 3 nœuds : compute-01/02/03 │
|
||
│ │
|
||
│ • Open WebUI • Traefik (ingress) │
|
||
│ • LiteLLM (proxy) • MetalLB (LB L2) │
|
||
│ • n8n (workflows) • cert-manager │
|
||
│ • Prometheus/Grafana • ArgoCD (GitOps) │
|
||
└──────────────────┬─────────────────────────┬─────────────────────────┘
|
||
│ │
|
||
│ NFS / S3 / DB │ HTTP /v1/chat/completions
|
||
▼ ▼
|
||
┌──────────────────────────────┐ ┌──────────────────────────────────┐
|
||
│ storage-01 (AlmaLinux 9.7) │ │ gpu-01 (AlmaLinux 9.7) │
|
||
│ 192.168.10.1 HORS CLUSTER │ │ 192.168.10.20 HORS CLUSTER │
|
||
│ │ │ │
|
||
│ Données : │ │ • LM Studio (mode serveur) │
|
||
│ • NFS (/srv/nfs/k8s) │ │ écoute sur :1234 │
|
||
│ • PostgreSQL │ │ • API OpenAI-compatible │
|
||
│ • Qdrant (vectoriel) │ │ • RX 6700XT via ROCm/Vulkan │
|
||
│ • MinIO (S3) │ │ • CLI `lms` pour pilotage │
|
||
│ │ │ │
|
||
│ Agent IA : │ │ │
|
||
│ • Hermes Agent ★ │◄──┤ Hermes appelle LM Studio │
|
||
│ (service systemd) │ │ via http://192.168.10.20:1234 │
|
||
│ │ │ │
|
||
│ Infra : │ │ │
|
||
│ • Passerelle / NAT │ │ │
|
||
│ • dnsmasq (lab.local) │ │ │
|
||
│ • Bastion admin │ │ │
|
||
└──────────────────────────────┘ └──────────────────────────────────┘
|
||
```
|
||
|
||
### 5.3. Plan d'adressage IP
|
||
|
||
**LAN domestique (existant, géré par la Freebox) — 192.168.1.0/24**
|
||
|
||
| IP | Hôte | Notes |
|
||
|---|---|---|
|
||
| `192.168.1.254` | Freebox | Gateway internet + DHCP |
|
||
| `192.168.1.10` | Machine 9950x3d (poste perso) | Déjà occupé |
|
||
| `192.168.1.200` | **storage-01** (interface WAN cluster) | IP statique réservée |
|
||
|
||
**LAN cluster (nouveau, isolé) — 192.168.10.0/24**
|
||
|
||
| IP | Hostname | Rôle |
|
||
|---|---|---|
|
||
| `192.168.10.1` | storage-01 | Gateway + admin + stockage + Hermes Agent (hors cluster k8s) |
|
||
| `192.168.10.11` | compute-01 | k8s control-plane (Talos, 16 GB) |
|
||
| `192.168.10.12` | compute-02 | k8s worker (Talos, 8 GB) |
|
||
| `192.168.10.13` | compute-03 | k8s worker (Talos, 8 GB) |
|
||
| `192.168.10.20` | gpu-01 | Hôte LM Studio dédié (AlmaLinux, hors cluster k8s) |
|
||
| `192.168.10.200-230` | (pool) | MetalLB — IP virtuelles des services k8s exposés |
|
||
|
||
**Ports applicatifs notables**
|
||
|
||
| Hôte | Port | Service | Notes |
|
||
|---|---|---|---|
|
||
| gpu-01 | 1234 | LM Studio API (OpenAI-compatible) | `http://192.168.10.20:1234/v1` |
|
||
| storage-01 | 22 | SSH (bastion + cible Ansible) | |
|
||
| storage-01 | 53 | dnsmasq | Résolution `*.lab.local` |
|
||
| storage-01 | 2049 | NFS | Export `/srv/nfs/k8s` |
|
||
| storage-01 | 5432 | PostgreSQL | |
|
||
| storage-01 | 6333 | Qdrant HTTP | |
|
||
| storage-01 | 9000 | MinIO S3 | |
|
||
| storage-01 | 9001 | MinIO Console | |
|
||
| MetalLB | 80/443 | Traefik | Tous les Ingress du cluster |
|
||
| MetalLB | 8080 | ArgoCD UI | `argocd.lab.local` |
|
||
|
||
**Réseaux internes Kubernetes (ne pas modifier sauf raison spécifique)**
|
||
|
||
- Pods (Flannel) : `10.42.0.0/16`
|
||
- Services : `10.43.0.0/16`
|
||
|
||
### 5.4. Câblage du switch GS308EV4
|
||
|
||
Tous les ports en mode **Access** (pas de trunk). storage-01 utilise deux NICs physiques — une par VLAN.
|
||
|
||
| Port | Connecté à | VLAN | Mode |
|
||
|---|---|---|---|
|
||
| 1 | Freebox | 1 - Default | Access |
|
||
| 2 | storage-01 NIC1 (WAN, 192.168.1.200) | 1 - Default | Access |
|
||
| 3 | gpu-01 (192.168.10.20) | 10 - cluster-funk | Access |
|
||
| 4 | compute-01 (192.168.10.11) | 10 - cluster-funk | Access |
|
||
| 5 | compute-02 (192.168.10.12) | 10 - cluster-funk | Access |
|
||
| 6 | compute-03 (192.168.10.13) | 10 - cluster-funk | Access |
|
||
| 7 | storage-01 NIC2 (LAN cluster, 192.168.10.1) | 10 - cluster-funk | Access |
|
||
| 8 | PC perso (192.168.1.x) | 1 - Default | Access |
|
||
|
||
**Avantage vs trunk** : pas de subinterface `eno1.10` à configurer — deux interfaces physiques classiques dans NetworkManager. Plus simple, moins de risque d'erreur au démarrage.
|
||
|
||
### 5.5. Route statique sur la Freebox
|
||
|
||
À configurer dans *Paramètres Freebox > Mode avancé > Configuration de routage* :
|
||
|
||
```
|
||
Réseau de destination : 192.168.10.0
|
||
Masque : 255.255.255.0
|
||
Passerelle : 192.168.1.200
|
||
```
|
||
|
||
Cela permet à toutes les machines du LAN domestique de joindre directement le LAN cluster.
|
||
|
||
---
|
||
|
||
## 6. Choix d'OS
|
||
|
||
| Machine | OS | Justification |
|
||
|---|---|---|
|
||
| storage-01 | **AlmaLinux 9.7 minimal** | Stack RHEL maîtrisée, stabilité, support sécurité jusqu'en 2032, doc abondante NFS/nftables/MinIO/Postgres |
|
||
| compute-01 | **Talos Linux v1.13+** | Choix d'apprentissage assumé, validation matérielle OK |
|
||
| compute-02 | **Talos Linux v1.13+** | idem |
|
||
| compute-03 | **Talos Linux v1.13+** | idem |
|
||
| gpu-01 | **AlmaLinux 9.7 minimal** | Cohérence RHEL avec storage-01, ROCm via repo officiel AMD pour RHEL 9 |
|
||
|
||
**Note sur AlmaLinux + ROCm pour gpu-01** : la majorité de la doc communautaire
|
||
ROCm + RX 6700XT vise Ubuntu. Sur AlmaLinux 9, utiliser le repo officiel AMD
|
||
pour RHEL 9 (`https://repo.radeon.com/rocm/`). Adapter les commandes dnf au
|
||
lieu d'apt. En cas de blocage ROCm, Vulkan reste un fallback fonctionnel pour LM Studio.
|
||
|
||
---
|
||
|
||
## 7. Architecture applicative
|
||
|
||
### 7.1. Topologie cluster Kubernetes
|
||
|
||
- **Control-plane** : single (compute-01 uniquement)
|
||
- **Workers** : compute-02, compute-03
|
||
- **storage-01 et gpu-01 sont HORS du cluster**
|
||
|
||
### 7.2. Découpage des responsabilités
|
||
|
||
**gpu-01 — Hôte d'inférence LLM (hors cluster)**
|
||
- LM Studio en mode serveur headless
|
||
- API OpenAI-compatible exposée sur `:1234`
|
||
|
||
**storage-01 — Bastion admin + données + agent (hors cluster)**
|
||
- Passerelle réseau (NAT, routage VLAN)
|
||
- Bastion : `talosctl`, `kubectl`, `helm`, `argocd` CLI, `ansible`
|
||
- Services données : NFS, PostgreSQL, Qdrant, MinIO
|
||
- **Hermes Agent** en service systemd
|
||
- dnsmasq pour la résolution `*.lab.local`
|
||
|
||
**Cluster Kubernetes (Talos, 3 nœuds)**
|
||
- Couche infra : MetalLB, Traefik, cert-manager, Longhorn, nfs-subdir-external-provisioner
|
||
- Couche observabilité : kube-prometheus-stack, Loki
|
||
- Couche applicative IA : Open WebUI, LiteLLM, n8n
|
||
- **GitOps via ArgoCD**
|
||
|
||
### 7.3. Flux principal Hermes ↔ LM Studio
|
||
|
||
```
|
||
Utilisateur → CLI Hermes / Telegram / autre interface
|
||
(sur storage-01)
|
||
│
|
||
▼
|
||
Hermes Agent (skills, mémoire, tools)
|
||
[storage-01 :daemon systemd]
|
||
│
|
||
│ HTTP POST /v1/chat/completions
|
||
▼
|
||
LM Studio (modèle chargé en VRAM 6700XT)
|
||
[gpu-01 :1234]
|
||
│
|
||
│ Réponse streaming
|
||
▼
|
||
Hermes Agent (parsing tool calls, exécution)
|
||
│
|
||
▼
|
||
Utilisateur
|
||
```
|
||
|
||
### 7.4. Deux setups IA — poste perso vs cluster Funk
|
||
|
||
#### Setup 1 — Poste perso (9950X3D) — dev local
|
||
|
||
**Matériel** : Ryzen 9 9950X3D · 32 GB DDR5 · RX 9070 XT 16 GB VRAM
|
||
|
||
| Composant | Config |
|
||
|---|---|
|
||
| LM Studio | `http://127.0.0.1:1234/v1` (bind localhost par défaut) |
|
||
| Ollama | `http://127.0.0.1:11434` (aussi installé) |
|
||
| Hermes Agent | config `base_url: http://127.0.0.1:1234/v1` |
|
||
| Goose agents | `Funk/Funk-infra/agents/` → pointent sur `http://localhost:1234/v1` |
|
||
|
||
**Démarrage LM Studio :**
|
||
```bash
|
||
# Charger le modèle avec un context suffisant (système Hermes ≈ 15 000 tokens)
|
||
lms load <modele> --context-length 16384
|
||
lms server start --port 1234
|
||
```
|
||
|
||
**Config Hermes (`~/.hermes/config.yaml`) :**
|
||
```yaml
|
||
model:
|
||
default: <nom-modele>
|
||
provider: lmstudio
|
||
base_url: http://127.0.0.1:1234/v1
|
||
context_length: 16384
|
||
```
|
||
|
||
**Goose agents :**
|
||
```bash
|
||
cd Funk/Funk-infra/agents/<nom-agent>
|
||
goose session --config goose-config.yaml
|
||
```
|
||
|
||
| Agent Goose | Modèle cible | Usage |
|
||
|---|---|---|
|
||
| `global` | qwen2.5-14b | Raisonnement général |
|
||
| `infra` | qwen2.5-coder-14b | k8s, Talos, Helm, ArgoCD |
|
||
| `sysadmin` | qwen2.5-7b | Admin système, diagnostics |
|
||
| `monitoring` | llama3.2-3b | Logs, métriques |
|
||
| `data` | qwen2.5-14b | Analyse de données |
|
||
|
||
---
|
||
|
||
#### Setup 2 — Cluster Funk (production)
|
||
|
||
**Matériel GPU** : gpu-01, Ryzen 9 5950X · 32 GB DDR4 · RX 6700XT 12 GB VRAM
|
||
|
||
| Composant | Config |
|
||
|---|---|
|
||
| LM Studio | `http://192.168.10.20:1234/v1` (bind `0.0.0.0`) |
|
||
| Hermes Agent | service systemd sur storage-01 |
|
||
| Hermes `base_url` | `http://192.168.10.20:1234/v1` |
|
||
|
||
**Démarrage LM Studio sur gpu-01 :**
|
||
```bash
|
||
HSA_OVERRIDE_GFX_VERSION=10.3.0 lms load <modele> --context-length 16384
|
||
lms server start --port 1234 --host 0.0.0.0
|
||
```
|
||
|
||
**Config Hermes sur storage-01 (`~/.hermes/config.yaml`) :**
|
||
```yaml
|
||
model:
|
||
default: <nom-modele>
|
||
provider: lmstudio
|
||
base_url: http://192.168.10.20:1234/v1
|
||
context_length: 16384
|
||
```
|
||
|
||
**Différence clé avec setup 1** : `HSA_OVERRIDE_GFX_VERSION=10.3.0` obligatoire pour la RX 6700XT (gfx1031 non officiellement supporté par ROCm). Sur la RX 9070 XT du poste perso, cette variable n'est pas nécessaire.
|
||
|
||
---
|
||
|
||
## 8. Stack IaC / Automatisation
|
||
|
||
### 8.1. Principe : un seul repo Git, trois flux de déploiement
|
||
|
||
Toute l'infrastructure est gérée en GitOps depuis un repo Git unique. Trois outils
|
||
se partagent les responsabilités selon la cible :
|
||
|
||
```
|
||
┌──────────────────────────────────────────────────────────────────┐
|
||
│ Repo Git du lab (sur poste admin + remote Gitea/GitHub privé) │
|
||
│ │
|
||
│ lab-infra/ │
|
||
│ ├── ansible/ ← gère storage-01 + gpu-01 │
|
||
│ │ ├── inventory.yml │
|
||
│ │ ├── playbooks/ │
|
||
│ │ ├── roles/ │
|
||
│ │ └── group_vars/ │
|
||
│ ├── talos/ ← configs Talos via talhelper │
|
||
│ │ ├── talconfig.yaml │
|
||
│ │ ├── talsecret.sops.yaml │
|
||
│ │ └── clusterconfig/ (généré par talhelper) │
|
||
│ ├── k8s/ ← manifests / Helm values │
|
||
│ │ ├── apps/ ← apps déployées par ArgoCD │
|
||
│ │ ├── infra/ ← MetalLB, Traefik, cert-manager... │
|
||
│ │ └── argocd-bootstrap/ ← Application of Applications │
|
||
│ └── docs/ │
|
||
│ └── HOMELAB.md ← ce document │
|
||
└────────┬─────────────────────────┬────────────────────┬──────────┘
|
||
│ │ │
|
||
│ ansible-playbook │ talosctl │ git push
|
||
│ (push manuel SSH) │ apply-config │ → ArgoCD
|
||
│ │ (push manuel) │ pull auto
|
||
▼ ▼ ▼
|
||
storage-01, compute-01/02/03 Workloads dans
|
||
gpu-01 (Talos) le cluster k8s
|
||
(AlmaLinux)
|
||
```
|
||
|
||
### 8.2. Outil 1 — Ansible (vanilla) pour les hôtes Linux classiques
|
||
|
||
**Cible** : storage-01 et gpu-01 (et futures machines AlmaLinux/Debian).
|
||
|
||
**Choix** : Ansible vanilla, **rôles écrits from scratch**. Pas de framework type
|
||
BlueBanquise — surdimensionné pour 5-10 hôtes Linux à terme. À reconsidérer si
|
||
on dépasse 25+ hôtes ou si on ajoute du HPC/Slurm.
|
||
|
||
**Structure des rôles prévus** :
|
||
|
||
```
|
||
ansible/
|
||
├── ansible.cfg
|
||
├── inventory.yml
|
||
├── group_vars/
|
||
│ ├── all.yml # variables communes (DNS, NTP, users)
|
||
│ ├── gateway.yml # variables passerelle
|
||
│ └── gpu_hosts.yml # variables hôtes GPU
|
||
├── host_vars/
|
||
│ ├── storage-01.yml
|
||
│ └── gpu-01.yml
|
||
├── playbooks/
|
||
│ ├── site.yml # playbook racine
|
||
│ ├── storage-01.yml
|
||
│ └── gpu-01.yml
|
||
└── roles/
|
||
├── common/ # paquets de base, sshd, sudoers, motd
|
||
├── gateway/ # NetworkManager VLAN, IP forwarding, nftables, NAT
|
||
├── dnsmasq/ # DNS local *.lab.local
|
||
├── nfs_server/ # NFS server + exports
|
||
├── postgresql/ # Postgres + DB init
|
||
├── qdrant/ # Qdrant via Podman
|
||
├── minio/ # MinIO via Podman
|
||
├── rocm/ # repo AMD + drivers + HSA_OVERRIDE
|
||
├── lm_studio/ # install + service systemd
|
||
└── hermes_agent/ # install + config + systemd unit
|
||
```
|
||
|
||
**Inventaire** :
|
||
|
||
```yaml
|
||
# ansible/inventory.yml
|
||
all:
|
||
children:
|
||
gateway:
|
||
hosts:
|
||
storage-01:
|
||
ansible_host: 192.168.10.1
|
||
gpu_hosts:
|
||
hosts:
|
||
gpu-01:
|
||
ansible_host: 192.168.10.20
|
||
almalinux:
|
||
children:
|
||
gateway:
|
||
gpu_hosts:
|
||
```
|
||
|
||
**Lancement type** :
|
||
|
||
```bash
|
||
cd ansible/
|
||
ansible-playbook -i inventory.yml playbooks/site.yml --check # dry-run
|
||
ansible-playbook -i inventory.yml playbooks/site.yml # apply
|
||
ansible-playbook -i inventory.yml playbooks/site.yml --tags rocm # cibler 1 rôle
|
||
```
|
||
|
||
**Bonnes pratiques** :
|
||
- Tous les rôles **idempotents** (peuvent être ré-exécutés sans casse).
|
||
- Variables sensibles dans **Ansible Vault** (mot de passe Postgres, clés API).
|
||
- Un playbook = une machine ou un groupe, pas de "playbook fourre-tout".
|
||
- Tags systématiques pour cibler un rôle spécifique.
|
||
|
||
### 8.3. Outil 2 — talhelper pour les nœuds Talos
|
||
|
||
**Cible** : compute-01, compute-02, compute-03.
|
||
|
||
**Pourquoi talhelper** : `talosctl gen config` brut produit des configs longues
|
||
et difficiles à maintenir. `talhelper` lit un seul fichier `talconfig.yaml`
|
||
clair et génère les configs YAML par nœud, avec gestion des secrets (chiffrement
|
||
SOPS) et patches par nœud.
|
||
|
||
**Structure** :
|
||
|
||
```
|
||
talos/
|
||
├── talconfig.yaml # config déclarative (lue par talhelper)
|
||
├── talsecret.sops.yaml # secrets chiffrés (token bootstrap, certs CA)
|
||
├── talenv.yaml # version Talos, version k8s
|
||
├── patches/ # patches YAML par nœud ou groupe
|
||
│ ├── compute-01.yaml
|
||
│ └── all-controlplane.yaml
|
||
└── clusterconfig/ # généré : ne PAS commit (au .gitignore)
|
||
├── lab-compute-01.yaml
|
||
├── lab-compute-02.yaml
|
||
└── lab-compute-03.yaml
|
||
```
|
||
|
||
**Workflow** :
|
||
|
||
```bash
|
||
cd talos/
|
||
|
||
# 1. Éditer talconfig.yaml (ajout d'un nœud, changement de version k8s, etc.)
|
||
vim talconfig.yaml
|
||
|
||
# 2. Régénérer les configs nœud
|
||
talhelper genconfig
|
||
|
||
# 3. Appliquer sur un nœud spécifique
|
||
talhelper gencommand apply --node compute-02 | bash
|
||
|
||
# 4. Bootstrap (uniquement la première fois, sur le control-plane)
|
||
talhelper gencommand bootstrap --node compute-01 | bash
|
||
|
||
# 5. Récupérer le kubeconfig
|
||
talhelper gencommand kubeconfig | bash
|
||
```
|
||
|
||
**Avantage GitOps** : le `talconfig.yaml` est ta source de vérité. N'importe qui
|
||
(toi dans 6 mois) peut lire ce fichier et comprendre l'état du cluster Talos
|
||
sans avoir à inspecter les nœuds.
|
||
|
||
### 8.4. Outil 3 — ArgoCD pour les workloads Kubernetes
|
||
|
||
**Cible** : tout ce qui tourne dans le cluster k8s (apps + infra k8s).
|
||
|
||
**Principe** : ArgoCD surveille en continu un dossier Git et garantit que l'état
|
||
réel du cluster correspond à ce qui est déclaré dans Git.
|
||
|
||
**Pattern recommandé : "App of Apps"**
|
||
|
||
```
|
||
k8s/
|
||
├── argocd-bootstrap/ # bootstrap ArgoCD lui-même
|
||
│ └── argocd-install.yaml
|
||
├── apps-of-apps/
|
||
│ └── root.yaml # une Application qui pointe sur apps/
|
||
├── infra/ # déployé d'abord
|
||
│ ├── metallb/
|
||
│ │ ├── application.yaml
|
||
│ │ └── values.yaml
|
||
│ ├── traefik/
|
||
│ ├── cert-manager/
|
||
│ ├── longhorn/
|
||
│ └── nfs-provisioner/
|
||
└── apps/ # déployé ensuite
|
||
├── litellm/
|
||
│ ├── application.yaml
|
||
│ ├── deployment.yaml
|
||
│ ├── service.yaml
|
||
│ └── ingress.yaml
|
||
├── open-webui/
|
||
├── n8n/
|
||
├── monitoring/ # kube-prometheus-stack
|
||
└── external-services/ # ExternalName vers storage-01
|
||
├── postgresql-external.yaml
|
||
├── qdrant-external.yaml
|
||
└── lm-studio-external.yaml # ExternalName vers gpu-01:1234
|
||
```
|
||
|
||
**Workflow d'utilisation** :
|
||
|
||
```bash
|
||
# 1. Modifier un manifest
|
||
vim k8s/apps/open-webui/deployment.yaml
|
||
|
||
# 2. Commit + push
|
||
git add k8s/apps/open-webui/
|
||
git commit -m "open-webui: bump to v0.4.0, add OIDC config"
|
||
git push
|
||
|
||
# 3. ArgoCD détecte le changement (poll par défaut toutes les 3 min)
|
||
# → applique automatiquement dans le cluster
|
||
# → visible dans l'UI argocd.lab.local
|
||
```
|
||
|
||
**Bénéfices** :
|
||
- Source de vérité unique (Git)
|
||
- Historique complet via `git log`
|
||
- Rollback en `git revert` + push
|
||
- Recréation totale du cluster en cas de désastre : install Talos via talhelper,
|
||
install ArgoCD via le bootstrap, ArgoCD redéploie tout le reste tout seul
|
||
|
||
### 8.5. Récapitulatif des responsabilités
|
||
|
||
| Outil | Cible | Mode de déploiement | Stockage source |
|
||
|---|---|---|---|
|
||
| **Ansible** | Hôtes Linux classiques (storage-01, gpu-01, futures Alma) | Push manuel (`ansible-playbook`) | `lab-infra/ansible/` |
|
||
| **talhelper** | Nœuds Talos (compute-01/02/03) | Push manuel (`talosctl apply-config`) | `lab-infra/talos/` |
|
||
| **ArgoCD** | Workloads Kubernetes (apps + infra k8s) | Pull automatique depuis Git | `lab-infra/k8s/` |
|
||
|
||
### 8.6. Repo Git : où l'héberger ?
|
||
|
||
**Court terme** : repo local sur ton poste + remote sur **GitHub** (privé) ou
|
||
**GitLab** (privé) → simple et fiable.
|
||
|
||
**Moyen terme (recommandé)** : héberger un **Gitea** ou **Forgejo** sur
|
||
storage-01 (rôle Ansible dédié) + miroir GitHub pour backup. Avantages :
|
||
- Indépendance totale (pas besoin d'Internet pour déployer)
|
||
- Apprentissage de l'auto-hébergement Git
|
||
- ArgoCD pointe sur `git.lab.local/admin/lab-infra.git`
|
||
|
||
### 8.7. Gestion des secrets
|
||
|
||
**Pas de secrets en clair dans Git, jamais.** Trois mécanismes selon la couche :
|
||
|
||
- **Ansible** : Ansible Vault pour les secrets (`ansible-vault encrypt_string`)
|
||
- **Talos** : SOPS + age (intégré nativement à talhelper)
|
||
- **Kubernetes** : Sealed Secrets (Bitnami) ou External Secrets Operator
|
||
pointant sur un Vault — pour démarrer, Sealed Secrets est plus simple
|
||
|
||
---
|
||
|
||
## 9. Feuille de route par phases
|
||
|
||
Chaque phase est validable indépendamment. Ne passer à la suivante que quand
|
||
la précédente fonctionne.
|
||
|
||
### Phase 0 — Préparation
|
||
- [x] Validation matérielle Talos sur 1 ThinkCentre (compute-01) ✅ effectué
|
||
- [ ] Vérifier que tous les ThinkCentre ont des SSD SATA opérationnels
|
||
- [ ] Préparer 1 clé USB pour Talos + 1 clé USB pour AlmaLinux
|
||
- [ ] Initialiser le repo Git `lab-infra/` sur le poste admin
|
||
|
||
### Phase 1 — Infra réseau (storage-01 manuel + bootstrap Ansible)
|
||
- [x] Installation AlmaLinux sur storage-01 ✅
|
||
- [x] Configuration IP de base — storage-01 joignable (192.168.10.1 LAN cluster) ✅
|
||
- [x] IP WAN storage-01 fixée à 192.168.1.200 ✅
|
||
- [x] Configuration VLAN sur le GS308EV4 ✅ — tous ports Access, storage-01 sur deux NICs physiques
|
||
- [ ] Initialiser `lab-infra/ansible/` avec inventory + rôle `common` + rôle `gateway`
|
||
- [ ] Premier `ansible-playbook` qui configure VLAN/nftables/NAT/IP forwarding
|
||
- [ ] Route statique sur la Freebox
|
||
- [ ] Rôle `dnsmasq` pour résolution `*.lab.local`
|
||
- [ ] Validation : ping bidirectionnel LAN domestique ↔ LAN cluster
|
||
|
||
### Phase 2 — Hôte gpu-01 + LM Studio (Ansible)
|
||
- [x] Installation AlmaLinux sur gpu-01 ✅ — ping OK depuis storage-01
|
||
- [ ] Ajout de gpu-01 à l'inventaire Ansible
|
||
- [ ] Rôle `rocm` : repo AMD + drivers + `HSA_OVERRIDE_GFX_VERSION=10.3.0`
|
||
- [ ] Validation ROCm : `rocminfo` doit lister la RX 6700XT
|
||
- [ ] Rôle `lm_studio` : install + service systemd avec bind `0.0.0.0:1234`
|
||
- [ ] Téléchargement d'un modèle test (Hermes 4, Qwen 2.5 7B...)
|
||
- [ ] Validation : `curl http://192.168.10.20:1234/v1/models` depuis storage-01
|
||
|
||
### Phase 3 — Hermes Agent sur storage-01 (Ansible)
|
||
- [ ] Rôle `hermes_agent` : install via script officiel
|
||
- [ ] Configuration provider custom endpoint (LM Studio gpu-01)
|
||
- [ ] Premier `hermes chat` interactif
|
||
- [ ] (Optionnel) Service systemd pour daemon background
|
||
- [ ] Données persistantes (`~/.hermes/`) sur le RAID5
|
||
|
||
### Phase 4 — Stack données sur storage-01 (Ansible)
|
||
- [ ] Rôle `nfs_server` : export `/srv/nfs/k8s` vers `192.168.10.0/24`
|
||
- [ ] Rôle `postgresql` : install + DB init
|
||
- [ ] Rôle `qdrant` : Podman + service systemd
|
||
- [ ] Rôle `minio` : Podman + service systemd
|
||
- [ ] Validation : tous les services accessibles depuis le LAN cluster
|
||
|
||
### Phase 5 — Cluster Talos (talhelper)
|
||
- [ ] Génération image Talos via factory.talos.dev (extensions `iscsi-tools`)
|
||
- [ ] Init `lab-infra/talos/` avec `talconfig.yaml` (3 nœuds)
|
||
- [ ] `talhelper genconfig`
|
||
- [ ] Apply sur compute-01 (control-plane) puis bootstrap etcd
|
||
- [ ] Apply sur compute-02 et compute-03 (workers)
|
||
- [ ] Validation : `kubectl get nodes` montre 3 nœuds Ready
|
||
|
||
### Phase 6 — Bootstrap ArgoCD + infra k8s (GitOps)
|
||
- [ ] Install ArgoCD manuel via Helm (une seule fois, l'install ArgoCD reste manuelle)
|
||
- [ ] Init `lab-infra/k8s/` avec App of Apps pattern
|
||
- [ ] Création des Applications ArgoCD pour : MetalLB, Traefik, cert-manager
|
||
- [ ] Validation : pod nginx test exposé via Ingress, accessible depuis le LAN
|
||
|
||
### Phase 7 — Stockage k8s (ArgoCD)
|
||
- [ ] Application ArgoCD : `nfs-subdir-external-provisioner` pointant sur storage-01
|
||
- [ ] Application ArgoCD : Longhorn (avec `iscsi-tools` extension Talos)
|
||
- [ ] Validation : 1 PVC NFS + 1 PVC Longhorn créés et montés
|
||
|
||
### Phase 8 — Apps IA (ArgoCD)
|
||
- [ ] Applications ArgoCD : ExternalName vers Postgres, Qdrant, LM Studio
|
||
- [ ] Application ArgoCD : LiteLLM (proxy vers LM Studio)
|
||
- [ ] Application ArgoCD : Open WebUI (front, pointe sur LiteLLM)
|
||
- [ ] Application ArgoCD : n8n
|
||
- [ ] Application ArgoCD : kube-prometheus-stack + Loki
|
||
- [ ] Validation finale : workflow n8n → Open WebUI → LiteLLM → LM Studio
|
||
|
||
### Phase 9 — Optionnel : Gitea local + miroir
|
||
- [ ] Rôle Ansible `gitea` sur storage-01
|
||
- [ ] Migration du repo `lab-infra` vers Gitea local
|
||
- [ ] Reconfiguration ArgoCD pour pointer sur `git.lab.local`
|
||
- [ ] Miroir push vers GitHub privé (sauvegarde)
|
||
|
||
---
|
||
|
||
## 10. Points d'attention spécifiques
|
||
|
||
### 10.1. RX 6700XT et ROCm sur AlmaLinux 9
|
||
- gfx1031 non officiellement supporté par ROCm
|
||
- **Variable obligatoire** : `HSA_OVERRIDE_GFX_VERSION=10.3.0`
|
||
- ROCm s'exécute directement sur l'OS hôte (gpu-01), pas dans des conteneurs
|
||
- Fallback Vulkan possible dans LM Studio si ROCm coince
|
||
- Doc ROCm pour RHEL 9 : https://rocm.docs.amd.com/projects/install-on-linux/
|
||
|
||
### 10.2. LM Studio en mode serveur
|
||
- Par défaut LM Studio bind sur `127.0.0.1` → inaccessible depuis le réseau
|
||
- Forcer `0.0.0.0` via CLI : `lms server start --port 1234 --host 0.0.0.0`
|
||
- LM Studio CLI : `lms ls`, `lms load <model>`, `lms unload`, `lms server status`
|
||
|
||
### 10.3. Hermes Agent
|
||
- Daemon : possible via systemd unit
|
||
- Mémoire/skills stockés dans `~/.hermes/` → **à mettre sur le RAID5**
|
||
- Variables `.env` dans `~/.hermes/.env`
|
||
|
||
### 10.4. RAM serrée sur ThinkCentre 8 GB
|
||
- Réserver système+kubelet : `system-reserved=cpu=500m,memory=1Gi`,
|
||
`kube-reserved=cpu=500m,memory=1Gi`
|
||
- Toujours définir `resources.requests/limits` sur les pods
|
||
- Sinon risque OOM-killer sur le nœud entier
|
||
|
||
### 10.5. Single control-plane
|
||
- Si compute-01 tombe, plus de `kubectl apply` mais les workloads continuent
|
||
- Snapshots etcd réguliers : `talosctl etcd snapshot` vers storage-01 (cron Ansible)
|
||
|
||
### 10.6. RAID5 sur storage-01
|
||
- 4×1 TB = 2.7 TB exploitables
|
||
- Sauvegarder : configs k8s (Git), bases de données (dump périodique
|
||
vers MinIO ou NAS externe), mémoire/skills Hermes (`~/.hermes/`)
|
||
- Pas les modèles LM Studio (re-téléchargeables)
|
||
|
||
### 10.7. Sécurité passerelle = bastion admin
|
||
- storage-01 cumule passerelle + bastion + Hermes + données → SPOF assumé
|
||
- gpu-01 sans rôle réseau critique : si tombe, perte inférence uniquement
|
||
|
||
### 10.8. Bootstrap : ce qui reste manuel
|
||
GitOps ne peut pas faire le bootstrap absolu. Restent toujours manuels :
|
||
- Installation OS sur chaque machine (AlmaLinux ou Talos depuis USB)
|
||
- Configuration IP/SSH minimale pour qu'Ansible puisse se connecter
|
||
- Premier déploiement ArgoCD via Helm
|
||
- Tout le reste est ensuite géré par Ansible / talhelper / ArgoCD
|
||
|
||
---
|
||
|
||
## 11. Outils à installer sur storage-01 (bastion admin)
|
||
|
||
```bash
|
||
# Outils Kubernetes / Talos
|
||
- talosctl (admin Talos)
|
||
- talhelper (génération configs Talos)
|
||
- kubectl (admin Kubernetes)
|
||
- helm (charts)
|
||
- argocd CLI
|
||
- k9s (TUI Kubernetes)
|
||
|
||
# Outils IaC
|
||
- ansible-core
|
||
- sops + age (secrets Talos)
|
||
|
||
# Outils IA
|
||
- hermes (Hermes Agent)
|
||
- curl/jq (debug API LM Studio)
|
||
|
||
# Outils système
|
||
- nftables, dnsmasq, nfs-utils, postgresql-server, podman
|
||
- minio, qdrant (binaires ou conteneurs Podman)
|
||
|
||
# Optionnel
|
||
- gitea ou forgejo (Git local)
|
||
- restic ou borgbackup (sauvegardes)
|
||
```
|
||
|
||
Tous installés via les rôles Ansible — pas de installation manuelle au-delà
|
||
du bootstrap initial.
|
||
|
||
---
|
||
|
||
## 12. Conventions et nommage
|
||
|
||
- Hostnames : `storage-01`, `compute-01`, `compute-02`, `compute-03`, `gpu-01`
|
||
- Domaine local : `lab.local`
|
||
- Services exposés via cluster : `<service>.lab.local` → IP MetalLB de Traefik
|
||
- Endpoint LM Studio : `http://192.168.10.20:1234/v1` (ou `lms.lab.local`)
|
||
- Namespaces k8s :
|
||
- `argocd` (ArgoCD lui-même)
|
||
- `infra` (MetalLB, Traefik, cert-manager, monitoring)
|
||
- `storage` (Longhorn, NFS provisioner)
|
||
- `external` (ExternalName vers services storage-01/gpu-01)
|
||
- `ai` (Open WebUI, LiteLLM)
|
||
- `workflows` (n8n)
|
||
- Git :
|
||
- Branches : `main` (= prod), `feature/*` (changements en cours)
|
||
- Commits : conventional commits (`feat:`, `fix:`, `chore:`, `docs:`)
|
||
|
||
---
|
||
|
||
## 13. État actuel (2026-05-09)
|
||
|
||
- ✅ Architecture validée
|
||
- ✅ Test Talos sur compute-01 effectué (boot OK, IP DHCP, talosctl répond)
|
||
- ✅ Stack IaC choisie : Ansible vanilla + talhelper + ArgoCD
|
||
- ✅ Hermes Agent configuré sur le poste perso (Setup 1 — 9950X3D + LM Studio local)
|
||
- ✅ AlmaLinux installé sur storage-01 — ping OK (`192.168.1.200` WAN, `192.168.10.1` LAN cluster)
|
||
- ✅ AlmaLinux installé sur gpu-01 — ping OK depuis storage-01 (`192.168.10.20`)
|
||
- ✅ Connectivité LAN cluster (VLAN 10) : storage-01 ↔ gpu-01 fonctionnelle
|
||
- ⏳ Phase 1 en cours : Ansible + rôles + dnsmasq + NAT à configurer
|
||
- ⏳ Phase 2 en cours : ROCm + LM Studio sur gpu-01 à installer
|
||
- ❌ Ansible pas encore exécuté (repo `lab-infra/` à initialiser)
|
||
- ❌ VLAN switch GS308EV4 à confirmer / finaliser
|
||
- ❌ Route statique Freebox à configurer
|
||
- ❌ Aucun cluster k8s monté
|
||
- ❌ LM Studio pas encore installé sur gpu-01
|
||
- ❌ Hermes Agent pas encore installé sur storage-01
|
||
|
||
---
|
||
|
||
## 14. Annexes — Liens utiles
|
||
|
||
**Infrastructure**
|
||
- Talos Linux : https://www.talos.dev/
|
||
- Image Factory Talos : https://factory.talos.dev/
|
||
- talhelper : https://github.com/budimanjojo/talhelper
|
||
- AlmaLinux 9 : https://almalinux.org/
|
||
- ROCm install (RHEL 9) : https://rocm.docs.amd.com/projects/install-on-linux/
|
||
|
||
**Kubernetes / GitOps**
|
||
- ArgoCD : https://argo-cd.readthedocs.io/
|
||
- ArgoCD App of Apps pattern : https://argo-cd.readthedocs.io/en/stable/operator-manual/cluster-bootstrapping/
|
||
- Sealed Secrets : https://github.com/bitnami-labs/sealed-secrets
|
||
- Longhorn : https://longhorn.io/
|
||
- MetalLB : https://metallb.universe.tf/
|
||
|
||
**IaC**
|
||
- Ansible docs : https://docs.ansible.com/
|
||
- Ansible Vault : https://docs.ansible.com/ansible/latest/vault_guide/index.html
|
||
- SOPS : https://github.com/getsops/sops
|
||
|
||
**IA**
|
||
- LM Studio : https://lmstudio.ai/
|
||
- LM Studio CLI : https://lmstudio.ai/docs/cli
|
||
- Hermes Agent : https://github.com/NousResearch/hermes-agent
|
||
- LiteLLM : https://docs.litellm.ai/
|
||
- Open WebUI : https://docs.openwebui.com/
|