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

count Terraform : créer N ressources identiques

11 min de lecture

logo terraform

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.

  • count : créer N instances d’une ressource
  • count.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 utiliser for_each à la place

Pensez à une boucle for classique en Python :

for i in range(3):
create_vm(f"vm-{i}")
# vm-0, vm-1, vm-2

count 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.

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 = 3 signifie « créer 3 instances de cette ressource »
  • count.index dans le bloc renvoie à l’index courant : 0, 1, ou 2
  • Chaque instance reçoit un nom unique grâce à ${count.index}
variables.tf
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.tf
resource "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",
]

Avec count, une ressource devient une liste d’instances adressables par index :

# Accéder au disque de la VM 0
libvirt_volume.disk[0].path
# Accéder au disque de la VM courante dans le même bloc count
libvirt_volume.disk[count.index].path

Dans 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]

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.

Passer de 3 à 2 VMs :

Fenêtre de terminal
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.

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 = falsecount = 0 → la ressource n’est pas créée
  • Si enable_monitoring_vm = truecount = 1 → la ressource est créée une fois

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"
}
SyntaxeUsage
count = 3Créer 3 instances
count = var.nNombre variable
count = condition ? 1 : 0Ressource optionnelle
Valeur connue avant applycount ne peut pas dépendre d’un attribut “known after apply”
count.indexIndex de l’instance courante (0 à count-1)
ressource.nom[index]Accéder à une instance spécifique
ressource.nom[*].attrSplat : liste de tous les attributs
one(liste)Extraire l’unique élément (si 0 ou 1 seul)
SymptômeCause probableSolution
count.index hors d’un bloc countcount.index utilisé sans count déclaréAjouter count = … à la ressource
Ressources détruites/recrées au changement de countRéindexation par TerraformNormal — prévisible ; utiliser for_each si l’ordre est sensible
Error: Invalid indexIndex hors limites dans ressource[x]Vérifier que x < count
Modification d’une ressource count=0→1 détruit les autresState recalculéUtiliser terraform plan pour anticiper
The "count" value depends on resource attributes that cannot be determined until applycount dépend d’un attribut inconnu avant applyUtiliser une variable ou un data source dont la valeur est connue au plan
  1. count crée N instances d’une ressource avec un seul bloc
  2. count.index (0 à N-1) différencie les instances
  3. count = condition ? 1 : 0 rend une ressource optionnelle
  4. one(ressource[*].attr) accède à une ressource optionnelle en output
  5. Réduire count supprime les instances de plus grand index
  6. La valeur de count doit être connue avant l’apply — pas d’attribut “known after apply”
  7. Le splat [*] fonctionne avec count (liste) mais pas avec for_each (map)
  8. Pour des instances nommées distinctement → préférer for_each

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