Le cluster K3s a un voisin de rack : un NAS qui héberge la stack media et Nextcloud, hors cluster, en Docker Compose. L’actuel — un i5-4690 de 2014, 84W de TDP — fatigue. Son remplaçant s’appelle gbnas : un build silencieux autour d’une carte ASRock N100M, pensé pour trois rôles : NAS, cible de backup pour le cluster, et station de travail pour l’agent qui pilote l’infra.
Cette partie 1 couvre le build et la première intégration : faire entrer une machine x86 dans l’écosystème de monitoring d’un cluster ARM. La migration de la stack media est couverte en partie 2.
Le build
| Composant | Choix | Pourquoi |
|---|---|---|
| Carte mère | ASRock N100M (mATX) | Intel N100 intégré, 4 cores, TDP 6 W, iGPU QuickSync |
| Boîtier | Jonsbo N4 | 6 baies 3.5” + 2× 2.5” — 3 baies libres pour grandir |
| Alim | be quiet! SFX Power 3 450W | silencieuse, très large marge |
| Disques | WD Red Plus 6 To (CMR) | miroir RAID1 mdadm (~5,5 Tio utiles), baies libres pour grandir |
| SSD | NVMe 256 Go (OS) + SATA 500 Go (apps Docker) | séparer OS / appdata / données |
| Réseau | carte PCIe 2.5GbE | le lien vérifié à 2500 Mb/s |
| Ventilation | Noctua NF-A12x25 + NF-A6x15 | inaudible |
| Contrôleur SATA | StarTech PCIe x1 | le N100M n’a que 2 ports SATA natifs |
Deux particularités du N100M à connaître : un seul slot SO-DIMM DDR4 (max 16 Go), et seulement 2 ports SATA — d’où le contrôleur PCIe. Les deux slots PCIe sont donc occupés (réseau + SATA), il ne reste que le M.2.
Comparé au sortant : Passmark équivalent (~5500 vs ~5100) pour 14× moins de TDP (6 W vs 84 W), et un QuickSync moderne qui décode l’AV1 — le transcodage Jellyfin se fera en hardware.
OS : Ubuntu Server, sans hésiter longtemps
J’ai pesé TrueNAS Scale (ZFS natif mais ~1 Go RAM/To, et 16 Go max ici), Proxmox (overkill pour un NAS mono-usage), Unraid (licence). Ubuntu Server a gagné par pragmatisme : la stack actuelle est du Docker Compose pur — la migration sera un rsync + docker compose up, pas une réinstallation conceptuelle.
Setup réalisé : IP fixe 10.0.0.30, Docker + Compose, et le lien 2.5GbE validé à l’iperf3 : 2.37 Gbit/s stables vers le PC. Le speedtest internet plafonne à ~1 Gbit/s symétrique — c’est l’abonnement qui limite, pas la machine.
L’intégration monitoring : une cible de scrape comme les autres
Le réflexe à éviter : installer une stack de monitoring sur le NAS (un deuxième Grafana, un Netdata local…). Le NAS n’est pas dans le cluster, mais il n’a aucune raison d’avoir sa propre observabilité : vmagent scrape ce qu’on lui dit de scraper, dans ou hors cluster.
job vmagent en plus (instance="gbnas"), et l'invité x86 apparaît dans les mêmes
dashboards que les Pi. SMART inclus via smartctl_exporter (température et santé des disques). The NAS is not in the cluster — it's a scrape target like any other :
one more vmagent job (instance="gbnas"), and the x86 guest shows up in the same
dashboards as the Pis. SMART included via smartctl_exporter (disk temperature and health). node_exporter — 10 lignes
Un container sur le NAS, un job statique côté vmagent :
# monitoring/vm/vmagent-values.yaml
- job_name: nas-gbnas
static_configs:
- targets: ['10.0.0.30:9100']
labels:
instance: gbnas
role: nas
Résultat immédiat : gbnas apparaît dans le dashboard « Benchmarks — toutes les machines » à côté des 6 Pi. CPU, RAM, disque, réseau, températures — mêmes panels, mêmes alertes possibles. Lors d’un audit réseau la semaine précédente, le NAS était littéralement invisible dans les mesures ; ce trou est bouché.
Portainer — l’agent, pas un deuxième Portainer
Pour les conteneurs du NAS (la future stack media), Portainer — qui tourne dans le cluster — sait gérer plusieurs environnements. Un agent sur le NAS :
services:
portainer_agent:
image: portainer/agent:2.42.0
restart: always
ports: ["9001:9001"]
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- /var/lib/docker/volumes:/var/lib/docker/volumes
Subtilité de topologie : agent standard, pas Edge Agent. L’agent standard se fait contacter par Portainer (pod → 10.0.0.30:9001) — trivial sur un même LAN. L’Edge Agent inverse le sens (NAS → tunnel Portainer), ce qui obligerait à exposer un port via Cloudflare. Sur un LAN : standard, et le port 9001 reste strictement interne (il expose le socket Docker — jamais à travers le tunnel).
smartctl_exporter — et le piège ARM64
Des disques mécaniques qui tourneront 24/7 méritent mieux qu’un smartctl -a manuel trimestriel. smartctl_exporter expose température, heures de vol, secteurs réalloués, statut SMART — sur le NAS et sur les SSD des nœuds du cluster (DaemonSet privilégié, accès /dev).
Le piège qui a coûté une soirée : depuis la v0.7.0, l’image officielle publiée est amd64-only. Sur les Pi : exec format error en boucle. Le fix — épingler par digest la dernière image multi-arch :
# Le tag "latest" ment sur ses architectures. Le digest, jamais.
# (digest tronqué ci-dessous pour lisibilité)
image: quay.io/prometheuscommunity/smartctl-exporter@sha256:b71402…
C’est le même réflexe que pour le pinning par digest en CI, appliqué pour une raison différente : non pas la reproductibilité, mais la vérité architecturale. Sur un parc mixte ARM/x86, un tag flottant peut changer d’architectures supportées sous vos pieds.
Les alertes qui viennent avec
L’intégration au monitoring n’est pas que cosmétique — le NAS hérite du pipeline d’alerting du cluster. Prochaines règles dédiées aux disques :
- alert: NasDiskTemperature # smartctl_device_temperature > 50°C
- alert: NasDiskUnhealthy # smartctl_device_smart_status != 1
- alert: NasDiskAlmostFull # le miroir RAID1 > 85%
La suite (partie 2)
La migration a eu lieu — et le plan n’a pas survécu intact au contact de la réalité (spoiler : le RAIDZ1 a perdu contre un miroir mdadm). La stack media complète, Nextcloud et deux invités surprise tournent désormais sur gbnas : partie 2 — la stack media déménage.
Resteront ensuite les chantiers où le NAS sert le cluster : backups Longhorn déchargés du précieux SSD de worker-2, CronJob de backup hors cluster, StorageClass NFS.