12 minutes
Homelab — Inventaire
Histoire de contextualiser mes expérimentations, je tenais à poser à l’écrit l’architecture de mon homelab, et ses usages.
Serveurs
Gath, serveur multi-usages
▗▄▄▄ ▗▄▄▄▄ ▄▄▄▖ root@gath ▜███▙ ▜███▙ ▟███▛ --------- ▜███▙ ▜███▙▟███▛ OS: NixOS 23.11.6621.dd37924974b9 (Tapir) x86_64 ▜███▙ ▜██████▛ Host: Gigabyte Technology Co., Ltd. TRX40 AORUS PRO WIFI ▟█████████████████▙ ▜████▛ ▟▙ Kernel: 6.6.27 ▟███████████████████▙ ▜███▙ ▟██▙ Uptime: 6 days, 10 hours, 20 mins ▄▄▄▄▖ ▜███▙ ▟███▛ Packages: 1013 (nix-system), 966 (nix-default) ▟███▛ ▜██▛ ▟███▛ Shell: bash 5.2.15 ▟███▛ ▜▛ ▟███▛ Resolution: 1920x1080 ▟███████████▛ ▟██████████▙ Terminal: /dev/pts/0 ▜██████████▛ ▟███████████▛ CPU: AMD Ryzen Threadripper 3960X (48) @ 4.100GHz ▟███▛ ▟▙ ▟███▛ GPU: NVIDIA GeForce RTX 3080 ▟███▛ ▟██▙ ▟███▛ GPU: NVIDIA GeForce GTX 1060 6GB ▟███▛ ▜███▙ ▝▀▀▀▀ GPU: AMD ATI Radeon RX 6950 XT ▜██▛ ▜███▙ ▜██████████████████▛ Memory: 72582MiB / 96419MiB ▜▛ ▟████▙ ▜████████████████▛ ▟██████▙ ▜███▙ ▟███▛▜███▙ ▜███▙ ▟███▛ ▜███▙ ▜███▙ ▝▀▀▀ ▀▀▀▀▘ ▀▀▀▘
Le cœur de mon homelab est constitué depuis 2020 d’un serveur un peu fourre-tout, hébergeant, grosso modo :
- mon NAS, pour 38Tio disponibles et redondés (ZFS)
- accès au stockage sur un réseau Samba et NFS, pour les machines sur le réseau local, et les VM de Gath
- divers serveurs de productivité (suite mail/calendrier sous Mailcow)
- des services de gestion de bibliothèque multimedia (Plex, Sonarr, Radarr, …)
- des services de téléchargement de contenu légal (Bittorrent Transmission)
- deux machines virtuelles de bureau/jeu attachées à un GPU chacun
- une troisième carte graphique utilisée occasionnellement (transcodage de mes bibliothèques multimedia avec Tdarr, reconnaissance vocale via Whisper pour Home Assistant, …)
- des serveurs de jeu, occasionnellement (via Pterodactyl pour mutualiser la gestion)
Hardware
L’architecture matérielle a beaucoup évoluée depuis l’acquisition du serveur, d’occasion, en 2019. En particulier :
- Je suis passé d’un bi-Xeon à un Threadripper 3960X, bien plus pratiques pour les lanes PCIe, les performances mono-cœur, et l’absence de NUMA (qui est une grosse contrainte à la mutualisation des ressources)
- J’ai fait évoluer les cartes graphiques (pour des besoins en jeu), me permettant de conserver un GPU bas de gamme pour l’accélération matérielle de certains services
- Je suis passé d’un RAID 0 sur quatre disques à une topologie ZFS type RAID 10 (3 mirroirs de 2 disques, soit 6 disques)
- Pour des bottlenecks en IOPS sur mes disques, j’ai ajouté un NVME en tant que L2ARC, un cache de lecture des données chaudes
- Plus tard, j’ai remplacé mon L2ARC par un special device sur un mirroir de NVME, me permettant de stocker toutes les métadonnées sur un stockage rapide, et définir avec précision, répertoire par répertoire, une classe de stockage (NVME ou RAID 10)

Le mélange un peu insouciant des usages sur un unique serveur a fait apparaître énormément de bottlenecks à des endroits inattendus. D’abord côté hardware :
Le refroidissement
Premiers problèmes autour du refroidissement, surtout pour un Threadripper !
J’ai pu installer un bloc de watercooling pour le processeur (Alphacool Eisbaer Pro Aurora 360) immédiatement, pour les besoins du Threadripper. Le radiateur de cet AIO étant en cuivre plaqué nickel, c’était un choix orienté pour du passage de la pâte thermique au métal liquide (qui a parfois des réactions désastreuses selon l’alliage utilisé pour le radiateur du CPU).
J’ai dû remplacer les 6 ventilateurs d’origine par 8 Noctua NF-A12 (d’une moyenne à ~80°C idle à ~72°C), puis j’ai remplacé la pâte thermique par du métal liquide (~72°C idle -> ~62°C).
(Pour information, Gath a un load average idle sur 5 minutes à 5.)
J’ai un projet pas encore planifié du passage des deux gros GPU sur du watercooling, et d’ajouter un radiateur externe type Mo-Ra (pour éviter les contraintes actuelles d’air-flow pas top des GPU). Soit en série du circuit de watercooling du CPU, soit sur une boucle à part.
Le châssis
J’ai longtemps réfléchi à un format rack. J’y réfléchis encore.
La problématique étant la suivante :
- un support E-ATX pour qu’une grande carte mère avec beaucoup de slots PCIe puisse être installée
- le châssis doit pouvoir accueillir au moins 3 cartes graphiques
- j’ai besoin d’avoir des emplacements PCIe verticaux, pour d’éventuelles cartes d’extension (j’envisage un NIC 10Gbps)
- il doit disposer de suffisamment d’emplacements de ventilateurs, et d’un radiateur pour du watercooling
- un maximum de disques durs (6 disques actuellement, avec un objectif de 8 disques durs ; le plus étant le mieux)
Pour cette raison, je suis parti sur le Phanteks Enthoo 719 qui est sur la photo plus haut. Il permet d’installer pas mal de disques (jusqu’à 12), supporte la carte mère, permet l’installation du bloc d’alimentation à l’arrière, et a beaucoup d’emplacements ventilateurs.
Les carte graphiques
Contrainte évidente de form-factor de cartes graphiques, qui ne peuvent pas dépasser les 2 slots PCIe de large (pour permettre l’installation d’autres périphériques PCIe au-dessous), et une certaine longueur pour évider de gêner le passage des connectiques carte mère.
Deux cartes graphiques sont dédiées aux machines virtuelles (une Nvidia RTX3080, et une AMD RX5960 XT pour une tentative pas encore conclue de Hackintosh). Une troisième (Nvidia GTX1060) me sert de transcodage vidéo, et d’accélération matérielle pour Whisper (un serveur de reconnaissance vocale).
Côté software
D’autres contraintes de choix de logiciel, et de maintenance, ici aussi.
Côté BIOS, deux choses que j’ai besoin de vérifier au setup/en cas de reset CMOS :
- le support des adresses PCIe étendues, indispensable pour connecter tous les périphériques PCIe (l’option BIOS « Above 4G decoding » qui permet le support 64bits des adresses PCIe)
- l’attribution exacte des lanes PCIe (ça m’est arrivé d’avoir une réinitialisation du BIOS qui me repasse un GPU en x8x8, initialement en x16, bloquant le démarrage)
Côté OS, d’autres contraintes :
- la supervision à distance en cas de pépin (Gath étant à la fois serveur et terminal)
- la capacité à composer, maintenir, et exécuter toutes les charges de travail radicalement différentes de manière simple et fiable
- la gestion des pannes de disque
- la répartition des ressources entre toutes ces applications différentes, des bottlenecks/freezes survenant lorsque : a. plusieurs process remplissent la RAM en même temps (réservation de la RAM, hugepages, swap sur un NVMe) b. les cœurs sont mal répartis entre les processus, et les caches CPU changent trop de contexte (réservation des cœurs dynamiquement via les cgroups, via la topologie CPU) c. les besoins réseau sont identiques au même moment (ports, download, upload) d. les besoins réseau sont différents (utilisation d’un tunnel VPN pour certains services seulement) e. tous les services remplissent les disques en même temps (le daemon Docker étant brické lorsque l’espace disque disponible passe à 0) f. un processus fait exploser les IOPS et la latence disque car il n’y a pas de throttling ou limite d’I/O (une opération de copie, par exemple, n’étant pas limitée par le réseau, elle utilise automatiquement 100% des ressources disque disponibles et ralentit immédiatement toutes les autres I/O)
Pour ces raisons, NixOS est une distribution de choix pour la possibilité de définir toutes les charges de travail dans un répertoire unique de configuration (j’en ai parlé très rapidement plus en détail ici).
Architecture disques et ZFS
Ayant un peu creusé le sujet depuis 2016, j’ai eu plusieurs aventures (plus ou moins fructueuses) avec ZFS. Les plus gros reproches que j’ai pu faire étaient liés à des choix d’architecture du driver ZFS-on-Linux, dont le développement a, depuis, été rappatrié vers OpenZFS 2.0.
Une des fonctionnalités banales, que j’utilise très régulièrement, sont les snapshots ZFS (des instantanées des volumes,
avec une granularité au répertoire), qui permettent de backup très rapidement, de naviguer dans l’historique (à la
manière de Time Machine sous OSX), et sur lesquelles on peut rollback en quelques secondes. Ça m’a sauvé de nombreuses
pannes de corruptions de partition NTFS pour les VM Windows (qui sont stockées dans des volumes ZFS), d’erreurs de
configuration, ou de rm -rf un peu trop rapides.
Côté architecture et topologies, j’ai pu en tester plusieurs : RAIDZ1 sur 6 disques de 12Tio (mauvaise idée !), disque simple sur un laptop (pas beaucoup d’avantages), et, sur Gath, un stripe de mirrors (type RAID10) :
NAME
goliath
mirror-0
ata-ST12000NE0008-1ZF101_ZTN0Z5H4-part1
ata-ST18000NM000J-2TV103_WR50GFXE-part2
mirror-4
ata-ST18000NM000J-2TV103_WR504ES7-part2
ata-ST18000NM000J-2TV103_WR504PA2-part2
mirror-5
ata-ST18000NM000J-2TV103_WR504EGE-part2
ata-ST18000NM000J-2TV103_WR5049G6-part2
specia
mirror-7
nvme-WDS100T1X0E-00AFY0_2140JY444704-part1
nvme-Samsung_SSD_980_PRO_1TB_S5GXNX0W378949K-part1
Le strip permet pas mal de choses. Rien de nouveau, pour les capacités théoriques de lectures et d’écriture qui fonctionnent comme avec un RAID10 hardware :
- capacité de lecture théorique égale à la somme de la capacité de tous les disques (ici, 6)
- capacité en écriture égale au disque le plus lent multipliée par le nombre de VDEVs dans le stripe (ici, 3)
Ceci dit, ZFS offre d’autres avantages :
- la possibilité d’étendre le stripe avec d’autres VDEVs, de topologie identique aux autres VDEVs (ici, je suis passé de 2 à 4 disques, puis de 4 à 6)
- le fait de pouvoir upgrade la capacité des VDEVs (je planifie actuellement le remplacement de
ata-ST12000NE0008-1ZF101_ZTN0Z5H4, de 12Tio, par un 18Tio, chose déjà faite pour son miroir) - la possibilité d’utiliser un NVMe en plus de la RAM pour le cache de lecture des fichiers fréquemments lus, et récemment lus (L2ARC)
- la possibilité de stocker toutes les métadonnées et les petits fichiers sur un NVMe, pour éviter les petites lectures fréquentes et fragmentées sur des disques lent, et les déporter sur un NVMe (ZFS Special Device)
- une configuration qui permet de déporter tous les petits fichiers (voire tous les fichiers d’un répertoire donné) sur un NVMe via le Special Device
Ici, j’ai pu expérimenter le L2ARC, qui a très largement amélioré les performances de certaines tâches sur des lectures répétitives, mais les patterns de petites écritures fréquentes, ainsi que les lectures aléatoires fréquentes, le passage au Special Device était du pain béni.
J’ai déplacé toutes les métadonnées Goliath vers un NVMe, avec certains répertoires dont les I/O sensibles (volume de jeux Steam, bases de données, binaires d’application, configuration systemd, …).
Hass, un NUC pour les gouverner tous
___ root@hass (.. | os Home Assistant OS 12.2 (<> | host x86_64 / __ \ kernel 6.6.25-haos ( / \ /| uptime 4d 13h 34m _/\ __)/_) memory 1873M / 7821M \/-____\/
Étant un peu compliqué de surveiller Gath depus Gath, j’ai préféré installer toute ma solution de pilotage domotique et systèmes (Home Assistant) ainsi que ma solution de monitoring (Grafana + InfluxDB) sur un NUC dédié.
Gefjon, pour assigner des IP publiques OVH vers mes services
_,met$$$$$gg. root@gefjon ,g$$$$$$$$$$$$$$$P. ----------- ,g$$P" """Y$$.". OS: Debian GNU/Linux 10 (buster) x86_64 ,$$P' `$$$. Host: OpenStack Nova 19.0.4 ',$$P ,ggs. `$$b: Kernel: 4.19.0-24-cloud-amd64 `d$$' ,$P"' . $$$ Uptime: 344 days, 22 hours, 51 mins $$P d$' , $$P Packages: 775 (dpkg) $$: $$. - ,d$$' Shell: fish 3.0.2 $$; Y$b._ _,d$P' CPU: Intel (Haswell, no TSX) (1) @ 2.399GHz Y$$. `.`"Y$$$$P"' GPU: Cirrus Logic GD 5446 `$$b "-.__ Memory: 224MiB / 1949MiB `Y$$ `Y$$. `$$b. `Y$$b. `"Y$b._ `"""
Mini VPS hébergé par OVH avec un sous-réseau /29 public, et de l’IP-forwarding et reverse-proxy vers certaines ressources.
Ça a été une vraie problématique pour le serveur mail, puisque l’envoi d’email depuis mon fournisseur d’accès à internet tombait systématiquement en spam (mon adresse IP publique étant flaggée « personnelle »).
Le serveur s’articule autour :
- d’une Debian (NixOS sur un VPS OVH, quand j’ai cherché, c’était un jeu qui n’en valait pas la chandelle)
- d’une config
iptablespersistente - d’un Traefik pour le reverse proxy HTTP, les redirections de port TCP & UDP
- du module Let’s Encrypt de Traefik pour le SSL
- de Docker Compose pour orchestrer Traefik
Feanor, laptop M1
Étant assez indispensable d’avoir une machine fiable pour débugger les autres, j’ai un Macbook Pro M1 que j’utilise à titre perso quand je sors de chez moi, ou que j’ai besoin de travailler sur Gath (surtout sur des redémarrages intempestifs). Par exemple, ça me permet de déboguer une machine virtuelle capricieuse qui ne démarre pas, et, essentiellement, d’avoir une deuxième machine-terminal quand Gath (ou les VM) sont K.O.
SteamDeck
.,,,,. deck@steamdeck .,'onNMMMMMNNnn',. -------------- .'oNMANKMMMMMMMMMMMNNn'. OS: SteamOS Holo x86_64 .'ANMMMMMMMXKNNWWWPFFWNNMNn. Host: Jupiter 1 ;NNMMMMMMMMMMNWW'' ,.., 'WMMM, Kernel: 6.1.52-valve16-1-neptune-61 ;NMMMMV+##+VNWWW' .+;'':+, 'WMW, Uptime: 5 mins ,VNNWP+######+WW, +: :+, +MMM, Packages: 975 (pacman), 57 (flatpak) '+#############, +. ,+' +NMMM Shell: fish 3.6.1 '*#########*' '*,,*' .+NMMMM. Resolution: 1200x1920 `'*###*' ,.,;###+WNM, Terminal: tailscaled .,;;, .;##########+W CPU: AMD Custom APU 0405 (8) @ 2.800GHz ,',. '; ,+##############' GPU: AMD ATI AMD Custom GPU 0405 '###+. :,. .,; ,###############' Memory: 1463MiB / 14810MiB '####.. `'' .,###############' '#####+++################' '*##################*' ''*##########*'' ''''''
Peut-être l’objet d’un article à venir, j’ai configuré mon SteamDeck en tant que terminal de jeu en streaming, dont l’hôte est sur Gath (via ma machine virtuelle Buri, rattachée à une AMD RX6950 XT).
Ça me permet de jouer avec une excellent qualité graphique, et sans tirer sur la batterie. Ça me permet aussi de jouer plus facilement aux jeux qui ne tournent pas sous Linux, en les streamant depuis une VM Windows.
J’ai eu l’occasion de modder la console pour avoir un écran 1920×1200 (au lieu de l’écran original à 1280×800), et je stream les jeux depuis Gath avec le client Moonlight + un serveur Sunshine (réimplémentation libre du protocole Game Stream, enterré par Nvidia), en local et via internet. Ça me permet de streamer des jeux en bonne qualité, avec une faible latence, du HDR, et sans pomper la batterie du SteamDeck. Une solution semblable à Parsec (plus connu), mais avec un encodeur plus efficace et moins de compression sur un réseau local.
Réseau
Sans doute la partie la moins peaufinée, je commence à passer tout mon réseau sous TailScale (qui propose du SSO, un VPN mesh, une latence faible, un DNS interne… ; bref, une distribution clé-en-main pour un VPN WireGuard efficace et performant).
Volsung
_______ root@OpenWrt | |.-----.-----.-----. os OpenWrt 19.07.7 | - || _ | -__| | host Linksys WRT3200ACM |_______|| __|_____|__|__| kernel 4.14.221 ________|__| __ uptime 87d 21h 53m | | | |.----.| |_ pkgs 156 | | | || _|| _| memory 295M / 499M |________||__| |____|
Le routeur qui s’occupe de gérer toutes les redirections de port entre l’IP publique de mon FAI, et mon réseau privé à la maison. Un des points d’entrée obligatoires, Gefjon ayant une IP publique un peu meilleure, mais avec +15ms de latence vers l’extérieur…
Volsung fait aussi routeur WiFi.
Je songe à passer prochainement Volsung via TailScale, en tant qu’exit node possible, et gérer toutes mes redirections de port et d’IP sur TailScale plutôt que sur mon réseau physique WiFi & Ethernet.
Volsung fait également office de cache DNS et de bloqueur de publicité DNS via la solution intégrée à OpenWRT.
Routeur FAI
J’ai pris l’habitude d’utiliser le port forwarding pour rediriger tout le traffic entrant sur Volsung, histoire de ne jamais être embêté quand je change de fournisseur d’accès à internet.
À défaut d’avoir une option d’IP forwarding, je forward tous les ports (1-65535, en UDP et TCP) vers Volsung.
2454 Mots
2024-04-25 11:10