
🌐 Aussi en: English · Deutsch · Español
Dans le dernier article, j’ai présenté le plan de reconstruction de mon homelab en petit datacenter façon entreprise : cinq piliers, huit jalons, un article de blog par jalon. Le jalon 1 est la fondation sur laquelle repose tout le reste — trois machines physiques transformées en un seul cluster Proxmox VE, plus le module Terraform qui provisionne désormais chaque VM par-dessus. Cet article couvre les deux. Avertissement : ce projet est un chantier permanent. Rien ici n’est « terminé » ni définitif — c’est au mieux une bêta, et ça change sans arrêt au fil de l’eau. Considérez cet article comme un instantané de l’état des choses au moment où je l’ai écrit, pas comme une installation achevée.🎯 Objectif de ce jalon
Deux conditions devaient être remplies avant que je puisse toucher à Active Directory, GitLab ou Kubernetes :- Trois machines HP distinctes devaient devenir un seul cluster Proxmox VE, afin que les VM puissent être gérées, migrées et sauvegardées depuis une interface unique.
- Plus aucune VM ne devait naître à coups de clics. Chaque VM — du contrôleur de domaine au control plane Kubernetes — est créée par
terraform apply, pas par un assistant dans l’interface Proxmox.
🖥️ Matériel
Trois machines HP, volontairement différentes — c’est du matériel recyclé, pas un lot assorti :| Hôte | RAM | Stockage | IP de gestion |
|---|---|---|---|
| HP1 | 64 GB | SSD système 512 GB + SSD 2 TB | 192.168.10.x |
| HP2 | 32 GB | SSD système 512 GB + SSD 2 TB | 192.168.10.x |
| HP3 | 32 GB | SSD système 512 GB + 3×2 TB (ZFS RAIDZ1) | 192.168.10.x |
💽 Installer Proxmox VE
Rien d’extraordinaire pour l’installation elle-même : l’ISO Proxmox VE 9.2, écrite sur une clé USB avec Rufus, une clé par machine, démarrage, installation, et on recommence trois fois. Pas de média virtuel distant, pas de PXE — pour trois machines posées sur le même bureau, une clé USB reste le chemin le plus rapide entre zéro et un hyperviseur qui tourne. Chaque nœud a reçu pendant l’installation une IP statique sur le réseau de gestion192.168.10.x/24 (.30, .40, .50 pour HP1–HP3), qui sert aussi de réseau au cluster et à toutes les VM — j’y reviens plus bas, avec le compromis que ça implique. Une étape post-installation sur les trois : changer les dépôts de paquets. Par défaut, Proxmox pointe vers le dépôt Enterprise, qui exige un abonnement payant pour récupérer réellement des mises à jour. En suivant la procédure documentée par Proxmox, j’ai désactivé le dépôt Enterprise et fait pointer chaque nœud vers le dépôt No-Subscription à la place — parfait pour les tests et un usage hors production, ce qui est exactement la définition d’un homelab, simplement sans le même niveau de validation que le dépôt Enterprise :# /etc/apt/sources.list.d/proxmox.sources
Types: deb
URIs: http://download.proxmox.com/debian/pve
Suites: trixie
Components: pve-no-subscription
Signed-By: /usr/share/keyrings/proxmox-archive-keyring.gpgEnsuite, la tournée habituelle sur les trois nœuds avant toute autre chose :apt-get update
apt-get upgrade
apt-get dist-upgrade🌐 Réseau
Chaque nœud dispose d’une seule carte réseau, pontée envmbr0 (bridge Linux, STP désactivé), à laquelle le network_device de chaque VM se raccorde ensuite. Un second port réseau intégré existe sur les cartes mères, mais reste inutilisé pour l’instant — un candidat pour un réseau dédié au stockage ou à corosync plus tard, mais rien dont un cluster homelab à 3 nœuds ait besoin dès le premier jour. C’est d’ailleurs la seule simplification délibérée qui mérite d’être signalée : corosync (le protocole de heartbeat et de quorum du cluster) passe par le même réseau que le trafic de gestion et des VM, avec un seul anneau :ring0_addr: HP1 = 192.168.10.x
ring0_addr: HP2 = 192.168.10.x
ring0_addr: HP3 = 192.168.10.xDans un cluster de production, on isolerait corosync sur son propre VLAN ou ses propres cartes réseau, pour qu’un réseau de gestion saturé ne puisse pas provoquer de perte de quorum intempestive. Pour trois nœuds sur un réseau domestique sans autre trafic qui se dispute la bande passante, ce risque est acceptable — c’est sur la liste des choses à revoir si tout ça dépasse un jour le stade du homelab. Si jamais vous subissez une perte de quorum intempestive, RackNotes propose un guide complet sur le calcul des votes, les modes de défaillance de Corosync, QDevice et les procédures de récupération : Proxmox cluster quorum loss.🔗 Former le cluster
Procédurepvecm standard : créer le cluster sur HP1, puis y faire rejoindre HP2 et HP3. Avec trois membres votants, le cluster tolère exactement un nœud hors ligne (2 votes sur 3) avant de perdre le quorum — la configuration HA minimale viable, et la raison même pour laquelle j’ai choisi trois nœuds plutôt que deux. Une interrogation du cluster aujourd’hui confirme que le scénario idéal a tenu :$ pvecm status
Cluster name: homelab
Quorate: Yes
Nodes: 3
Nodeid Ip Name
1 192.168.10.x HP1 (local)
2 192.168.10.x HP2
3 192.168.10.x HP3🗄️ Organisation du stockage
C’est ici que les trois nœuds cessent d’être identiques. Le second disque de chaque nœud (ou les disques, pour HP3) est configuré différemment, et c’est voulu :- HP1 & HP2 : le SSD supplémentaire de 2 To est ajouté comme simple stockage de type répertoire (
data/data-hp2) — pas de ZFS, pas de RAID, juste un système de fichiers pour les disques de VM, les ISO et les sauvegardes. Un seul SSD, rien à mettre en miroir, donc l’option la plus simple l’emporte. - HP3 : trois disques de 2 To forment un pool ZFS en RAIDZ1 (
data-hp3), ce qui donne un peu moins de 4 To utilisables avec une tolérance de panne d’un disque. C’est le nœud réservé à tout ce que je ne veux pas perdre à cause d’un seul disque mort — pensez aux réplicas Longhorn ou aux données MinIO une fois Kubernetes en place.
local (système de fichiers racine) et local-lvm (LVM-thin sur le SSD système) créés par l’installateur, utilisés pour le système lui-même et comme débordement.🧱 Du ClickOps à l’Infrastructure as Code
Une fois le cluster en place, la tentation suivante est de cliquer sept fois sur « Create VM » dans l’interface Proxmox. C’est exactement ce que j’avais fait dans la version précédente de ce homelab, et chaque VM avait fini par être légèrement différente — un paramètre cloud-init oublié ici, une IP statique tapée à la main là, et aucune trace de ce que j’avais réellement fait six mois plus tard. Pas cette fois : chaque VM de cette reconstruction est définie une seule fois, dans Terraform, et reproductible à partir d’un cluster vierge.⚙️ Le module Terraform
Le module se trouve dans 01_terraform/ dans le dépôt du projet et utilise le provider bpg/proxmox. Plutôt que de monter une ISO Ubuntu Server et de cliquer tout au long de l’installateur, chaque VM est clonée à partir d’une image cloud Ubuntu 26.04 et configurée entièrement via cloud-init — IP statique, DNS, clé SSH, tout — si bien qu’il n’y a aucune étape d’installation interactive nulle part dans le pipeline :resource "proxmox_download_file" "ubuntu_cloud_image" {
content_type = "iso"
datastore_id = var.image_datastore_id
node_name = var.proxmox_node
url = var.ubuntu_cloud_image_url
file_name = "noble-server-cloudimg-amd64.img"
overwrite = false
}
resource "proxmox_virtual_environment_vm" "vm" {
for_each = local.vms
name = each.key
tags = ["terraform", "rebuild-2026"]
node_name = var.proxmox_node
vm_id = each.value.vmid
disk {
datastore_id = var.vm_datastore_id
file_id = proxmox_download_file.ubuntu_cloud_image.id
interface = "scsi0"
size = each.value.disk_gb
}
initialization {
ip_config {
ipv4 {
address = "${each.value.ip}/${var.network_prefix}"
gateway = var.network_gateway
}
}
user_account {
username = var.vm_username
keys = var.ssh_public_keys
}
}
}Les sept VM — une par rôle pour ce jalon — sont déclarées dans une seule map locals.vms, si bien qu’ajouter une huitième VM plus tard se résume à un diff de cinq lignes, et non à un bloc resource copié-collé :| Nom | Rôle | IP | RAM | Disque |
|---|---|---|---|---|
| HP1-dc01 | AD / DNS / CA racine | 192.168.10.x | 4 GB | 60 GB |
| HP1-gitlab01 | GitLab / Container Registry | 192.168.10.x | 8 GB | 120 GB |
| HP1-seed01 | VM de dev (Ansible, kubectl, outillage) | 192.168.10.x | 4 GB | 60 GB |
| HP1-vault01 | Gestion des secrets (phase 2) | 192.168.10.x | 2 GB | 40 GB |
| HP1-icinga01 | Supervision | 192.168.10.x | 4 GB | 60 GB |
| HP1-k8s-cp01 | Control plane RKE2 | 192.168.10.x | 8 GB | 80 GB |
| HP1-k8s-cp02 | Control plane RKE2 | 192.168.10.x | 8 GB | 80 GB |
100 + <last IP octet> (131–137) — Proxmox exige des ID ≥ 100, et de cette façon l’ID et l’adresse restent faciles à associer d’un coup d’œil, sans table de correspondance séparée.▶️ Le déploiement
Tout le déploiement tient en trois commandes, une fois qu’un jeton d’API Proxmox et une clé SSH sont en place :cp terraform.tfvars.example terraform.tfvars
# edit terraform.tfvars: API URL, API token, node name, SSH key
terraform init
terraform plan
terraform applyQuelques minutes plus tard, les sept VM existent, démarrent et répondent sur leurs IP attribuées — et Terraform vous dit précisément qui est qui :Outputs:
vm_ids = {
"HP1-dc01" = 131
"HP1-gitlab01" = 132
"HP1-icinga01" = 135
"HP1-k8s-cp01" = 136
"HP1-k8s-cp02" = 137
"HP1-seed01" = 133
"HP1-vault01" = 134
}
vm_ips = {
"HP1-dc01" = "192.168.10.x"
"HP1-gitlab01" = "192.168.10.x"
...
}🧩 Quelques points à signaler
- Image cloud, pas ISO. L’ISO Ubuntu présente sur le stockage local de HP1 n’est volontairement pas utilisée par ce module — cloner une image cloud et la configurer via cloud-init est plus rapide et entièrement automatique. L’ISO ne reste là que pour les rares installations manuelles.
ignore_changessur lefile_iddu disque. Sans cela, Terraform veut réimporter l’image de base à chaque plan, car l’ID du fichier téléchargé n’est pas censé être réconcilié après le clonage initial.- Les secrets ne quittent jamais le dépôt interne.
terraform.tfvarscontient le vrai jeton d’API et la clé SSH et figure dans le gitignore ; en plus du gitignore, un hook pre-push l’empêche activement d’atterrir un jour sur le miroir GitHub public de ce projet. - Le state est local, et c’est très bien comme ça. Un seul opérateur, un seul portable qui lance
apply— un backend distant résoudrait un problème que je n’ai pas encore.
⚠️ L’ensemble de ce projet — y compris le code Terraform présenté ci-dessous — est un chantier permanent. Il tourne, il fait ce qu’il annonce, mais il reste en bêta et il est remanié en continu. Ne considérez rien ici comme terminé ou stable.
📊 L’angle mort du ballooning sous Windows
HP1-dc01 est provisionnée par ce module comme n’importe quelle autre VM, mais elle ne reste pas longtemps sous Ubuntu — elle passe sous Windows Server juste après, puisque c’est ce qu’exige Active Directory. À ce moment-là, son graphique de RAM dans le résumé Proxmox s’est figé à 100 % des 4 Go attribués, quelle que soit l’inactivité réelle de la VM. La cause : Proxmox ne mesure pas directement la consommation mémoire de l’invité. Il la récupère via le périphérique balloon virtuel de QEMU, qui ne remonte de vrais chiffres que si un pilote tourne dans l’invité pour l’alimenter. Sur les VM Linux de ce cluster, il est fourni avec qemu-guest-agent — déjà traité plus haut avec le correctif de l’agent invité. Windows Server n’a rien d’équivalent en standard : sans logiciel supplémentaire, le périphérique balloon n’a rien à signaler, et Proxmox affiche simplement la VM bloquée à son allocation maximale. La solution a été un second lecteur CD-ROM virtuel : monter l’ISO de pilotes virtio-win et y installer le pilote VirtIO Balloon via le Gestionnaire de périphériques. C’est le même paquet de pilotes qui contient aussi l’équivalent Windows de l’agent invité — une fois installé, le graphique du résumé s’est mis à suivre la pression mémoire réelle au lieu d’une ligne plate collée au plafond. La transformation de cette VM en véritable contrôleur de domaine, ce sera pour le prochain article.🔜 La suite
Avec un cluster de 3 nœuds qui a son quorum et un moyen reproductible de lancer des VM, le jalon 2 commence à transformerHP1-dc01 en véritable contrôleur de domaine : Active Directory, DNS et la CA racine hors ligne à laquelle tout le reste de ce homelab finira par faire confiance. Ce sera le prochain article. 




