
Vous devez déployer 5 workers identiques pour un cluster. Sans count,
vous copiez le bloc resource 5 fois et maintenez 5 noms distincts.
Ajouter un sixième worker demande de coller un bloc de plus — et réduire
à 3 demande d’en effacer deux manuellement.
Le meta-argument count résout ce problème : une seule ligne dans
un bloc resource, et Terraform crée N instances. count.index
expose l’entier courant (0 à N-1) pour personnaliser chaque instance —
noms, chemins de disques, adresses IP. Réduire count de 5 à 3
détruit proprement les deux dernières instances. count est conçu
pour les ressources vraiment interchangeables : workers d’un cluster,
replicas identiques, disques supplémentaires. Pour des instances avec
des rôles distincts — une VM web, une VM db, une VM cache — for_each
offre des identités stables dans le state.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »count: créer N instances d’une ressourcecount.index: personnaliser chaque instance (nom, disque…)- Adressage :
ressource.nom[index]et l’opérateur splat[*] - Modifier
count: ajouter ou retirer des instances - Limites de
count: quand utiliserfor_eachà la place
Prérequis
Section intitulée « Prérequis »- Blocs resource maîtrisés (déclarer des ressources)
- Variables comprises (variables Terraform)
L’idée derrière count
Section intitulée « L’idée derrière count »Pensez à une boucle for classique en Python :
for i in range(3): create_vm(f"vm-{i}") # vm-0, vm-1, vm-2count fait exactement cela en Terraform : au lieu de copier 3 blocs identiques, vous écrivez qu’il doit en créer 3, et Terraform génère l’équivalent.
Syntaxe minimale
Section intitulée « Syntaxe minimale »La logique : « pour chaque index de 0 à N-1, créer une ressource avec ce numéro ».
resource "libvirt_volume" "disk" { count = 3 # ← Créer 3 instances
name = "vm-${count.index}.qcow2" # ← Utiliser l'index (0, 1, 2) dans le nom pool = "default"}En HCL :
count = 3signifie « créer 3 instances de cette ressource »count.indexdans le bloc renvoie à l’index courant : 0, 1, ou 2- Chaque instance reçoit un nom unique grâce à
${count.index}
Exemple : 3 VMs avec count
Section intitulée « Exemple : 3 VMs avec count »variable "vm_count" { type = number default = 3 validation { condition = var.vm_count >= 1 && var.vm_count <= 5 error_message = "vm_count doit être entre 1 et 5." }}
# main.tfresource "libvirt_volume" "disk" { count = var.vm_count
name = "${var.vm_name_prefix}-${count.index}.qcow2" pool = var.pool target = { format = { type = "qcow2" } } create = { content = { url = var.image_path } }}
resource "libvirt_domain" "vm" { count = var.vm_count
name = "${var.vm_name_prefix}-${count.index}" memory = 512 memory_unit = "MiB" vcpu = 1
devices = { disks = [ { source = { file = { file = libvirt_volume.disk[count.index].path } } target = { dev = "vda", bus = "virtio" } } ] } depends_on = [libvirt_volume.disk]}Résultat de l’apply avec vm_count = 3 :
Apply complete! Resources: 6 added, 0 changed, 0 destroyed.
Outputs:
disk_paths = [ "/var/lib/libvirt/images/lab08-vm-0.qcow2", "/var/lib/libvirt/images/lab08-vm-1.qcow2", "/var/lib/libvirt/images/lab08-vm-2.qcow2",]vm_names = [ "lab08-vm-0", "lab08-vm-1", "lab08-vm-2",]Adresser une instance spécifique
Section intitulée « Adresser une instance spécifique »Avec count, une ressource devient une liste d’instances adressables
par index :
# Accéder au disque de la VM 0libvirt_volume.disk[0].path
# Accéder au disque de la VM courante dans le même bloc countlibvirt_volume.disk[count.index].pathDans le terraform state list, les instances apparaissent avec leur index :
libvirt_domain.vm[0]libvirt_domain.vm[1]libvirt_domain.vm[2]libvirt_volume.disk[0]libvirt_volume.disk[1]libvirt_volume.disk[2]L’opérateur splat [*]
Section intitulée « L’opérateur splat [*] »Pour récupérer une liste de tous les attributs d’une ressource avec count :
output "vm_names" { value = libvirt_domain.vm[*].name # ["lab08-vm-0", "lab08-vm-1", "lab08-vm-2"]}
output "disk_paths" { value = libvirt_volume.disk[*].path # ["/var/.../lab08-vm-0.qcow2", ...]}[*] est l’opérateur splat — il extrait l’attribut .name ou .path
de toutes les instances et retourne une liste.
Modifier count : ajouter ou retirer des instances
Section intitulée « Modifier count : ajouter ou retirer des instances »Passer de 3 à 2 VMs :
terraform apply -var="vm_count=2"Apply complete! Resources: 0 added, 0 changed, 2 destroyed.Terraform détruit vm[2] et disk[2] — les instances avec le plus
grand index. C’est ici le piège principal de count.
count conditionnel : 0 ou 1 instance
Section intitulée « count conditionnel : 0 ou 1 instance »Un usage particulier : créer une ressource optionnelle selon un flag.
variable "enable_monitoring_vm" { type = bool # ← Booléen : true ou false default = false}
resource "libvirt_domain" "monitoring" { count = var.enable_monitoring_vm ? 1 : 0 # ← Si true, créer 1 ; si false, créer 0
name = "monitoring-vm" # ...}Résultat :
- Si
enable_monitoring_vm = false→count = 0→ la ressource n’est pas créée - Si
enable_monitoring_vm = true→count = 1→ la ressource est créée une fois
Accéder à une ressource optionnelle : one()
Section intitulée « Accéder à une ressource optionnelle : one() »Quand count vaut 0 ou 1, la ressource est soit absente, soit présente une fois. Pour y accéder en output, utiliser one() :
one() est une fonction Terraform qui demande : « donne-moi l’unique élément de cette liste » :
- Si la liste a 0 éléments → retourne
null - Si la liste a 1 élément → retourne cet élément
- Si la liste en a plusieurs → erreur (empêche les bugs)
Exemple :
output "monitoring_vm_name" { value = one(libvirt_domain.monitoring[*].name) # ↑ ↑ splat : liste de tous les noms (0 ou 1 élément) # si count=0 : null # si count=1 : "monitoring-vm"}Référence rapide
Section intitulée « Référence rapide »| Syntaxe | Usage |
|---|---|
count = 3 | Créer 3 instances |
count = var.n | Nombre variable |
count = condition ? 1 : 0 | Ressource optionnelle |
| Valeur connue avant apply | count ne peut pas dépendre d’un attribut “known after apply” |
count.index | Index de l’instance courante (0 à count-1) |
ressource.nom[index] | Accéder à une instance spécifique |
ressource.nom[*].attr | Splat : liste de tous les attributs |
one(liste) | Extraire l’unique élément (si 0 ou 1 seul) |
Dépannage
Section intitulée « Dépannage »| Symptôme | Cause probable | Solution |
|---|---|---|
count.index hors d’un bloc count | count.index utilisé sans count déclaré | Ajouter count = … à la ressource |
| Ressources détruites/recrées au changement de count | Réindexation par Terraform | Normal — prévisible ; utiliser for_each si l’ordre est sensible |
Error: Invalid index | Index hors limites dans ressource[x] | Vérifier que x < count |
| Modification d’une ressource count=0→1 détruit les autres | State recalculé | Utiliser terraform plan pour anticiper |
The "count" value depends on resource attributes that cannot be determined until apply | count dépend d’un attribut inconnu avant apply | Utiliser une variable ou un data source dont la valeur est connue au plan |
À retenir
Section intitulée « À retenir »countcrée N instances d’une ressource avec un seul bloccount.index(0 à N-1) différencie les instancescount = condition ? 1 : 0rend une ressource optionnelleone(ressource[*].attr)accède à une ressource optionnelle en output- Réduire
countsupprime les instances de plus grand index - La valeur de
countdoit être connue avant l’apply — pas d’attribut “known after apply” - Le splat
[*]fonctionne aveccount(liste) mais pas avecfor_each(map) - Pour des instances nommées distinctement → préférer
for_each