- CLAUDE.md : état mis à jour (2026-05-13), gpu-01 → llama-server, setup IA → endpoints réels (llama-server + LiteLLM), rôles Ansible à jour, suppression CLI LM Studio - admin/lm_studio.md : marqué supprimé du cluster, lms CLI conservée pour téléchargement modèles uniquement, /opt/lmstudio disparu - admin/nfs.md : section modèles mise à jour (plus de symlink lmstudio) - admin/rocm.md : debug section → llama-server, section Vulkan supprimée - admin/README.md : description lm_studio.md mise à jour Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
7.3 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Présentation du projet
Funk — homelab IA composé d'un cluster Kubernetes (Talos) pour les services applicatifs, d'un hôte d'inférence LLM dédié (gpu-01 / llama-server ROCm), et d'un agent autonome (Hermes Agent) sur storage-01. Stack IaC complète : Ansible + talhelper + ArgoCD.
Référence complète : Funk/Funk-infra/HOMELAB.md
État actuel (2026-05-13) :
- ✅ Hermes Agent opérationnel sur storage-01 (llama-server GPU via LiteLLM)
- ✅ storage-01 installé —
192.168.10.1(LAN cluster),192.168.1.200(WAN) - ✅ gpu-01 installé — llama-server GPU (:1234) + CPU (:1236/:1237) opérationnels
- ✅ LiteLLM sur storage-01 — proxy multi-modèles + ask-agent
- ✅ Cluster k8s Talos opérationnel (MetalLB + Traefik + wildcard DNS lab.local)
- ⏳ WOL compute nodes non configuré (BIOS) — allumage manuel requis
Architecture des machines
| Machine | IP | OS | Rôle |
|---|---|---|---|
| storage-01 | 192.168.10.1 | AlmaLinux 9.7 | Passerelle + bastion admin + données + Hermes Agent — hors cluster |
| compute-01 | 192.168.10.11 | Talos v1.13+ | k8s control-plane |
| compute-02 | 192.168.10.12 | Talos v1.13+ | k8s worker |
| compute-03 | 192.168.10.13 | Talos v1.13+ | k8s worker |
| gpu-01 | 192.168.10.20 | AlmaLinux 9.7 | llama-server dédié (RX 6700XT, ROCm 7.x) — hors cluster |
Points clés d'architecture :
storage-01etgpu-01sont hors du cluster k8s — ils sont consommés via desExternalNameservices ouEndpointsmanuels- Le cluster n'a que 3 nœuds (compute-01/02/03), pas de GPU dans k8s
- Single control-plane assumé : si compute-01 tombe,
kubectl applyne fonctionne plus mais les workloads continuent
Structure du repo lab-infra (cible)
lab-infra/
├── ansible/ # gère storage-01 + gpu-01 (AlmaLinux)
│ ├── inventory.yml
│ ├── playbooks/site.yml
│ ├── group_vars/
│ └── roles/ # common, gateway, dnsmasq, nfs_server, postgresql,
│ # qdrant, minio, rocm, llama_server, litellm, hermes_agent, hermes_user
├── talos/ # nœuds Talos via talhelper
│ ├── talconfig.yaml # source de vérité (lue par talhelper)
│ ├── talsecret.sops.yaml
│ ├── talenv.yaml
│ ├── patches/
│ └── clusterconfig/ # généré → au .gitignore, ne pas committer
└── k8s/ # workloads k8s (ArgoCD)
├── argocd-bootstrap/
├── apps-of-apps/root.yaml
├── infra/ # metallb, traefik, cert-manager, longhorn, nfs-provisioner
└── apps/ # litellm, open-webui, n8n, monitoring,
# external-services (ExternalName vers storage-01/gpu-01)
Stack IaC — trois outils, trois cibles
| Outil | Cible | Déclenchement |
|---|---|---|
| Ansible | storage-01, gpu-01 (AlmaLinux) | Push manuel : ansible-playbook |
| talhelper | compute-01/02/03 (Talos) | Push manuel : talosctl apply-config |
| ArgoCD | Workloads k8s | Pull automatique depuis Git |
Ansible
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 # un rôle
Rôles : common, gateway, dnsmasq, nfs_server, nfs_client, postgresql, qdrant, minio, rocm, llama_server, litellm, hermes_agent, hermes_user. Tous idempotents. Secrets via Ansible Vault.
talhelper (nœuds Talos)
cd talos/
talhelper genconfig # régénérer configs nœuds
talhelper gencommand apply --node compute-02 | bash # appliquer sur un nœud
talhelper gencommand bootstrap --node compute-01 | bash # bootstrap (1ère fois seulement)
talhelper gencommand kubeconfig | bash # récupérer kubeconfig
talos/clusterconfig/ est généré — ne pas committer (mettre au .gitignore).
ArgoCD (workloads k8s)
Pattern "App of Apps" : modifier un manifest → git commit + git push → ArgoCD applique automatiquement (poll toutes les ~3 min).
vim k8s/apps/open-webui/deployment.yaml
git add k8s/apps/open-webui/
git commit -m "open-webui: bump to v0.4.0"
git push
Réseaux internes Kubernetes
- CNI (Flannel) — Pods :
10.42.0.0/16 - Services :
10.43.0.0/16 - MetalLB pool (IP virtuelles Traefik/services) :
192.168.10.200-230
Contrainte GPU critique
La RX 6700XT (gfx1031) n'est pas officiellement supportée par ROCm. Toujours s'assurer que la variable est présente dans le service systemd llama-server :
HSA_OVERRIDE_GFX_VERSION=10.3.0
ROCm tourne directement sur l'hôte AlmaLinux (pas dans des conteneurs). L'inférence est assurée par llama-server (llama.cpp compilé ROCm 7.x).
CLI lms disponible sur gpu-01 uniquement pour télécharger des modèles (lms get <url-hf>, lms ls).
Deux setups IA
Setup 1 — Poste perso (9950X3D) — dev local
| Composant | Endpoint |
|---|---|
| Ollama | http://127.0.0.1:11434 |
| LM Studio (optionnel) | http://127.0.0.1:1234/v1 |
| Hermes Agent | base_url: http://127.0.0.1:1234/v1 ou Ollama |
Setup 2 — Cluster Funk (production)
| Composant | Endpoint |
|---|---|
| llama-server GPU (gpu-01) | http://192.168.10.20:1234/v1 |
| llama-server CPU system (gpu-01) | http://192.168.10.20:1236/v1 |
| llama-server CPU monitor (gpu-01) | http://192.168.10.20:1237/v1 |
| LiteLLM proxy (storage-01) | http://127.0.0.1:4000/v1 (master_key: lm-studio) |
| Hermes Agent | service systemd sur storage-01, via LiteLLM |
# Vérifier l'état complet depuis le poste perso
funk-status
Conventions
- Domaine :
lab.local— wildcard DNS via dnsmasq sur storage-01 - Ingress :
<service>.lab.local→ IP MetalLB de Traefik (192.168.10.200-230) - llama-server endpoint :
http://192.168.10.20:1234/v1(GPU) — accès via LiteLLM sur storage-01 - Namespaces k8s :
argocd,infra,storage,external,ai,workflows - Git : branches
main(prod) /feature/*— commits en conventional commits (feat:,fix:,chore:,docs:) - Secrets : Ansible Vault (Ansible), SOPS+age (Talos via talhelper), Sealed Secrets (k8s)
Opérations cluster importantes
etcd backup (single control-plane → critique) :
talosctl etcd snapshot /path/to/backup.db --nodes compute-01
À planifier en cron Ansible vers le RAID5 de storage-01.
Hermes Agent — données persistantes dans ~/.hermes/ → doit résider sur le RAID5, pas sur le SSD OS.
Ce qui reste toujours manuel (GitOps ne peut pas bootstrapper lui-même) :
- Installation OS depuis USB (AlmaLinux ou Talos)
- Configuration IP/SSH minimale pour le premier Ansible
- Premier déploiement ArgoCD via Helm
RAM serrée sur compute-02/03 (8 GB)
Toujours définir resources.requests et resources.limits sur les pods déployés sur ces nœuds — sans quoi l'OOM-killer peut tuer kubelet.
Réservations à configurer dans talhelper :
system-reserved: cpu=500m,memory=1Gi
kube-reserved: cpu=500m,memory=1Gi