Hermès répondait « la doc ne le précise pas » à « combien de nœuds K8s + OS » alors que talos.md § Architecture contenait l'info — mais en TABLE : nomic embed mal une table face à une question en langage naturel (pas de « 3 »/« trois », OS implicite), donc le chunk ne remontait pas dans le top-k. Fix = phrase en prose dense en tête de la section (compte explicite + OS + rôles + les 2 hôtes AlmaLinux hors cluster). Le chunk passe #1 (score 0.743 vs ~0.69 avant). Validé après re-ingest : - « combien de nœuds K8s + OS » → « 3 nœuds, tous sous Talos Linux v1.13.0 » (docs=6) - « combien de machines + OS » → réponse nuancée (3 Talos + 2 AlmaLinux hors cluster) Leçon RAG : préfixer toute table dense d'une phrase en prose pour l'ancrage des questions naturelles « combien / quel ». Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
9.4 KiB
Talos Linux — Installation et administration du cluster
Cluster Kubernetes funk sur 3 ThinkCentre (AMD A10-9700E) via Talos Linux.
Architecture
Le cluster Kubernetes funk compte 3 nœuds (trois machines ThinkCentre), tous sous Talos Linux v1.13.0 (Kubernetes v1.33.1) : compute-01 est le control-plane, compute-02 et compute-03 sont des workers. Les deux autres machines du homelab — storage-01 (passerelle) et gpu-01 (llama-server) — sont hors du cluster et tournent sous AlmaLinux 9.7. Donc : 3 nœuds Kubernetes Talos + 2 hôtes AlmaLinux hors cluster.
| Nœud | IP | Rôle | Disque | RAM |
|---|---|---|---|---|
| compute-01 | 192.168.10.11 | control-plane | NVMe 256 GB (PNY/Samsung) | 16 GB |
| compute-02 | 192.168.10.12 | worker | NVMe 256 GB (PNY) | 8 GB |
| compute-03 | 192.168.10.13 | worker | NVMe 256 GB (PNY) | 8 GB |
- OS : Talos Linux v1.13.0
- Kubernetes : v1.33.1
- CNI : Flannel (pods
10.42.0.0/16, services10.43.0.0/16) - Single control-plane : si compute-01 tombe,
kubectlne fonctionne plus mais les workloads continuent
Outils requis (poste perso + storage-01)
# talhelper
curl -sL https://github.com/budimanjojo/talhelper/releases/latest/download/talhelper_linux_amd64.tar.gz | sudo tar xz -C /usr/local/bin talhelper
# age
AGE_VERSION=$(curl -s https://api.github.com/repos/FiloSottile/age/releases/latest | grep tag_name | cut -d'"' -f4)
curl -sL "https://github.com/FiloSottile/age/releases/download/${AGE_VERSION}/age-${AGE_VERSION}-linux-amd64.tar.gz" | sudo tar xz -C /tmp && sudo mv /tmp/age/age /usr/local/bin/ && sudo mv /tmp/age/age-keygen /usr/local/bin/
# sops
sudo curl -sL "https://github.com/getsops/sops/releases/download/v3.9.4/sops-v3.9.4.linux.amd64" -o /usr/local/bin/sops && sudo chmod +x /usr/local/bin/sops
# talosctl
curl -sL https://talos.dev/install | sh
# kubectl
curl -sL "https://dl.k8s.io/release/$(curl -sL https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl" -o /tmp/kubectl && sudo install /tmp/kubectl /usr/local/bin/kubectl
Structure du repo
talos/
├── talconfig.yaml # config déclarative — source de vérité
├── talsecret.sops.yaml # secrets chiffrés (SOPS/age) — commitable
├── patches/
│ ├── all.yaml # NTP + DNS → storage-01
│ └── workers.yaml # kubelet reserved resources (8 GB RAM)
└── clusterconfig/ # généré par talhelper — NE PAS committer
├── funk-compute-01.yaml
├── funk-compute-02.yaml
├── funk-compute-03.yaml
└── talosconfig
Clé age (SOPS)
# Générer une fois par poste admin
mkdir -p ~/.config/sops/age
age-keygen -o ~/.config/sops/age/keys.txt
# → noter la clé publique et l'ajouter dans .sops.yaml
La clé privée (
~/.config/sops/age/keys.txt) ne doit JAMAIS être committée.
Procédure d'installation (premier déploiement)
1. Préparer la clé USB
# Flasher l'ISO Talos directement (pas Ventoy)
sudo dd if=/mnt/data/talos/1.13/metal-amd64.iso of=/dev/sdX bs=4M status=progress conv=fsync
Utiliser le metal ISO directement (pas Ventoy) — Talos doit être le seul bootable sur la clé.
2. Générer les configs
cd talos/
# Générer les secrets (une seule fois)
talhelper gensecret | sops --filename-override talsecret.sops.yaml --encrypt /dev/stdin > talsecret.sops.yaml
# Générer les configs nœuds
talhelper genconfig
3. Booter chaque nœud en maintenance mode
- Brancher la clé USB sur le nœud, allumer
- Le nœud prend une IP DHCP dans
192.168.10.50-99(dnsmasq sur storage-01) - Vérifier les disques avant d'appliquer la config :
export TALOSCONFIG=talos/clusterconfig/talosconfig
talosctl get disks --insecure --nodes <IP-DHCP>
⚠️ Les ThinkCentre ont un NVMe (
nvme0n1), pas un SATA. Vérifier queinstallDisk: /dev/nvme0n1danstalconfig.yaml.
4. Appliquer la config
# compute-01
talosctl apply-config --insecure --nodes <IP-DHCP> --file talos/clusterconfig/funk-compute-01.yaml
# compute-02
talosctl apply-config --insecure --nodes <IP-DHCP> --file talos/clusterconfig/funk-compute-02.yaml
# compute-03
talosctl apply-config --insecure --nodes <IP-DHCP> --file talos/clusterconfig/funk-compute-03.yaml
Talos installe sur nvme0n1 et reboot automatiquement → nœud disponible sur son IP statique.
Si le nœud reboot sur un ancien OS (EFI entries) : lancer
talosctl upgrade --image ghcr.io/siderolabs/installer:v1.13.0 --nodes <IP>puis retirer la clé USB pendant le reboot.
5. Bootstrap etcd (une seule fois sur compute-01)
talosctl bootstrap --nodes 192.168.10.11
⚠️ Ne lancer qu'une seule fois — relancer sur un cluster existant casse etcd.
6. Récupérer le kubeconfig
talosctl kubeconfig --nodes 192.168.10.11 ~/.kube/config
kubectl get nodes
7. Flannel (CNI) — intégré à Talos
Talos v1.13 inclut Flannel nativement dans kube-system avec le bon CIDR 10.42.0.0/16.
Ne pas appliquer le manifest Flannel externe — ça crée un conflit de deux DaemonSets qui mettent les pods en CrashLoopBackOff.
Si vous avez appliqué le manifest externe par erreur :
kubectl delete namespace kube-flannel
# Corriger la ClusterRoleBinding pour pointer vers kube-system
kubectl patch clusterrolebinding flannel --type='json' \
-p='[{"op": "replace", "path": "/subjects/0/namespace", "value": "kube-system"}]'
kubectl delete pod -n kube-system -l app=flannel
Les nœuds passent NotReady → Ready en ~1 minute après le bootstrap.
8. Installer MetalLB
helm repo add metallb https://metallb.github.io/metallb
helm repo update
kubectl create namespace metallb-system
helm install metallb metallb/metallb --namespace metallb-system
# Attendre que les pods soient Running
kubectl get pods -n metallb-system -w
Configurer le pool d'IPs :
cat <<'EOF' | kubectl apply -f -
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: funk-pool
namespace: metallb-system
spec:
addresses:
- 192.168.10.200-192.168.10.230
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
name: funk-l2
namespace: metallb-system
spec:
ipAddressPools:
- funk-pool
EOF
9. Installer Traefik
helm repo add traefik https://traefik.github.io/charts
helm repo update
kubectl create namespace infra
helm install traefik traefik/traefik \
--namespace infra \
--set service.type=LoadBalancer \
--set service.loadBalancerIP=192.168.10.200 \
--set ports.web.port=80 \
--set ports.websecure.port=443 \
--set ingressRoute.dashboard.enabled=true \
--set logs.general.level=INFO
Vérifier que l'IP 192.168.10.200 est assignée :
kubectl get svc -n infra traefik
10. DNS wildcard *.lab.local
Le rôle dnsmasq Ansible configure automatiquement address=/.lab.local/192.168.10.200.
Après ansible-playbook --tags dnsmasq, tout nom <service>.lab.local résout vers Traefik.
Administration quotidienne
État du cluster
kubectl get nodes -o wide
kubectl get pods -A
talosctl --nodes 192.168.10.11,192.168.10.12,192.168.10.13 service
Logs et diagnostics
# Logs d'un service Talos
talosctl --nodes 192.168.10.11 dmesg | tail -30
talosctl --nodes 192.168.10.11 service etcd
# Logs d'un pod k8s
kubectl logs -n <namespace> <pod>
# Events k8s
kubectl get events -A --sort-by='.lastTimestamp'
Reboot / shutdown d'un nœud
# Reboot propre
talosctl --nodes 192.168.10.12 reboot
# Shutdown
talosctl --nodes 192.168.10.12 shutdown
# Tous les workers
talosctl --nodes 192.168.10.12,192.168.10.13 reboot
Mise à jour de la config d'un nœud
cd talos/
# 1. Modifier talconfig.yaml
# 2. Régénérer
talhelper genconfig
# 3. Appliquer (sans --insecure cette fois)
talosctl --nodes 192.168.10.11 apply-config --file clusterconfig/funk-compute-01.yaml
Backup etcd (critique — single control-plane)
talosctl --nodes 192.168.10.11 etcd snapshot /tmp/etcd-backup-$(date +%Y%m%d).db
# Copier vers storage-01 RAID5
scp /tmp/etcd-*.db storage-01:/srv/data/backups/etcd/
À planifier en cron hebdomadaire au minimum.
Variables d'environnement utiles
export TALOSCONFIG=~/Projets/lab/talos/clusterconfig/talosconfig
export KUBECONFIG=~/.kube/config
MACs des nœuds (baux DHCP statiques)
| Nœud | MAC | IP fixe |
|---|---|---|
| compute-01 | 6c:4b:90:82:8e:47 |
192.168.10.11 |
| compute-02 | 6c:4b:90:cf:7f:c5 |
192.168.10.12 |
| compute-03 | 6c:4b:90:b6:49:20 |
192.168.10.13 |
Points d'attention
| Sujet | Détail |
|---|---|
| installDisk | Toujours nvme0n1 sur ces ThinkCentre — ne pas mettre /dev/sda (clé USB) |
| USB ISO | Flasher le metal ISO directement avec dd, pas Ventoy |
| Bootstrap | Une seule fois sur compute-01, jamais relancer |
| etcd backup | Critique sur single control-plane — planifier en cron |
| RAM workers | 8 GB sur compute-02/03 — toujours définir resources.requests/limits |
| VIP | Ne pas configurer de VIP = même IP que le nœud — inutile et cassant |
| Flannel externe | Ne PAS appliquer le manifest Flannel officiel — Talos l'inclut nativement |
| ClusterRoleBinding flannel | Doit pointer vers kube-system, pas kube-flannel |
| MetalLB webhook | Nécessite que Flannel soit 100% healthy avant d'appliquer IPAddressPool |