Aller au contenu
Infrastructure as Code medium
🔐 Alerte sécurité — Incident supply chain Trivy : lire mon analyse de l'attaque

Réseau virtuel avec Terraform et libvirt

14 min de lecture

logo terraform

Votre VM atterrit sur le réseau default de libvirt — un réseau partagé avec toutes les autres VMs de la machine. Si deux labs utilisent la même plage IP, les conflits sont inévitables. Avec libvirt_network, vous créez un réseau dédié, isolé et entièrement décrit en code.

Un réseau virtuel dédié résout trois problèmes concrets : l’isolation entre projets (chaque lab a sa plage IP), le DHCP automatique (les VMs obtiennent une IP sans configuration manuelle), et la reproductibilité (le réseau est détruit et recréé avec terraform destroy / terraform apply). Sans réseau dédié, vos labs interfèrent les uns avec les autres et le nettoyage devient manuel.

Ce que vous allez apprendre :

  • Créer un réseau NAT isolé avec DHCP via libvirt_network
  • Connecter une VM au réseau dédié avec une référence dynamique
  • Comprendre depends_on et la différence avec les dépendances implicites
  • Vérifier le réseau avec virsh net-list et virsh net-dumpxml

Prérequis : avoir suivi le guide Première infrastructure et avoir KVM actif sur votre machine.

Un réseau virtuel libvirt est un bridge logiciel créé dans KVM qui connecte des VMs entre elles et, optionnellement, vers l’extérieur. C’est l’équivalent d’un switch réseau physique, mais entièrement logiciel et géré par libvirt.

En mode NAT (le plus courant pour les labs), le réseau fournit :

  • Une passerelle (gateway) qui route le trafic vers l’extérieur
  • Un serveur DHCP qui distribue automatiquement des adresses IP aux VMs
  • Une isolation : les VMs du réseau ne sont pas visibles depuis d’autres réseaux libvirt

Sans réseau dédié, toutes vos VMs partagent le réseau default de libvirt :

SituationRéseau defaultRéseau dédié
Deux labs en parallèleConflits d’IP possiblesPlages IP séparées
NettoyageImpossible de détruire le réseau defaultterraform destroy supprime tout
ReproductibilitéDépend de l’état de la machineDécrit en code, reproductible

Dès que vous travaillez sur plus d’un projet Terraform en parallèle, un réseau dédié par lab devient indispensable.

Préparez le répertoire du lab et écrivez la configuration :

  1. Créez le répertoire de travail :

    Fenêtre de terminal
    mkdir -p ~/terraform-reseau-virtuel
    cd ~/terraform-reseau-virtuel
  2. Créez le fichier versions.tf :

    terraform {
    required_version = ">= 1.11.0"
    required_providers {
    libvirt = {
    source = "dmacvicar/libvirt"
    version = "~> 0.8"
    }
    }
    }
    provider "libvirt" {
    uri = "qemu:///system"
    }
  3. Créez le fichier main.tf avec le réseau, le disque et la VM :

    # Réseau NAT isolé avec DHCP
    resource "libvirt_network" "lab_net" {
    name = "lab14-net"
    autostart = false
    forward = { mode = "nat" }
    ips = [{
    address = "10.99.14.1"
    netmask = "255.255.255.0"
    dhcp = { ranges = [{ start = "10.99.14.100", end = "10.99.14.200" }] }
    }]
    }
    # Volume disque de la VM
    resource "libvirt_volume" "disk" {
    name = "lab14-vm.qcow2"
    pool = "default"
    target = { format = { type = "qcow2" } }
    create = { content = { url = pathexpand("~/images/ubuntu-24.04-cloudimg.img") } }
    }
    # VM connectée au réseau dédié
    resource "libvirt_domain" "vm" {
    name = "lab14-vm"
    type = "kvm"
    memory = 512
    memory_unit = "MiB"
    vcpu = 1
    os = { type = "hvm", type_arch = "x86_64", type_machine = "q35" }
    devices = {
    disks = [{
    source = { file = { file = libvirt_volume.disk.path } }
    target = { dev = "vda", bus = "virtio" }
    }]
    interfaces = [{
    model = { type = "virtio" }
    source = { network = { network = libvirt_network.lab_net.name } }
    }]
    }
    }
    output "network_name" {
    value = libvirt_network.lab_net.name
    description = "Nom du réseau virtuel créé"
    }
    output "vm_name" {
    value = libvirt_domain.vm.name
    description = "Nom de la VM connectée au réseau"
    }
  4. Initialisez et appliquez :

    Fenêtre de terminal
    terraform init
    terraform apply -auto-approve

    Terraform crée les ressources dans l’ordre des dépendances — le réseau en premier, puis le disque, enfin la VM.

Terraform affiche la progression pendant le apply. Notez l’ordre : le réseau est créé en premier, puis le disque, enfin la VM (car la VM dépend des deux autres) :

libvirt_network.lab_net: Creating...
libvirt_network.lab_net: Creation complete after 1s [id=...]
libvirt_volume.disk: Creating...
libvirt_volume.disk: Creation complete after 1s [id=...]
libvirt_domain.vm: Creating...
libvirt_domain.vm: Creation complete after 2s [id=...]
Apply complete! Resources: 3 added, 0 changed, 0 destroyed.
Outputs:
network_name = "lab14-net"
vm_name = "lab14-vm"

Vérifiez que le réseau existe dans libvirt :

Fenêtre de terminal
virsh net-list --all
Name State Autostart Persistent
----------------------------------------------
default active yes yes
lab14-net active no yes

La commande virsh net-dumpxml lab14-net affiche la configuration complète du réseau tel que libvirt l’a créé — vous retrouverez la plage DHCP 10.99.14.100–200 et le bridge associé.

Affichez les outputs à tout moment avec :

Fenêtre de terminal
terraform output
network_name = "lab14-net"
vm_name = "lab14-vm"

Maintenant que le réseau fonctionne, détaillons chaque attribut de la ressource libvirt_network :

resource "libvirt_network" "lab_net" {
name = "lab14-net" # Nom visible dans virsh net-list
autostart = false # Ne pas démarrer au boot de la machine hôte
forward = { mode = "nat" } # Trafic sortant via NAT (accès internet pour la VM)
ips = [{
address = "10.99.14.1" # Adresse du routeur (gateway) sur ce réseau
netmask = "255.255.255.0" # Masque /24 → 254 adresses disponibles
dhcp = { ranges = [{
start = "10.99.14.100" # Première adresse distribuée par DHCP
end = "10.99.14.200" # Dernière adresse distribuée par DHCP
}] }
}]
}

Dans cet exemple, la VM référence déjà explicitement le réseau avec libvirt_network.lab_net.name. Cette référence suffit à créer une dépendance implicite : Terraform sait qu’il doit créer le réseau avant la VM.

Si vous vouliez malgré tout rendre cette intention visible, vous pourriez ajouter :

depends_on = [libvirt_network.lab_net]

… mais ce serait ici redondant, pas indispensable.

La connexion entre la VM et le réseau se fait dans le bloc devices.interfaces :

interfaces = [{
model = { type = "virtio" }
source = { network = { network = libvirt_network.lab_net.name } }
# ↑ référence dynamique au nom du réseau
}]

En écrivant libvirt_network.lab_net.name au lieu de "lab14-net" en dur, vous créez une dépendance implicite : si le nom du réseau change, la VM est automatiquement mise à jour. C’est une bonne pratique Terraform — toujours préférer les références dynamiques aux valeurs en dur.

La ressource libvirt_network supporte des attributs avancés utiles en pratique :

AttributUtilité
dnsConfigurer un serveur DNS local pour les VMs
domainAssocier un domaine DNS (ex. lab.local)
bridgeSpécifier le nom du bridge Linux créé
mtuAjuster la MTU pour des réseaux spéciaux
ipv6Activer IPv6 sur le réseau

Pour la documentation complète des attributs, consultez le provider libvirt v0.9.7.

Fenêtre de terminal
terraform destroy -auto-approve

Terraform détruit les ressources dans l’ordre inverse : VM d’abord, puis disque et réseau :

libvirt_domain.vm: Destroying...
libvirt_domain.vm: Destruction complete after 1s
libvirt_volume.disk: Destroying...
libvirt_network.lab_net: Destroying...
libvirt_volume.disk: Destruction complete after 0s
libvirt_network.lab_net: Destruction complete after 0s
Destroy complete! Resources: 3 destroyed.

Vérifiez que le nettoyage est complet :

Fenêtre de terminal
virsh net-list --all | grep lab14
# (aucune sortie — réseau supprimé)

Cette propriété de destruction inversée est expliquée en détail dans le guide Détruire proprement.

  • libvirt_network crée un bridge virtuel KVM géré entièrement par Terraform.
  • Le mode nat donne accès internet aux VMs sans configuration supplémentaire.
  • depends_on sert surtout quand aucune référence directe n’exprime déjà la dépendance.
  • Référencer libvirt_network.lab_net.name au lieu d’un nom en dur crée une dépendance automatique.
  • virsh net-list confirme que le réseau existe indépendamment de Terraform.
  • L’ordre de destruction est l’inverse de l’ordre de création : VM → disque → réseau.

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracing. Aujourd'hui, ce site ne couvre même pas mes frais d'hébergement, d'électricité, de matériel, de logiciels, mais surtout de cafés.

Un soutien régulier, même symbolique, m'aide à garder ces ressources gratuites et à continuer de produire des guides de qualité. Merci pour votre appui.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn