Ateliers — chapitre 3
Infrastructure : nœud
pxe2<N>1— carteens19pour le pont du cluster ; disques/dev/sdc,/dev/sdddisponibles pour ZFS.Adressage : votre poste dispose d'un réseau NATé qui lui est propre. Toutes les ressources que vous créez portent une adresse fixe — aucune ne dépend d'un DHCP de la salle.
État du lab en fin de chapitre :
- Pont du cluster
vmbr1surens19(adresse Corosync10.<site>.<N+10>.11/24) et bridge isolévmbr9 - Pool ZFS miroir
datapool(snapshot/rollback validé) intégré comme stockagezfs-vms - Disque de la VM 140 déplacé à chaud de
local-lvmverszfs-vmssans perte de ping (atelier 4), puis VM supprimée - VLAN et NAT éprouvés sur
vmbr9(atelier 2), puisvmbr9rendu isolé et conteneurs 311-312 supprimés - Serveur NFS dans un conteneur, partage déclaré et sauvegarde écrite (atelier 5) — CT 260 et stockage
nfs-partagesupprimés
Atelier 1 — Réseau Linux et bridges
Contexte
Tout ce qui se connecte au réseau dans Proxmox — VM, conteneur, cluster — passe par un bridge, un commutateur virtuel logiciel. Le nœud en a déjà un, vmbr0, qui le relie au monde. Savoir lire cette configuration et en créer d'autres est le préalable à tout le reste.
Le réseau isolé pour des VMs entre elles. Et surtout le réseau dédié qu'un cluster exige pour Corosync.
Résultat à obtenir : une lecture claire du réseau existant, et un bridge isolé sans interface physique (pour un réseau interne). Puis vmbr1 monté sur la seconde carte physique, prêt à porter le trafic du cluster.
Les cinq cartes de votre nœud, et les trois ponts de l'atelier. vmbr0 existe déjà sur ens18. Vous créez vmbr9, sans carte, puis vmbr1 sur ens19.
Les cartes ens20 à ens22 restent libres. Cliquez sur un pont pour lire son rôle et le résultat obtenu.
Arborescence attendue
/etc/network/interfaces ← la configuration réseau persistante du nœud
├── vmbr0 ← existant : pont principal, relié à la carte physique + Internet
├── vmbr9 ← à créer : pont ISOLÉ, sans interface physique (réseau interne)
└── vmbr1 ← à créer : pont dédié au cluster, sur ens19, adresse 10.<site>.<N+10>.11/24
Ce que vous devez faire
- Explorer l'existant : lister les interfaces et lire la configuration de
vmbr0— quelle carte physique il englobe, quelle adresse il porte. - Créer un bridge isolé, sans interface physique attachée : il servira à faire communiquer des VMs entre elles sans les exposer au réseau.
- Créer
vmbr1sur la carteens19, celle du réseau interne cluster — c'est lui qui portera le réseau Corosync du cluster.
💡 Un bridge sans interface physique = réseau purement interne au nœud. Un bridge avec interface = pont vers le réseau réel. Cette distinction commande toute l'architecture réseau de la formation.
Cliquez pour vous aider
Étape 1 — Explorer le réseau existant
Dans le Shell du nœud (interface web → votre nœud → Shell) :
# Toutes les interfaces, une ligne chacune
ip -br link
ip -br addr show vmbr0 # l'adresse portée par vmbr0
bridge link show # les ports rattachés aux ponts
# La configuration persistante, telle que Proxmox l'a écrite
cat /etc/network/interfaces
Machine d'exemple : nœud pxe211 (Proxmox VE 9.2.21), construit comme le vôtre : cinq cartes ens18 à ens22. C'est le nœud du stagiaire 1 du site 59 : son vmbr0 est en 10.59.1.11 ; le vôtre est en 10.<site>.<N>.11.
Résultat attendu (extraits) :
ens18 UP bc:24:11:01:a1:11 <BROADCAST,MULTICAST,UP,LOWER_UP>
ens19 DOWN bc:24:11:01:b1:11 <BROADCAST,MULTICAST>
ens20 DOWN bc:24:11:01:c1:11 <BROADCAST,MULTICAST>
ens21 DOWN bc:24:11:01:d1:11 <BROADCAST,MULTICAST>
ens22 DOWN bc:24:11:01:e1:11 <BROADCAST,MULTICAST>
vmbr0 UP 10.59.1.11/24 fe80::be24:11ff:fe01:a111/64
2: ens18: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 master vmbr0 state forwarding priority 32 cost 100
auto vmbr0
iface vmbr0 inet static
address 10.59.1.11/24
gateway 10.59.1.1
bridge-ports ens18
bridge-stp off
bridge-fd 0
vmbr0 porte l'adresse du nœud ; bridge link show montre sa carte physique, ens18, avec master vmbr0. Les quatre autres cartes sont DOWN : elles mènent aux réseaux internes du lab, encore inutilisés. bridge link show liste aussi des interfaces veth…, tap…, fwbr… : ce sont les cartes des conteneurs et des VM en marche, branchées sur vmbr0 — chaque invité est un port du commutateur virtuel.
Étape 1 bis — Un filet avant de toucher au réseau
Apply Configuration recharge le réseau du nœud à chaud. Une erreur (la carte de vmbr0 reprise par un autre pont, une passerelle en trop) peut vous couper l'accès.
Votre nœud est distant : sans accès physique, personne ne pourrait le rattraper. Avant de créer quoi que ce soit, gardez une copie de la configuration et programmez son retour automatique.
Dans le Shell du nœud (interface web → votre nœud → Shell) :
# Copie de la configuration réseau actuelle, qui fonctionne
cp /etc/network/interfaces /root/interfaces.avant-tp3
# Dans 10 minutes, la remettre en place et recharger le réseau, sauf si on annule avant
systemd-run --on-active=10min --unit=filet-reseau sh -c "cp /root/interfaces.avant-tp3 /etc/network/interfaces && ifreload -a"
Résultat attendu :
Running timer as unit: filet-reseau.timer
Will run service as unit: filet-reseau.service
Si un Apply vous coupait l'accès, il suffirait d'attendre la fin du délai : la configuration d'origine revient, et les ponts ajoutés disparaissent. Sur le lab, avec un délai d'une minute, le fichier a bien été restauré et le pont de test vmbr9 supprimé (Device "vmbr9" does not exist.).
Étape 2 — Créer un bridge supplémentaire isolé
Nœud → Network → Create → Linux Bridge : Name vmbr9, Autostart ✓, Bridge ports (laisser vide — bridge interne isolé), Comment LAB-ISOLE → Create → Apply Configuration.
Dans le Shell du nœud (interface web → votre nœud → Shell) :
# Le nouveau pont existe-t-il ?
ip -br link show vmbr9
# Combien de ports y sont branchés ?
bridge link show | grep -c 'master vmbr9'
Résultat attendu :
vmbr9 UNKNOWN 8e:1d:76:ca:3e:4e <BROADCAST,MULTICAST,UP,LOWER_UP>
0
Aucune ligne master vmbr9 dans bridge link show. Le pont existe sans interface physique : un réseau isolé entre les VM et conteneurs qu'on y branchera.
Désactiver, puis réactiver le pont. L'interface n'a pas de bouton pour cela : la colonne Active de Network ne fait qu'afficher l'état. On passe par le Shell :
Dans le Shell du nœud :
ifdown vmbr9 # désactiver le pont : il disparaît du système
ip -br link show vmbr9 # vérifier
ifup vmbr9 # le réactiver, d'après /etc/network/interfaces
ip -br link show vmbr9 # vérifier
Résultat attendu (pxe212) :
Device "vmbr9" does not exist.
vmbr9 UNKNOWN 6a:09:e0:40:4f:f9 <BROADCAST,MULTICAST,UP,LOWER_UP>
Désactivé, le pont n'existe plus, et la colonne Active de Network passe à No ; réactivé, il revient. Sa déclaration, elle, reste dans /etc/network/interfaces : c'est Autostart (la ligne auto vmbr9) qui le remonte à chaque démarrage du nœud.
Étape 3 — Créer vmbr1, le pont dédié au cluster
Votre serveur a une seconde carte physique inutilisée. Elle portera le réseau réservé aux échanges du cluster.
Chaque carte de votre nœud mène à un réseau du lab :
| Carte | Réseau interne | Usage |
|---|---|---|
ens18 |
10.<site>.<N>.0/24 (NAT) |
déjà sous vmbr0 : gestion, interface web, Internet |
ens19 |
10.<site>.<N+10>.0/24 |
cluster (Corosync) — cet atelier |
ens20 |
10.<site>.<N+20>.0/24 |
Ceph, réseau du cluster |
ens21 |
10.<site>.<N+30>.0/24 |
Ceph, réseau public |
ens22 |
10.<site>.<N+40>.0/24 |
migration des VM |
Lisez la liste réelle avant de choisir une carte. Sur les nœuds du lab, les cartes s'appellent ens18 à ens22. La carte à prendre est celle qui n'apparaît dans la colonne Ports/Slaves d'aucun pont.
Dans le Shell du nœud (interface web → votre nœud → Shell) :
# Lister les cartes et leur etat. Celle qui porte deja vmbr0 est prise ;
# une carte "DOWN" sans bridge associe est celle que vous cherchez.
ip -br link
# La meme lecture, cote Proxmox, avec la correspondance nom <-> bridge
cat /etc/network/interfaces
Nœud → Network → Create → Linux Bridge :
| Champ | Valeur |
|---|---|
| Name | vmbr1 |
| IPv4/CIDR | l'adresse Corosync de votre nœud : 10.<site>.<N+10>.11/24 |
| Gateway (IPv4) | (laisser vide) |
| Bridge ports | ens19 |
| Autostart | ✓ |
| Comment | COROSYNC |
Les trois nœuds partageront ce réseau, une adresse chacun, avec le même dernier octet que sur vmbr0 :
| Nœud | IP Corosync | Exemple : stagiaire 1 du site 59 (le lab d'exemple) |
|---|---|---|
pxe2<N>1 |
10.<site>.<N+10>.11/24 |
10.59.11.11/24 |
pxe2<N>2 |
10.<site>.<N+10>.12/24 |
10.59.11.12/24 |
pxe2<N>3 |
10.<site>.<N+10>.13/24 |
10.59.11.13/24 |
Le troisième octet vaut votre numéro de stagiaire plus 10 : stagiaire 4 du site 59 → 10.59.14.x. C'est le même calcul pour les trois nœuds — c'est ce qui les met sur le même réseau ; seul le dernier octet change.
Les valeurs du lab : Name vmbr1, IPv4/CIDR 10.59.11.11/24, Bridge ports ens19, Comment COROSYNC, et Gateway laissé vide. Autostart est coché par défaut.
→ Create, puis Apply Configuration.
Les deux ponts sont créés, mais pas encore actifs : colonne Active à No. Le panneau Pending changes montre la différence entre /etc/network/interfaces et /etc/network/interfaces.new, le fichier que Proxmox a préparé. Rien n'est appliqué tant que vous n'avez pas cliqué Apply Configuration (ou redémarré le nœud).
Pas de passerelle sur vmbr1. Ce réseau ne sort pas : il ne reliera que les trois serveurs entre eux. Une seconde passerelle sur la machine casserait le routage par défaut, et vous perdriez l'accès à l'interface.
Dans le Shell du nœud (interface web → votre nœud → Shell) :
# Le pont du cluster, son adresse, puis sa configuration persistante
ip -br addr show vmbr1
grep -A 6 vmbr1 /etc/network/interfaces # les lignes de vmbr1 dans le fichier réseau
bridge link show | grep ens19 # la carte ens19, rattachée à vmbr1
Résultat attendu :
vmbr1 UP 10.59.11.11/24 fe80::be24:11ff:fe01:b111/64
auto vmbr1
iface vmbr1 inet static
address 10.59.11.11/24
bridge-ports ens19
bridge-stp off
bridge-fd 0
#COROSYNC
3: ens19: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 master vmbr1 state forwarding priority 32 cost 100
vmbr1 est UP, avec son adresse, sur ens19 ; bridge link show montre désormais ens19 … master vmbr1. Le pont n'a encore personne à qui parler : votre serveur est seul à ce stade.
Après Apply Configuration, le panneau Pending changes a disparu. vmbr0 (sur ens18) et vmbr1 (sur ens19, 10.59.11.11/24) portent chacun une adresse, et la colonne Active est passée à Yes, pour ens19 aussi ; vmbr9 n'a ni port ni adresse.
Ne confondez pas les deux ponts que vous venez de créer. vmbr9 isole (aucun port physique, aucune adresse) ; vmbr1 relie les serveurs entre eux (seconde carte + adresse Corosync). Vider vmbr1 de son port couperait le cluster.
Tout répond : annulez le filet, sinon il remettra l'ancienne configuration et supprimera vos deux ponts à la fin du délai.
Dans le Shell du nœud :
# Arrêter le minuteur : la restauration programmée n'aura pas lieu
systemctl stop filet-reseau.timer
# Vérifier qu'il n'est plus armé
systemctl is-active filet-reseau.timer
Résultat attendu : inactive.
Atelier 2 — VLAN et NAT sur le pont isolé
Contexte
Le pont vmbr9 de l'atelier 1 isole ses invités. Cet atelier le fait travailler de deux façons, celles du cours §2.
D'abord il segmente : rendu VLAN-aware, il sépare deux conteneurs branchés sur lui selon leur VLAN. Puis il fait sortir : il devient la passerelle d'un réseau privé, que le nœud traduit vers l'extérieur par NAT.
Tout se passe sur vmbr9. Le pont vmbr0, qui porte votre accès au nœud, n'est jamais modifié.
Résultat à obtenir : deux conteneurs qui se voient dans le même VLAN et ne se voient plus dans deux VLAN différents. Puis un conteneur du réseau privé 10.0.0.0/24 qui sort par le NAT du nœud, avec la preuve que c'est bien la règle MASQUERADE qui le permet. Enfin vmbr9 rendu à son état isolé.
Le schéma suit vmbr9 de la copie de sécurité au nettoyage. Cliquez sur chaque bloc pour les commandes et ce qu'elles prouvent.
Arborescence attendue
Nœud pxe2<N>1
└── vmbr9 ← VLAN-aware, puis passerelle 10.0.0.1/24 avec NAT vers vmbr0
├── CT 311 « ct-vlan311 » 10.0.0.11/24 VLAN 10, puis sans VLAN, passerelle 10.0.0.1
└── CT 312 « ct-vlan312 » 10.0.0.12/24 VLAN 10, puis VLAN 20
(les deux conteneurs et la configuration de l'atelier sont retirés à la fin)
Ce que vous devez faire
- Garder une copie de
/etc/network/interfaces, comme à l'atelier 1. - Rendre
vmbr9VLAN-aware. - Créer deux conteneurs sur
vmbr9, dans le VLAN 10, et vérifier qu'ils se joignent. Puis passer le second dans le VLAN 20 et constater qu'ils ne se joignent plus. - Faire de
vmbr9une passerelle NATée : adresse10.0.0.1/24, routage et règleMASQUERADEattachés au pont (cours §2.4). - Sortir par le NAT depuis le premier conteneur, sans VLAN : joindre la passerelle de votre
vmbr0, puis une adresse extérieure. Retirer la règle, refaire le test, la remettre. - Nettoyer : conteneurs supprimés,
vmbr9rendu isolé, règle NAT et routage retirés.
Cliquez pour vous aider
Machine d'exemple : nœud pxe211 (Proxmox VE 9.2.21), avec vmbr9 dans l'état de fin d'atelier 1. Son vmbr0 est en 10.59.1.11, sa passerelle en 10.59.1.1 ; chez vous, 10.<site>.<N>.11 et 10.<site>.<N>.1. Les adresses 10.0.0.x sont internes à vmbr9 : elles sont les mêmes chez vous.
Étape 1 — Une copie de la configuration réseau
Dans le Shell du nœud (interface web → votre nœud → Shell) :
cp /etc/network/interfaces /root/interfaces.avant-atelier2 # l'état de fin d'atelier 1, pour le nettoyage
cat /proc/sys/net/ipv4/ip_forward # le routage du nœud avant l'atelier : notez la valeur
Résultat attendu : 0 : le nœud ne route pas. L'étape 4 l'activera, l'étape 6 remettra la valeur notée.
Étape 2 — Rendre vmbr9 VLAN-aware
Via l'interface : votre nœud → System → Network → vmbr9 → Edit → cocher VLAN aware → OK → Apply Configuration.
En ligne de commande, ce sont les deux lignes du cours §2.1, ajoutées au bloc de vmbr9 dans /etc/network/interfaces (avec nano), puis ifreload -a :
auto vmbr9
iface vmbr9 inet manual
bridge-ports none
bridge-stp off
bridge-fd 0
bridge-vlan-aware yes
bridge-vids 2-4094
#LAB-ISOLE
Dans le Shell du nœud :
ifreload -a # appliquer
bridge vlan show dev vmbr9 # les VLAN que le pont connaît
Résultat attendu :
port vlan-id
vmbr9 1 PVID Egress Untagged
Le pont lui-même est dans le VLAN 1, sans étiquette : c'est son VLAN natif. Les VLAN 2 à 4094 lui sont permis (bridge-vids) ; ils apparaîtront avec les ports qui les utilisent.
Étape 3 — Deux conteneurs, un VLAN, puis deux
Via l'interface : Create CT, deux fois, avec le modèle Debian 13 du chapitre 1 :
| Champ | CT 311 | CT 312 |
|---|---|---|
| CT ID / Hostname | 311 / ct-vlan311 |
312 / ct-vlan312 |
| Disk / Memory | 2 Gio / 256 Mio |
2 Gio / 256 Mio |
| Network → Bridge / VLAN Tag | vmbr9 / 10 |
vmbr9 / 10 |
| Network → IPv4 | Static, 10.0.0.11/24, sans passerelle |
Static, 10.0.0.12/24, sans passerelle |
Dans le Shell du nœud :
# Les deux conteneurs, dans le VLAN 10 de vmbr9 (nesting=1 : requis par le systemd de Debian 13)
pct create 311 local:vztmpl/debian-13-standard_13.6-1_amd64.tar.zst --hostname ct-vlan311 --password dawan \
--rootfs local-lvm:2 --memory 256 --unprivileged 1 --features nesting=1 \
--net0 name=eth0,bridge=vmbr9,ip=10.0.0.11/24,tag=10
# le second, même VLAN
pct create 312 local:vztmpl/debian-13-standard_13.6-1_amd64.tar.zst --hostname ct-vlan312 --password dawan \
--rootfs local-lvm:2 --memory 256 --unprivileged 1 --features nesting=1 \
--net0 name=eth0,bridge=vmbr9,ip=10.0.0.12/24,tag=10
pct start 311 # démarrer le premier
pct start 312 # puis le second
pct exec 311 -- ping -c 2 -W 2 10.0.0.12 # même VLAN
bridge vlan show | grep -A1 veth # le VLAN de chaque port
Résultat attendu :
2 packets transmitted, 2 received, 0% packet loss, time 1003ms
veth200i0 1 PVID Egress Untagged
fwbr200i0 1 PVID Egress Untagged
--
veth311i0 10 PVID Egress Untagged
veth312i0 10 PVID Egress Untagged
Failed to create the network au démarrage : vmbr9 n'est pas VLAN-aware. Sur le lab, avec un conteneur étiqueté tag=10 sur un vmbr9 resté sans l'option :
run_buffer: 569 Script exited with status 255
lxc_create_network_priv: 3731 Success - Failed to create network device
lxc_spawn: 2032 Failed to create the network
startup for container '311' failed
L'étape 2 n'a pas pris effet : case VLAN aware cochée sans Apply Configuration, ou fichier modifié sans ifreload -a. Vérifiez avec grep -A7 "iface vmbr9" /etc/network/interfaces : les lignes bridge-vlan-aware yes et bridge-vids 2-4094 doivent y être.
Les lignes présentes ne suffisent pas : cat /sys/class/net/vmbr9/bridge/vlan_filtering dit si le pont en marche les applique (sur le lab : 0 tant que ifreload -a n'a pas été lancé, 1 après). Appliquez, puis relancez pct start 311; pct start 312 : sur le lab, le conteneur a alors démarré.
Si le message est bridge 'vmbr9' does not exist, c'est le pont lui-même qui manque : ifup vmbr9 (atelier 1, étape 2).
Dans le résultat, les deux premières lignes sont le CT 200 du chapitre 1, branché sur vmbr0 : ses ports sont dans le VLAN 1, celui par défaut. Si votre nœud porte d'autres conteneurs, leurs ports apparaissent de la même façon.
Chaque conteneur de l'atelier est un port du pont, dans le VLAN 10 : ils se joignent. Egress Untagged : le pont retire l'étiquette avant de livrer la trame, le conteneur ne la voit jamais (cours §2.2).
Sans nesting=1, pct create avertit : WARN: Systemd 257 detected. You may need to enable nesting. L'assistant de l'interface coche Nesting d'office.
Passez maintenant le CT 312 dans le VLAN 20 : CT 312 → Network → net0 → Edit → VLAN Tag 20 → OK. En ligne de commande, recopiez l'adresse MAC (pct config 312 | grep net0) : sans hwaddr=, pct set en tire une nouvelle.
Dans le Shell du nœud :
pct set 312 --net0 name=eth0,bridge=vmbr9,hwaddr=<MAC-du-312>,ip=10.0.0.12/24,tag=20 # le 312 dans le VLAN 20
pct exec 311 -- ping -c 2 -W 2 10.0.0.12 # VLAN 10 vers VLAN 20
bridge vlan show | grep -A1 veth # le VLAN de chaque port
Résultat attendu :
2 packets transmitted, 0 received, 100% packet loss, time 1003ms
veth311i0 10 PVID Egress Untagged
veth312i0 20 PVID Egress Untagged
Même pont, même sous-réseau, même nœud : seul le VLAN diffère, et plus rien ne passe. C'est la segmentation du cours §2.1, sans un câble de plus.
Étape 4 — vmbr9 devient une passerelle NATée
Via l'interface : vmbr9 → Edit → IPv4/CIDR 10.0.0.1/24 (sans passerelle) → OK. Les règles de NAT, elles, n'ont pas de champ dans l'interface : elles s'ajoutent au fichier.
Dans le Shell du nœud, avec nano /etc/network/interfaces, le bloc de vmbr9 devient celui du cours §2.4 :
auto vmbr9
iface vmbr9 inet static
address 10.0.0.1/24
bridge-ports none
bridge-stp off
bridge-fd 0
bridge-vlan-aware yes
bridge-vids 2-4094
post-up echo 1 > /proc/sys/net/ipv4/ip_forward
post-up iptables -t nat -A POSTROUTING -s 10.0.0.0/24 -o vmbr0 -j MASQUERADE
post-down iptables -t nat -D POSTROUTING -s 10.0.0.0/24 -o vmbr0 -j MASQUERADE
#LAB-ISOLE
Dans le Shell du nœud :
ifreload -a # appliquer
ip -br addr show vmbr9 # l'adresse du pont
iptables -t nat -S POSTROUTING # la règle posée par post-up
cat /proc/sys/net/ipv4/ip_forward # le routage activé
Résultat attendu :
vmbr9 UP 10.0.0.1/24 fe80::6c52:eff:feb3:deb3/64
-P POSTROUTING ACCEPT
-A POSTROUTING -s 10.0.0.0/24 -o vmbr0 -j MASQUERADE
1
Étape 5 — Sortir par le NAT
Le CT 311 sort du VLAN 10 et prend la passerelle : CT 311 → Network → net0 → Edit → VLAN Tag vide, Gateway (IPv4) 10.0.0.1 → OK. L'adresse du pont est portée par son VLAN natif, le VLAN 1 sans étiquette (étape 2). On retire donc l'étiquette du CT 311 pour le mettre sur le même segment que sa passerelle.
Dans le Shell du nœud :
pct set 311 --net0 name=eth0,bridge=vmbr9,hwaddr=<MAC-du-311>,ip=10.0.0.11/24,gw=10.0.0.1 # ou par l'interface
pct exec 311 -- ping -c 2 -W 2 10.0.0.1 # la passerelle : le pont
pct exec 311 -- ping -c 2 -W 2 10.<site>.<N>.1 # la passerelle de votre vmbr0, de l'autre côté du NAT
pct exec 311 -- ping -c 2 -W 2 1.1.1.1 # une adresse extérieure
iptables -t nat -L POSTROUTING -v -n | grep MASQUERADE # le compteur de la règle
Résultat attendu : 0% packet loss pour les trois, puis :
2 168 MASQUERADE all -- * vmbr0 10.0.0.0/24 0.0.0.0/0
Le compteur a compté 2 paquets : un par connexion traduite, les deux pings vers l'extérieur. Le premier paquet d'une connexion passe par la règle ; les suivants suivent la traduction déjà établie.
La contre-épreuve : la règle retirée, puis remise.
Dans le Shell du nœud :
iptables -t nat -D POSTROUTING -s 10.0.0.0/24 -o vmbr0 -j MASQUERADE # retirer la règle
pct exec 311 -- ping -c 2 -W 2 1.1.1.1 # sans la règle
iptables -t nat -A POSTROUTING -s 10.0.0.0/24 -o vmbr0 -j MASQUERADE # la remettre
pct exec 311 -- ping -c 2 -W 2 1.1.1.1 # avec la règle
Résultat attendu : 2 packets transmitted, 0 received, 100% packet loss, puis 0% packet loss : c'est bien la traduction d'adresse qui fait sortir le réseau privé.
Si 1.1.1.1 ne répond pas même avec la règle, le réseau autour de votre nœud ne route peut-être pas vers Internet (cours §2.4). La passerelle de votre vmbr0 et le compteur de la règle suffisent alors à prouver le NAT.
Étape 6 — Nettoyer
Dans le Shell du nœud :
pct stop 311 # arrêter le premier conteneur
pct destroy 311 --purge # le supprimer
pct stop 312 # puis le second
pct destroy 312 --purge # le supprimer
cp /root/interfaces.avant-atelier2 /etc/network/interfaces # vmbr9 tel qu'à la fin de l'atelier 1
ifreload -a # appliquer
iptables -t nat -S POSTROUTING # la règle est-elle partie ?
cat /proc/sys/net/ipv4/ip_forward # et le routage ?
Résultat attendu :
-P POSTROUTING ACCEPT
-A POSTROUTING -s 10.0.0.0/24 -o vmbr0 -j MASQUERADE
1
ifreload -a n'exécute pas les post-down d'une configuration qu'on a retirée. La règle MASQUERADE et le routage restent actifs après le retour au fichier d'origine, vu ci-dessus. Retirez-les à la main.
Dans le Shell du nœud :
iptables -t nat -D POSTROUTING -s 10.0.0.0/24 -o vmbr0 -j MASQUERADE # retirer la règle
echo 0 > /proc/sys/net/ipv4/ip_forward # la valeur notée à l'étape 1 (0 sur le lab)
iptables -t nat -S POSTROUTING # → -P POSTROUTING ACCEPT, seul
ip -br link show vmbr9 répond alors DOWN et NO-CARRIER : un pont sans port ni invité n'a pas de lien. Il redevient UP dès qu'un invité s'y branche.
Atelier 3 — Pool ZFS en miroir
Contexte
ZFS est bien plus qu'un système de fichiers : il réunit la gestion des volumes, le RAID logiciel, la compression transparente et les snapshots instantanés en une seule couche. Sur ce nœud, deux disques lui sont réservés (sdc et sdd) pour un miroir — l'équivalent d'un RAID1, où chaque donnée existe en double.
Vous allez le construire de bout en bout : le pool en miroir, un dataset compressé, un snapshot avec retour arrière, puis son intégration comme stockage Proxmox.
Résultat à obtenir : un pool ZFS en miroir sur sdc/sdd. Deux datasets compressés selon leur usage, et la mesure de ce que chacun fait gagner. Un snapshot restauré avec succès, et le stockage visible et utilisable dans Proxmox.
Deux façons de rendre un pool redondant. Le miroir écrit la même donnée sur deux disques (comme RAID 1) : c'est ce que vous construisez ici, avec sdc et sdd.
RAIDZ1 répartit les données et une parité sur trois disques ou plus (comme RAID 5) et tolère la perte d'un disque. En production pour la virtualisation, le miroir est préféré pour ses performances en accès aléatoire. Cliquez sur un pool pour son détail.
Arborescence attendue
Pool ZFS « datapool » (miroir sdc + sdd)
├── dataset « datapool/vms » ← compression lz4 (disques de VM : la vitesse)
│ └── snapshot @avant-modif ← créé puis rollback
└── dataset « datapool/sauvegardes » ← compression zstd (archives : la place), comparé puis supprimé
Intégré dans Proxmox → stockage de type « ZFS »
Ce que vous devez faire
- Identifier les disques disponibles et confirmer que
sdcetsddsont bien libres — surtout passdb, réservé à Ceph, nisda, le système. - Créer le pool en miroir sur les deux disques, puis un dataset avec la compression activée.
-
Un cran plus loin : un réglage par usage. Créez un second dataset,
datapool/sauvegardes, compressé enzstd. Écrivez les mêmes données texte dans les deux datasets et comparez ce qu'elles occupent réellement.Supprimez ensuite ce second dataset.
-
Éprouver les snapshots : prendre un snapshot du dataset, modifier des données, puis revenir en arrière et constater la restauration.
- Intégrer le pool dans Proxmox comme stockage, et vérifier qu'il accepte bien des disques de VM.
⚠️ Attention au disque : monter ZFS sur
sdbrendrait Ceph impossible (Ceph refuse un disque portant une signature ZFS). Respectez le plan des disques.
Cliquez pour vous aider
Étape 1 — Identifier les disques disponibles
Dans le Shell du nœud (interface web → votre nœud → Shell) :
# Les disques entiers (-d), puis le contenu des deux disques visés
lsblk -d -o NAME,SIZE,TYPE,MODEL
fdisk -l /dev/sdc # le disque sdc
fdisk -l /dev/sdd # le disque sdd
Résultat attendu (nœud pxe211, construit comme le vôtre) :
NAME SIZE TYPE MODEL
sda 150G disk QEMU HARDDISK
sdb 70G disk QEMU HARDDISK
sdc 50G disk QEMU HARDDISK
sdd 50G disk QEMU HARDDISK
Disk /dev/sdc: 50 GiB, 53687091200 bytes, 104857600 sectors
Disk model: QEMU HARDDISK
...
Quatre disques : sda (système), sdb (70 Go, Ceph) et sdc, sdd de même taille (50 Go). Pour ces deux derniers, fdisk -l n'affiche aucune ligne de partition — seulement la taille et le modèle.
Attention : vérifiez bien que sdc et sdd sont des disques vides, sans données. La création du pool est irréversible.
Étape 2 — Créer un pool ZFS miroir
La fenêtre remplie sur le lab. Seuls les deux disques de taille identique sont cochés — sdc et sdd, 53.69 GB chacun sur ce nœud (50 Gio exprimés en gigaoctets décimaux).
La taille varie d'un nœud à l'autre : seule compte l'égalité des deux disques. Dans un miroir, la capacité du pool est celle du plus petit disque, et sdb reste réservé aux OSD Ceph.
RAID Level est passé de Single Disk à Mirror, Add Storage est décoché. Les valeurs par défaut Compression on et ashift 12 conviennent.
Via l'interface : pxe2<N>1 → Disks → ZFS → Create: ZFS — Name datapool, RAID Level Mirror, Add Storage décoché (on l'ajoute manuellement à l'étape 5), Disk 1 /dev/sdc, Disk 2 /dev/sdd → Create.
Équivalent CLI :
Dans le Shell du nœud (interface web → votre nœud → Shell) :
# Pool en miroir ; -f passe outre un avertissement de signature résiduelle (à n'utiliser
# qu'après avoir vérifié à l'étape 1 que les disques sont bien vides)
zpool create -f -o ashift=12 datapool mirror /dev/sdc /dev/sdd
zpool status # état du pool et de ses disques
zpool list # taille et remplissage du pool
Résultat attendu :
pool: datapool
state: ONLINE
config:
NAME STATE READ WRITE CKSUM
datapool ONLINE 0 0 0
mirror-0 ONLINE 0 0 0
sdc ONLINE 0 0 0
sdd ONLINE 0 0 0
errors: No known data errors
zpool list affiche une taille d'environ 49,5 Go : celle d'un disque, puisque le miroir écrit tout en double.
Résultat attendu, pool créé par l'interface :
NAME STATE READ WRITE CKSUM
datapool ONLINE 0 0 0
mirror-0 ONLINE 0 0 0
scsi-0QEMU_QEMU_HARDDISK_drive-scsi2 ONLINE 0 0 0
scsi-0QEMU_QEMU_HARDDISK_drive-scsi3 ONLINE 0 0 0
NAME SIZE ALLOC FREE CKPOINT EXPANDSZ FRAG CAP DEDUP HEALTH ALTROOT
datapool 49.5G 624K 49.5G - - 0% 0% 1.00x ONLINE -
Remarquez les noms des disques. L'interface ne les désigne pas par sdc et sdd, mais par leur identifiant stable (/dev/disk/by-id/…). Un nom comme sdc peut changer au redémarrage suivant, si l'ordre de détection des disques change ; l'identifiant, jamais.
C'est la bonne pratique en production. En ligne de commande, zpool create … mirror /dev/sdc /dev/sdd garde les noms courts du tableau précédent.
datapool apparaît sous Disks → ZFS, Health ONLINE. La taille affichée, 53.15 GB, est la même capacité que les 49,5 Gio de zpool list, exprimée en gigaoctets décimaux.
Étape 3 — Créer un dataset et activer la compression
Dans le Shell du nœud (interface web → votre nœud → Shell) :
# Un dataset dédié aux VM, compressé en lz4
zfs create datapool/vms
zfs set compression=lz4 datapool/vms # compression lz4 sur ce dataset
zfs get compression,used,available datapool/vms # compression, espace occupé et disponible
Résultat attendu :
NAME PROPERTY VALUE SOURCE
datapool/vms compression lz4 local
datapool/vms used 96K -
datapool/vms available 48.0G -
SOURCE local signifie que la propriété est posée sur ce dataset ; un dataset enfant afficherait inherited from datapool/vms. C'est ainsi qu'on repère d'où vient un réglage.
Étape 3 bis — Un réglage par usage
Tous les datasets n'ont pas le même besoin. Les disques de VM demandent de la vitesse : lz4 compresse peu mais presque sans coût.
Des archives de sauvegarde demandent de la place : zstd compresse davantage, au prix d'un peu plus de calcul. Sur ZFS, ce choix se fait dataset par dataset.
Dans le Shell du nœud (interface web → votre nœud → Shell) :
# Un second dataset, compressé en zstd dès sa création
zfs create -o compression=zstd datapool/sauvegardes
# Les mêmes données texte (les modules Perl de Proxmox), écrites séparément dans chaque dataset
tar -cf /datapool/vms/perl.tar -C /usr/share perl5 # dans le premier dataset
tar -cf /datapool/sauvegardes/perl.tar -C /usr/share perl5 # puis dans le second
sync # forcer l'écriture sur disque avant de mesurer
# Taux de compression, place réellement occupée, taille avant compression
zfs get -o name,property,value compressratio,used,logicalused datapool/vms datapool/sauvegardes
Résultat attendu :
NAME PROPERTY VALUE
datapool/sauvegardes compressratio 3.81x
datapool/sauvegardes used 3.25M
datapool/sauvegardes logicalused 12.2M
datapool/vms compressratio 2.56x
datapool/vms used 4.82M
datapool/vms logicalused 12.2M
Les mêmes 12,2 Mo (logicalused) occupent 4,82 Mo en lz4 et 3,25 Mo en zstd : un tiers de place en moins pour les sauvegardes. Deux pièges vus sur le lab :
- Écrivez les données dans chaque dataset. Un
cpd'un dataset à l'autre du même pool ne réécrit pas les blocs : OpenZFS les clone (zpool get feature@block_cloning datapoolrépondenabled), et la copie garde la compression d'origine. Les deux taux affichaient alors2.56x. - Des données déjà compressées ne gagnent rien. Avec une archive de
/usr/share/doc, faite surtout de fichiers.gz, les deux datasets plafonnaient au même taux (1.54x), quel que soit l'algorithme.
Supprimez les deux archives de test, puis le dataset sauvegardes, qui ne sert plus.
Dans le Shell du nœud :
rm /datapool/vms/perl.tar /datapool/sauvegardes/perl.tar # les deux archives de test
zfs destroy datapool/sauvegardes # le dataset
Les ateliers suivants partent d'un pool qui ne contient que datapool/vms.
Étape 4 — Snapshots ZFS
Dans le Shell du nœud (interface web → votre nœud → Shell) :
# Un fichier témoin dans le dataset (monté d'office sur /datapool/vms)
mkdir -p /datapool/vms/test
nano /datapool/vms/test/fichier.txt # un fichier de test : la ligne « données importantes »
zfs snapshot datapool/vms@avant-modif # snapshot du dataset
zfs list -t snapshot # vérifier qu'il existe
# Simuler une erreur
rm /datapool/vms/test/fichier.txt
# Revenir au snapshot
zfs rollback datapool/vms@avant-modif
cat /datapool/vms/test/fichier.txt # le contenu actuel du fichier
Résultat attendu :
NAME USED AVAIL REFER MOUNTPOINT
datapool/vms@avant-modif 0B - 104K -
données importantes
Le snapshot n'occupe rien (USED 0B) tant que rien n'a changé ; après le rollback, cat affiche de nouveau données importantes — le fichier supprimé est revenu, sans aucune copie préalable.
Étape 5 — Intégrer ZFS dans Proxmox
Via l'interface : Datacenter → Storage → Add → ZFS — ID zfs-vms, ZFS Pool datapool/vms, Content Disk image, Container, Nodes (laisser vide = tous les nœuds) → Add.
Équivalent CLI :
Dans le Shell du nœud (interface web → votre nœud → Shell) :
# Déclarer le dataset comme stockage : disques de VM et racines de conteneurs
pvesm add zfspool zfs-vms \
--pool datapool/vms \
--content images,rootdir
pvesm status # le stockage zfs-vms doit apparaître
Résultat attendu : zfs-vms zfspool active 50298460 104 50298356 0.00%. Dans Datacenter → Storage, le stockage zfs-vms apparaît avec le type ZFS.
zfspool en ligne de commande, ZFS dans l'interface : c'est le même type. zfspool est son identifiant technique, celui de pvesm et de /etc/pve/storage.cfg ; ZFS est son libellé dans l'interface.
Attention au piège inverse : l'identifiant zfs, en ligne de commande, désigne un autre type, ZFS over iSCSI. Cela se lit dans le code de l'interface de Proxmox VE 9.2.21 : zfspool → ZFS, zfs → ZFS over iSCSI.
Validation finale
Dans le Shell du nœud (interface web → votre nœud → Shell) :
# Le pool, la compression, le stockage Proxmox
zpool list -H -o health datapool # l'état du pool
zfs get compression datapool/vms # la compression du dataset
pvesm status | grep zfs-vms # le stockage zfs-vms est-il actif ?
Résultat attendu : ONLINE, datapool/vms compression lz4 local, et la ligne zfs-vms zfspool active.
Atelier 4 — Déplacer à chaud un disque de VM de LVM-thin vers ZFS
Contexte
Votre nœud a maintenant deux stockages de disques : local-lvm (LVM-thin) et zfs-vms (le miroir de l'atelier 3). Une VM installée sur le premier peut passer sur le second sans être arrêtée.
Proxmox recopie le disque pendant que la VM tourne, puis bascule sur la copie (cours, §4.5). C'est le geste qui permet de profiter du miroir ZFS sans réinstaller une machine.
Résultat à obtenir : une VM 140 vm-disque, clonée sur local-lvm, dont le disque passe sur zfs-vms sans perte de ping ; l'ancien volume LVM supprimé ; puis la VM supprimée.
Le schéma suit le disque de la VM 140 de local-lvm vers zfs-vms. Cliquez sur chaque bloc pour son détail.
Arborescence attendue
Nœud pxe2<N>1
├── Avant : VM 140 « vm-disque » (10.<site>.<N>.66), running ← étapes 1 et 2
│ └── scsi0 : local-lvm:vm-140-disk-0 → volume LVM pve/vm-140-disk-0
└── Après : la même VM, toujours running ← étapes 3 et 4
└── scsi0 : zfs-vms:vm-140-disk-0 → zvol datapool/vms/vm-140-disk-0
Ce que vous devez faire
- Cloner le template 100 du chapitre 2 en VM 140
vm-disque, clone complet surlocal-lvm, adresse.66, et la démarrer. - Relever l'état initial : où est le disque, et quel volume LVM le porte.
- Déplacer le disque vers
zfs-vms, VM démarrée, en supprimant la source, pendant qu'un ping tourne. - Constater : où est le disque maintenant, et combien de pings ont été perdus.
- Supprimer la VM 140.
Cliquez pour vous aider
Machine d'exemple : nœud pxe211 (Proxmox VE 9.2.21, lab 10.59.1.x), avec le template de 20 Go de l'atelier 7 du chapitre 2. La VM 140 y avait l'adresse 10.59.1.66 ; chez vous, 10.<site>.<N>.66. Les captures, plus anciennes, montrent un disque de 3 Go.
Étape 1 — La VM de l'atelier
Dans le Shell du nœud (interface web → votre nœud → Shell) :
qm clone 100 140 --name vm-disque --full --storage local-lvm # clone intégral de la VM 100
qm set 140 --ipconfig0 ip=10.<site>.<N>.66/24,gw=10.<site>.<N>.1 # son adresse fixe
qm start 140 # la démarrer
Attendez une trentaine de secondes, le temps que la VM démarre.
Étape 2 — L'état initial
Dans le Shell du nœud :
ping -c2 10.<site>.<N>.66 # la VM répond
qm config 140 | grep scsi0 # son disque, sur local-lvm
lvs pve | grep vm-140 # le volume LVM correspondant
Résultat attendu :
2 packets transmitted, 2 received, 0% packet loss, time 1014ms
scsi0: local-lvm:vm-140-disk-0,discard=on,iothread=1,size=20G
vm-140-cloudinit pve Vwi-aotz-- 4.00m data 9.38
vm-140-disk-0 pve Vwi-aotz-- 20.00g data 6.17
Le disque de 20 Go est un volume du pool LVM-thin data, rempli à 6 % : à peine plus d'1 Go réellement écrit.
Étape 3 — Déplacer le disque, VM démarrée
Via l'interface : VM 140 → Hardware → sélectionner Hard Disk (scsi0) → Disk Action → Move Storage.
| Champ | Valeur |
|---|---|
| Target Storage | zfs-vms |
| Format | grisé : un stockage ZFS n'accepte que le format raw |
| Delete source | coché |
La fenêtre Move disk telle qu'elle s'ouvre. Target Storage est encadré en rouge tant qu'aucune cible n'est choisie. Format est grisé : c'est le stockage cible qui impose le format.
Delete source décide du sort de l'ancien volume. Non coché, il reste en unused0 dans la configuration de la VM et continue d'occuper local-lvm. (Capture prise après le déplacement, d'où zfs-vms déjà affiché sur la ligne du disque.)
Ou en ligne de commande. Dans le Shell du nœud, avec un ping qui tourne pendant le déplacement :
ping -i 0.2 10.<site>.<N>.66 > /tmp/ping140.txt 2>&1 & # ping toutes les 0,2 s, en arrière-plan
qm disk move 140 scsi0 zfs-vms --delete 1 # déplacer le disque vers ZFS, VM allumée
kill %1 # arrêter le ping
tail -2 /tmp/ping140.txt # lire le bilan
Résultat attendu (lignes de progression abrégées) :
create full clone of drive scsi0 (local-lvm:vm-140-disk-0)
allocated target volume 'zfs-vms:vm-140-disk-0'
drive mirror is starting for drive-scsi0
mirror-scsi0: transferred 20.0 GiB of 20.0 GiB (100.00%) in 8s, ready
all 'mirror' jobs are ready
mirror-scsi0: Completing block job...
mirror-scsi0: Completed successfully.
mirror-scsi0: mirror-job finished
removing source volume 'local-lvm:vm-140-disk-0' after successful copy
Logical volume "vm-140-disk-0" successfully removed.
Lisez les lignes dans l'ordre. Proxmox crée le volume cible, puis lance un miroir (drive mirror) : QEMU copie le disque et répercute sur la copie chaque écriture de la VM. Quand les deux sont identiques (ready), il bascule la VM sur la copie (Completing block job).
Enfin il supprime la source. L'opération a duré 12 secondes sur le lab ; le ping, une réponse toutes les 0,2 s, n'en a manqué aucune (57 reçues sur 57).
Étape 4 — Constater
Dans le Shell du nœud :
qm config 140 # le disque est maintenant sur zfs-vms ; à lire : scsi0, unused
zfs list -o name,used,refer,volsize -r datapool/vms # le volume ZFS de la VM
lvs pve | grep vm-140 # plus de volume LVM
Résultat attendu (les lignes qui comptent) :
scsi0: zfs-vms:vm-140-disk-0,discard=on,iothread=1,size=20G
NAME USED REFER VOLSIZE
datapool/vms 20.3G 96K -
datapool/vms/vm-140-disk-0 20.3G 787M 20G
L'onglet Hardware après le déplacement. Hard Disk (scsi0) pointe sur zfs-vms:vm-140-disk-0.
Le CloudInit Drive (ide2) est resté sur local-lvm : seul le disque choisi a bougé. En bas, la tâche VM 140 - Move disk est OK.
Deux constats. Le disque est devenu un zvol ZFS de 20 Go, dont 787 Mo réellement écrits (REFER). Pourtant USED vaut 20,3G : sur un stockage zfs-vms qui n'est pas en Thin provision, Proxmox réserve d'avance toute la taille du disque.
Il n'y a plus de ligne unused0 ni de volume vm-140-disk-0 dans LVM : la source est supprimée. Et aucun ping n'a été perdu : la VM n'a pas été interrompue.
Un disque sur zfs-vms est local au nœud. Dans un cluster, une VM dont le disque est sur ce stockage ne peut pas être migrée vers un nœud qui n'a pas de pool datapool. C'est pourquoi l'atelier se fait sur une VM dédiée, supprimée à la fin : vos VM 101 et 102 restent sur local-lvm.
Validation finale
| Contrôle | Attendu |
|---|---|
qm config 140 | grep scsi0 |
zfs-vms:vm-140-disk-0 |
| Pings perdus pendant le déplacement | 0% packet loss |
lvs pve | grep vm-140-disk-0 |
rien |
Nettoyage :
Dans le Shell du nœud :
qm stop 140 # arrêter la VM 140
qm destroy 140 --purge # puis la supprimer
zfs list -r datapool/vms # vérifier que son volume a disparu
Résultat attendu : plus de vm-140-disk-0 sous datapool/vms.
Atelier 5 — Un serveur NFS dans un conteneur
Cours : §5.1 (ajouter un partage NFS à Proxmox).
Contexte
Au §5.1, le partage NFS est fourni par l'infrastructure : on ne fait que le déclarer. Ici, vous montez vous-même le serveur, dans un conteneur, pour voir l'autre côté : ce qu'il exporte, à qui, et avec quels droits.
Le serveur NFS du noyau Linux (nfsd) tourne dans le noyau, que le conteneur partage avec l'hôte. Un conteneur non privilégié n'a pas le droit de le piloter : ce conteneur-ci sera privilégié, un choix à justifier et à documenter (chapitre 1, conteneurs privilégiés).
Résultat à obtenir : un conteneur ct-nfs qui exporte /srv/partage vers votre réseau. Le partage monté depuis le nœud, où root est ramené à nobody (root_squash), et où un UID étranger passe tel quel.
Puis ce partage déclaré comme stockage de sauvegardes, et une sauvegarde écrite dessus. Tout est supprimé à la fin.
Le schéma suit le partage du serveur jusqu'au stockage de sauvegardes. Cliquez sur chaque bloc pour son détail.
Arborescence attendue
CT 260 « ct-nfs » — privilégié, nesting, 10.<site>.<N>.81
└── /srv/partage ← exporté vers 10.<site>.<N>.0/24, root_squash
├── test.txt ← créé dans le conteneur
├── depuis-root ← écrit par root du nœud : propriétaire 65534 (nobody)
├── equipe/rapport.txt ← écrit par l'UID 2000 du nœud : propriétaire 2000
└── dump/ ← sauvegarde du CT 200, via le stockage nfs-partage
Ce que vous devez faire
- Créer le conteneur 260
ct-nfs, privilégié, avecnesting, à l'adresse.81, depuis le modèle Debian 13. Y installernfs-kernel-server. - Exporter
/srv/partagevers votre réseau, avecroot_squash. - Monter le partage sur le nœud et y écrire en
root: expliquer le refus, le corriger. - Écrire avec l'UID 2000 depuis le nœud : quel propriétaire voit le serveur ?
- Déclarer le partage comme stockage
nfs-partage(contenu : sauvegardes), et y sauvegarder le CT 200. - Nettoyer dans le bon ordre : le stockage d'abord, le conteneur ensuite.
Cliquez pour vous aider
Machine d'exemple : nœud pxe211 (Proxmox VE 9.2.21). Le conteneur 260 y a l'adresse 10.59.1.81 et exporte vers 10.59.1.0/24 ; chez vous, 10.<site>.<N>.81 et 10.<site>.<N>.0/24. Les heures affichées par le conteneur sont en UTC (Coordinated Universal Time, temps universel), celles du nœud en heure de Paris.
Étape 1 — Le conteneur et le serveur
Via l'interface : Create CT — General : CT ID 260, Hostname ct-nfs, Unprivileged container décoché, Nesting coché, mot de passe. Template : debian-13-standard ; Disks : local-lvm, 4 Go ; CPU 1 ; Memory 512. Network : vmbr0, IPv4 10.<site>.<N>.81/24, passerelle 10.<site>.<N>.1 → Finish, puis Start.
Équivalent CLI, dans le Shell du nœud :
# Conteneur privilégié (--unprivileged 0), nesting activé
pct create 260 local:vztmpl/debian-13-standard_13.6-1_amd64.tar.zst --hostname ct-nfs \
--unprivileged 0 --features nesting=1 --cores 1 --memory 512 --swap 512 --rootfs local-lvm:4 \
--net0 name=eth0,bridge=vmbr0,ip=10.<site>.<N>.81/24,gw=10.<site>.<N>.1 --password proxmoxx
pct start 260 # le démarrer
Dans la console du conteneur 260 (CT 260 → Console, compte root) :
apt update # la liste des paquets
apt install -y nfs-kernel-server # le serveur NFS du noyau
systemctl is-active nfs-server # le service doit être actif
Résultat attendu :
● nfs-server.service - NFS server and services
Loaded: loaded (/usr/lib/systemd/system/nfs-server.service; enabled; preset: enabled)
Active: active (exited) since Tue 2026-10-06 18:28:55 UTC; 868ms ago
Sur Proxmox VE 9, le conteneur privilégié avec nesting suffit : aucun réglage AppArmor supplémentaire n'a été nécessaire.
Étape 2 — Exporter le répertoire
Dans la console du conteneur 260 :
Dans la console du conteneur 260 :
mkdir -p /srv/partage # le répertoire à partager
nano /srv/partage/test.txt # un fichier de test : la ligne « Fichier de test NFS »
nano /etc/exports # le partage
La ligne à écrire dans /etc/exports : le partage, pour tout votre réseau, en lecture-écriture, root ramené à nobody.
/srv/partage 10.<site>.<N>.0/24(rw,sync,no_subtree_check,root_squash)
Dans la console du conteneur 260 :
exportfs -ra # relire /etc/exports
exportfs -v # ce qui est réellement exporté, options comprises
ls -ld /srv/partage # propriétaire et droits du répertoire
Résultat attendu :
/srv/partage 10.59.1.0/24(sync,wdelay,hide,no_subtree_check,sec=sys,rw,secure,root_squash,no_all_squash)
drwxr-xr-x 2 root root 4096 Oct 6 18:29 /srv/partage
| Option | Effet |
|---|---|
rw |
lecture et écriture (ro : lecture seule) |
sync |
le serveur ne confirme une écriture qu'une fois sur disque |
no_subtree_check |
pas de vérification coûteuse de l'arborescence, recommandé pour un répertoire entier |
root_squash |
le root du client devient nobody sur le serveur : la protection par défaut |
Étape 3 — Le nœud comme client
Dans le Shell du nœud :
showmount -e 10.<site>.<N>.81 # ce que le serveur propose
mkdir -p /mnt/essai-nfs # le point de montage
mount -t nfs4 10.<site>.<N>.81:/srv/partage /mnt/essai-nfs # monter le partage
cat /mnt/essai-nfs/test.txt # lire le fichier de test
touch /mnt/essai-nfs/depuis-root # écrire en root
Résultat attendu :
Export list for 10.59.1.81:
/srv/partage 10.59.1.0/24
Fichier de test NFS
touch: cannot touch '/mnt/essai-nfs/depuis-root': Permission denied
Vous êtes root sur le nœud, et pourtant refusé. root_squash vous a ramené à nobody, et /srv/partage appartient à root, en 755 : nobody n'y écrit pas.
Dans la console du conteneur 260 :
chown nobody:nogroup /srv/partage # le répertoire à nobody
chmod 775 /srv/partage # écriture pour nobody, traversée pour les autres
Dans le Shell du nœud :
touch /mnt/essai-nfs/depuis-root # écrire en root, de nouveau
ls -ln /mnt/essai-nfs # -n : les numéros d'UID, pas les noms
Résultat attendu :
-rw-r--r-- 1 65534 65534 0 Oct 6 20:29 depuis-root
-rw-r--r-- 1 0 0 20 Oct 6 20:29 test.txt
Le fichier écrit par root appartient à 65534, l'UID de nobody : c'est root_squash au travail.
Étape 4 — Un UID étranger
Dans la console du conteneur 260 :
mkdir /srv/partage/equipe # un sous-répertoire
chown 2000:2000 /srv/partage/equipe # un répertoire à l'UID 2000, qui n'existe pas ici
Dans le Shell du nœud :
# Écrire sous l'UID 2000 et le GID 2000, sans créer de compte
setpriv --reuid=2000 --regid=2000 --clear-groups touch /mnt/essai-nfs/equipe/rapport.txt
Dans la console du conteneur 260 :
ls -l /srv/partage/equipe # le contenu, vu du serveur
getent passwd 2000 # existe-t-il un compte 2000 ?
Résultat attendu :
-rw-r--r-- 1 2000 2000 0 Oct 6 18:29 rapport.txt
getent ne répond rien : aucun compte 2000 n'existe dans le conteneur. NFS transmet le numéro d'UID tel quel, sans traduction par nom. Deux machines qui partagent des fichiers doivent donc avoir les mêmes UID.
Avec un chmod 770 sur /srv/partage au lieu de 775, l'UID 2000 ne peut même pas traverser le répertoire : Permission denied, alors que le sous-répertoire equipe lui appartient. Pour atteindre un fichier, il faut le droit x sur chaque répertoire du chemin.
Étape 5 — Le partage comme stockage de sauvegardes
Dans le Shell du nœud, démontez d'abord le montage d'essai :
umount /mnt/essai-nfs # démonter
rmdir /mnt/essai-nfs # retirer le point de montage
Via l'interface : Datacenter → Storage → Add → NFS — ID nfs-partage, Server 10.<site>.<N>.81, Export /srv/partage, Content Backup → Add. Puis CT 200 → Backup → Backup now — Storage nfs-partage, Mode Snapshot, Compression ZSTD → Backup.
Équivalent CLI, dans le Shell du nœud :
pvesm add nfs nfs-partage --server 10.<site>.<N>.81 --export /srv/partage --content backup # déclarer le partage
pvesm status | grep nfs-partage # actif ?
vzdump 200 --storage nfs-partage --mode snapshot --compress zstd # une sauvegarde dessus
Résultat attendu (extrait) :
nfs-partage nfs active 4046848 720896 3099648 17.81%
INFO: Finished Backup of VM 200 (00:00:07)
INFO: Backup job finished successfully
Datacenter → Storage : nfs-partage est de type NFS, contenu Backup, monté sous /mnt/pve/nfs-partage. Sa colonne Shared vaut Yes, contrairement aux trois stockages locaux.
Le stockage nfs-partage → Backups : la sauvegarde du CT 200, 206,79 Mio. Sa capacité (4 Go) est celle du disque du conteneur 260 : un partage n'offre que la place de ce qu'il exporte.
Dans la console du conteneur 260 :
ls -ln /srv/partage/dump # la sauvegarde, vue du serveur
Résultat attendu :
-rw-r--r-- 1 65534 65534 742 Oct 6 18:29 vzdump-lxc-200-2026_10_06-20_29_34.log
-rw-r--r-- 1 65534 65534 216834678 Oct 6 18:29 vzdump-lxc-200-2026_10_06-20_29_34.tar.zst
Proxmox écrit ses sauvegardes en root : sur ce partage, root_squash les fait appartenir à nobody, comme le fichier depuis-root de l'étape 3.
Validation finale
| Contrôle | Attendu |
|---|---|
exportfs -v dans le conteneur |
/srv/partage vers votre réseau, root_squash |
Propriétaire de depuis-root |
65534 |
Propriétaire de equipe/rapport.txt |
2000 |
pvesm status | grep nfs-partage |
active |
Nettoyage — dans cet ordre, dans le Shell du nœud :
pvesm remove nfs-partage # 1. le stockage d'abord : Proxmox cesse de l'utiliser
umount /mnt/pve/nfs-partage # 2. pvesm remove ne démonte pas
pct stop 260 # 3. le serveur ensuite : l'arrêter
pct destroy 260 --purge # puis le supprimer
pvesm status # nfs-partage a disparu, tout est active
Résultat attendu (pvesm status) :
local dir active 24527236 9683680 13680676 39.48%
local-lvm lvmthin active 64876544 41929710 22946833 64.63%
zfs-vms zfspool active 29965724 96 29965628 0.00%
Détruire le conteneur avant de retirer le stockage laisserait un nfs-partage déclaré mais injoignable. Sur le lab, serveur arrêté : pvesm status le montre inactive, avec une capacité de 0. Et umount -f -l est resté bloqué plusieurs minutes, jusqu'au redémarrage du serveur.
Proxmox VE — TSSR








