
Cette référence récapitule l'usage du provider Terraform OUTSCALE version 1.5.0 : configuration du provider avec les nouveaux blocs api { ... } / oks { ... }, backend d'état centralisé sur OOS, ressources et datasources principales (Net, Subnet, VM, Volume, Security Group, Public IP, Route Table…), patterns alignés sur les piliers Well-Architected, antipatterns observés. Les exemples sont repris du guide pratique existant et alignés sur la syntaxe v1.5.0. La page est organisée par topic pour une consultation ciblée plutôt qu'une lecture linéaire.
Versions et compatibilité
Section intitulée « Versions et compatibilité »Trois versions conditionnent le fonctionnement de tout ce qui suit : celle du provider, celle de Terraform lui-même et, le cas échéant, celle d'OpenTofu. Le passage à la branche 1.x du provider n'est pas une simple montée de version : la syntaxe du bloc provider change, ce qui explique la section suivante. Vérifiez ces trois lignes avant de copier un exemple de cette page.
| Composant | Version cible | Note |
|---|---|---|
| Provider OUTSCALE | outscale/outscale v1.5.0 | Source officielle, v1.x change la syntaxe du provider (voir « Provider »). |
| Terraform | 1.10.x ou plus récent | La doc README du provider exige 1.10.x or latest. |
| OpenTofu | Compatible | Source outscale/outscale valide pour tofu init (ou registry.opentofu.org/outscale/outscale). |
La migration depuis les versions 0.x du provider implique des renommages d'état (par exemple outscale_volumes_link → outscale_volume_link). Suivre le guide de migration officiel avant terraform init -upgrade.
Provider, configuration v1.5.0
Section intitulée « Provider, configuration v1.5.0 »WAF, Operational Excellence, Security. Le provider est la porte d'entrée du pipeline IaC. Sa configuration centralise authentification, endpoint et région ; elle se versionne au même titre que le code applicatif.
Required providers
Section intitulée « Required providers »La version du provider est ici figée à une valeur exacte plutôt qu'à un intervalle : sur une page de référence, cela garantit que la syntaxe décrite correspond à celle que terraform init téléchargera.
terraform { required_version = ">= 1.10.0" required_providers { outscale = { source = "outscale/outscale" version = "1.5.0" } }}Provider, blocs api et oks
Section intitulée « Provider, blocs api et oks »Depuis la v1.4.0, le provider expose des blocs par service : api { ... } pour l'OAPI principale (réseau, compute, stockage…) et oks { ... } pour OKS (Kubernetes managé). Les attributs racine region, endpoints { ... }, x509_cert_path, x509_key_path, insecure sont deprecated et seront retirés au prochain major.
provider "outscale" { access_key_id = var.access_key_id secret_key_id = var.secret_key_id
api { endpoint = "https://api.eu-west-2.outscale.com" region = "eu-west-2" }
oks { endpoint = "https://api.eu-west-2.oks.outscale.com/api/v2" region = "eu-west-2" }}Pour la région SecNumCloud, remplacer eu-west-2 par cloudgouv-eu-west-1 dans les blocs et adapter les endpoints en conséquence.
Authentification, variables d'environnement
Section intitulée « Authentification, variables d'environnement »Le provider lit directement ses identifiants depuis les variables d'environnement standard OUTSCALE, pas besoin de les passer via des var Terraform. Les variables reconnues (validées sur la documentation officielle du provider v1.5.0) :
| Variable | Usage |
|---|---|
OUTSCALE_ACCESSKEYID | Access key (équivalent attribut access_key_id) |
OUTSCALE_SECRETKEYID | Secret key (équivalent secret_key_id) |
OUTSCALE_REGION | Région cible (équivalent api.region et oks.region) |
OUTSCALE_X509CERT | Chemin du certificat x509 client |
OUTSCALE_X509KEY | Chemin de la clé privée x509 |
OSC_PROFILE | Nom du profil dans le fichier de configuration OSC |
OSC_CONFIG_FILE | Chemin du fichier de configuration OSC (défaut ~/.osc/config.json) |
Avec ces variables exportées, un provider "outscale" {} vide suffit pour l'authentification :
# Linux / macOSexport OUTSCALE_ACCESSKEYID="..."export OUTSCALE_SECRETKEYID="..."export OUTSCALE_REGION="eu-west-2"# Bloc provider minimalprovider "outscale" {}Profil et fichier de configuration OSC
Section intitulée « Profil et fichier de configuration OSC »Alternative à l'export en variables : pointer un profil dans le fichier ~/.osc/config.json (le même que celui de oapi-cli).
provider "outscale" { config_file = "./.osc/config.json" profile = "default"}Ou via les variables OSC_CONFIG_FILE et OSC_PROFILE, utile pour basculer entre comptes (par exemple OSC_PROFILE=prod vs OSC_PROFILE=secnumcloud) sans toucher au code Terraform.
x509 (authentification certificat)
Section intitulée « x509 (authentification certificat) »Pour les contextes qui imposent l'authentification par certificat client (typique des environnements cloudgouv-eu-west-1), placer les chemins dans le bloc api :
provider "outscale" { api { x509_cert_path = "/etc/outscale/client.crt" x509_key_path = "/etc/outscale/client.key" }}Ou via les variables d'environnement OUTSCALE_X509CERT et OUTSCALE_X509KEY. Les attributs racine x509_cert_path / x509_key_path du provider sont deprecated.
Backend d'état, OOS
Section intitulée « Backend d'état, OOS »WAF, Operational Excellence, Security, Reliability. Centraliser l'état Terraform sur OOS garantit reproductibilité, collaboration et traçabilité. C'est le mécanisme qui transforme un script local en pipeline équipe. Le backend s3 natif Terraform fonctionne sur OOS, mais avec plusieurs flags spécifiques parce que le SDK AWS Go v2 utilisé en interne par Terraform 1.6+ a hérité de comportements AWS-only qu'il faut neutraliser.
terraform { backend "s3" { bucket = "capstone-outscale-tfstate" key = "00-nets/terraform.tfstate" region = "eu-west-2"
endpoints = { s3 = "https://oos.eu-west-2.outscale.com" }
skip_credentials_validation = true skip_region_validation = true skip_requesting_account_id = true skip_metadata_api_check = true skip_s3_checksum = true use_path_style = true }}Chaque option a une raison d'être, pas de copier-coller à l'aveugle :
| Option | Pourquoi sur OOS |
|---|---|
endpoints = { s3 = "..." } | Depuis Terraform 1.6+, l'attribut racine endpoint (singulier) est deprecated au profit du bloc endpoints (pluriel) qui couvre plusieurs services (s3, dynamodb, iam, sts). |
skip_credentials_validation = true | Le backend essaie sinon de valider les credentials via STS AWS, qui n'existe pas sur OOS. |
skip_region_validation = true | La liste de régions valides est codée en dur côté SDK AWS, eu-west-2 chez OUTSCALE n'y figure pas. |
skip_requesting_account_id = true | Le SDK appelle sinon STS:GetCallerIdentity pour récupérer l'AccountId. Pas d'équivalent OAPI exposé via le SDK S3. |
skip_metadata_api_check = true | Le SDK essaie sinon de lire IMDS (169.254.169.254) au cas où il tournerait sur EC2. Sur un poste local ou un runner CI hors AWS, c'est un timeout systématique au démarrage. |
skip_s3_checksum = true | Désactive le calcul de checksum S3 supplémentaire qui n'est pas reconnu par OOS. |
use_path_style = true | OOS expose https://oos.eu-west-2.outscale.com/<bucket>/... (path-style) et pas le DNS virtual-hosted <bucket>.oos.eu-west-2.outscale.com. Sans ce flag, chaque requête échoue en NoSuchBucket ou DNS resolution. |
Le bucket de backend doit être créé avant le premier terraform init. Avec aws-cli, en pensant bien à --endpoint-url (et pas --endpoint, deprecated) :
aws --endpoint-url https://oos.eu-west-2.outscale.com \ --region eu-west-2 \ s3api create-bucket --bucket capstone-outscale-tfstate
# Versioning : récupération de state en cas de corruption ou de mauvais merge.aws --endpoint-url https://oos.eu-west-2.outscale.com \ s3api put-bucket-versioning --bucket capstone-outscale-tfstate \ --versioning-configuration Status=Enabled
# Chiffrement serveur AES256 : au repos.aws --endpoint-url https://oos.eu-west-2.outscale.com \ s3api put-bucket-encryption --bucket capstone-outscale-tfstate \ --server-side-encryption-configuration \ '{"Rules":[{"ApplyServerSideEncryptionByDefault":{"SSEAlgorithm":"AES256"}}]}'Patterns de hardening à appliquer sur le bucket de backend : activer le versioning (récupération en cas de corruption d'état), chiffrement serveur AES256 (voir Stockage OOS, versioning, lifecycle), accès restreint à un rôle EIM dédié au pipeline IaC, isolation dans un compte d'audit séparé du compte applicatif. Un script bootstrap-tfstate-bucket.sh idempotent évite de répéter ces commandes manuellement à chaque création de projet.
Ressources réseau
Section intitulée « Ressources réseau »WAF, Reliability, Security, Performance. Le réseau est la première fondation, taguée multi-AZ et segmentée par tier. Les ressources de cette section s'enchaînent dans un ordre imposé par leurs dépendances : le Net d'abord, puis les Subnets qui le découpent, ensuite les passerelles de sortie et enfin les tables de routage qui relient le tout. Terraform déduit cet ordre des références entre ressources, mais le connaître aide à lire un plan et à comprendre pourquoi une destruction partielle échoue.
outscale_net, Net (VPC)
Section intitulée « outscale_net, Net (VPC) »Le Net est l'équivalent VPC. Préférer un /16 qui laisse la marge nécessaire au peering futur.
resource "outscale_net" "main" { ip_range = "192.168.0.0/16"
tags { key = "Name" value = "main-net" } tags { key = "env" value = "prod" }}Référence du paramètre IpRange (au format CIDR RFC 1918) : voir Réseau, design Net + Subnets.
outscale_subnet, Subnet par sous-région
Section intitulée « outscale_subnet, Subnet par sous-région »Un Subnet appartient à un Net et à une seule sous-région, désignée par subregion_name. Son ip_range doit être inclus dans celui du Net parent et ne chevaucher aucun autre subnet.
resource "outscale_subnet" "public_a" { net_id = outscale_net.main.net_id subregion_name = "eu-west-2a" ip_range = "192.168.2.0/24"
tags { key = "Name" value = "public-a" }}Pour le pilier Reliability, créer un subnet par tier (public / privé / data) et par sous-région (eu-west-2a, eu-west-2b, eu-west-2c).
Internet Service et liaison
Section intitulée « Internet Service et liaison »L'Internet Service se crée sans aucun argument, puis une ressource de liaison distincte l'attache au Net. Cette séparation en deux objets est volontaire : elle permet de détacher la passerelle sans la détruire.
resource "outscale_internet_service" "igw" {}
resource "outscale_internet_service_link" "igw_link" { internet_service_id = outscale_internet_service.igw.internet_service_id net_id = outscale_net.main.net_id}NAT Service et IP publique
Section intitulée « NAT Service et IP publique »Le NAT Service vit dans un subnet public et porte une IP publique allouée séparément.
resource "outscale_public_ip" "nat_eip" {}
resource "outscale_nat_service" "nat" { subnet_id = outscale_subnet.public_a.subnet_id public_ip_id = outscale_public_ip.nat_eip.public_ip_id
tags { key = "Name" value = "nat-public-a" }}Routes et tables de routage
Section intitulée « Routes et tables de routage »C'est la table de routage associée à un subnet qui détermine s'il est réellement public ou privé, pas son nom. L'exemple suivant matérialise cette distinction : la table publique envoie le trafic sortant vers l'Internet Service, la table privée vers le NAT Service. La ressource de liaison finale est indispensable, une table sans outscale_route_table_link n'a aucun effet.
resource "outscale_route_table" "public" { net_id = outscale_net.main.net_id}
resource "outscale_route_table" "private" { net_id = outscale_net.main.net_id}
resource "outscale_route" "public_to_igw" { route_table_id = outscale_route_table.public.route_table_id destination_ip_range = "0.0.0.0/0" gateway_id = outscale_internet_service.igw.internet_service_id}
resource "outscale_route" "private_to_nat" { route_table_id = outscale_route_table.private.route_table_id destination_ip_range = "0.0.0.0/0" nat_service_id = outscale_nat_service.nat.nat_service_id}
resource "outscale_route_table_link" "public_link" { subnet_id = outscale_subnet.public_a.subnet_id route_table_id = outscale_route_table.public.route_table_id}Ressources sécurité réseau
Section intitulée « Ressources sécurité réseau »WAF, Security. Le pattern SG-to-SG (un Security Group autorise un autre Security Group plutôt qu'un CIDR) est la base d'une posture défendable. Voir Réseau, Security Groups.
outscale_security_group et outscale_security_group_rule
Section intitulée « outscale_security_group et outscale_security_group_rule »Le groupe et ses règles sont deux ressources distinctes : déclarer les règles séparément permet de les faire évoluer sans recréer le groupe, donc sans détacher les VMs qui l'utilisent. L'attribut flow indique le sens du trafic concerné par la règle.
resource "outscale_security_group" "web" { description = "HTTP/HTTPS from Internet" security_group_name = "web-public" net_id = outscale_net.main.net_id}
resource "outscale_security_group_rule" "web_https" { flow = "Inbound" security_group_id = outscale_security_group.web.id from_port_range = 443 to_port_range = 443 ip_protocol = "tcp" ip_range = "0.0.0.0/0"}Attention : le nom du Security Group passé à security_group_name ne doit pas commencer par sg- (réservé aux IDs internes du provider). Utiliser un préfixe métier (web-public, app-back, db-data).
Antipattern à éviter : ip_range = "0.0.0.0/0" sur le port 22. Le SSH ne doit jamais être ouvert sur Internet, il transite par le bastion dans le subnet public, qui est lui-même restreint à votre IP fixe ou au CIDR de votre VPN.
Pour le pattern SG-to-SG, utiliser security_group_name_to_link (référence à un autre SG par nom) ou les blocs rules { security_groups_members { security_group_id = ... } } :
resource "outscale_security_group_rule" "db_from_app" { flow = "Inbound" security_group_id = outscale_security_group.database.id rules { from_port_range = 5432 to_port_range = 5432 ip_protocol = "tcp" security_groups_members { security_group_id = outscale_security_group.app.id } }}Ressources compute
Section intitulée « Ressources compute »WAF, Performance Efficiency, Cost. Trois ressources suffisent à faire tourner une machine et à la joindre : une paire de clés pour l'accès SSH, la VM elle-même, et si nécessaire une IP publique attachée séparément. Le dimensionnement de la VM passe par le seul attribut vm_type, dont le format est propre à OUTSCALE et détaillé plus bas.
outscale_keypair
Section intitulée « outscale_keypair »La ressource n'envoie que la partie publique de la clé : la clé privée ne quitte jamais votre poste. Terraform ne peut pas la régénérer, sa perte impose de recréer la paire et de redéployer les VMs qui l'utilisent.
resource "outscale_keypair" "admin" { keypair_name = "admin-key" public_key = file("~/.ssh/id_ed25519.pub")}outscale_vm
Section intitulée « outscale_vm »L'image (image_id) est ici résolue par un datasource plutôt qu'écrite en dur, ce qui évite de casser le code à chaque publication d'une nouvelle OMI. Les autres attributs rattachent la machine au réseau et à sa sécurité : le subnet détermine sa sous-région, les groupes de sécurité les flux autorisés.
resource "outscale_vm" "bastion" { image_id = data.outscale_images.bastion_omi.images[0].image_id vm_type = "tinav5.c1r2p2" keypair_name = outscale_keypair.admin.keypair_name security_group_ids = [outscale_security_group.bastion_sg.id] subnet_id = outscale_subnet.public_a.subnet_id
tags { key = "Name" value = "bastion" } tags { key = "env" value = "prod" } tags { key = "owner" value = "platform" }}WAF, Performance Efficiency, Cost. Le vm_type suit le format TINA natif tinavW.cXrYpZ (voir Calcul, instances TINA et sizing). Les noms AWS-style (t2.small, m5.large) sont acceptés par compatibilité mais déconseillés en parcours OUTSCALE, préférer le format natif qui exprime exactement le couple vCPU / RAM / flag de performance.
outscale_public_ip et outscale_public_ip_link
Section intitulée « outscale_public_ip et outscale_public_ip_link »Là encore, l'allocation de l'adresse et son rattachement à une VM sont deux ressources séparées. C'est ce découpage qui permet de conserver la même adresse publique lors du remplacement d'une machine, mais aussi de laisser une adresse allouée sans usage.
resource "outscale_public_ip" "bastion_eip" {}
resource "outscale_public_ip_link" "bastion_link" { vm_id = outscale_vm.bastion.vm_id public_ip = outscale_public_ip.bastion_eip.public_ip}WAF, Cost. Une EIP allouée mais non attachée à une VM est facturée, c'est un gisement classique de gaspillage. Auditer périodiquement via oapi-cli ReadPublicIps.
Ressources stockage
Section intitulée « Ressources stockage »WAF, Reliability, Performance, Cost. Voir Stockage, BSU, volumes, IOPS pour le choix du type. Le stockage bloc suit la même logique de découpage que le reste du provider : le volume existe indépendamment de la machine, une ressource de liaison l'y rattache, et le snapshot en fige le contenu à un instant donné. Un volume est créé dans une sous-région précise et ne peut être attaché qu'à une VM de cette même sous-région.
outscale_volume
Section intitulée « outscale_volume »Deux attributs déterminent le comportement et le coût : la taille en gibioctets et le volume_type. Le type retenu ici, gp2, couvre les usages courants ; les volumes à IOPS provisionnées se configurent différemment, comme indiqué juste après.
resource "outscale_volume" "data" { subregion_name = "eu-west-2a" size = 100 volume_type = "gp2"
tags { key = "Name" value = "app-data" }}Pour io1, ajouter iops (entier) avec un plafond de 13 000 IOPS par volume et un ratio maximum de 300 IOPS/GiB (validé sur la spec OAPI CreateVolume).
outscale_volume_link
Section intitulée « outscale_volume_link »Cette ressource attache un volume existant à une VM sous un nom de périphérique donné. Le système d'exploitation invité peut exposer le disque sous un autre nom que celui demandé, vérifiez-le côté machine avant d'écrire une entrée dans /etc/fstab.
Attention à la migration v1 : la ressource s'appelait outscale_volumes_link avant la v1.0.0. Elle a été renommée en outscale_volume_link (singulier).
resource "outscale_volume_link" "data_attach" { vm_id = outscale_vm.app.vm_id volume_id = outscale_volume.data.volume_id device_name = "/dev/xvdf"}outscale_snapshot
Section intitulée « outscale_snapshot »Un snapshot déclaré ainsi est pris une seule fois, à la création de la ressource : Terraform ne le rafraîchit pas aux apply suivants. Pour des sauvegardes récurrentes, pilotez-les depuis un ordonnanceur externe et réservez cette ressource aux points de restauration liés à un changement d'infrastructure.
resource "outscale_snapshot" "data_snapshot" { volume_id = outscale_volume.data.volume_id
tags { key = "Name" value = "app-data-backup" } tags { key = "backup-date" value = "2026-04-29" }}WAF, Reliability, Cost. Snapshots couvrent les niveaux 1 et 2 de la règle 3-2-1 ; le niveau 3 (hors-site) est un export OOS dans un compte séparé. Voir Sauvegardes, RPO/RTO/PRA.
Datasources principales
Section intitulée « Datasources principales »WAF, Operational Excellence. Les datasources évitent de hardcoder des IDs (qui changent) et permettent de référencer des ressources créées dans une autre stack ou hors Terraform.
outscale_images, chercher une OMI
Section intitulée « outscale_images, chercher une OMI »La recherche s'effectue par filtre et retourne une liste, d'où l'indexation images[0] au moment de l'utiliser. Si le filtre remonte plusieurs images, l'ordre n'est pas garanti : resserrez-le jusqu'à obtenir un résultat unique.
data "outscale_images" "ubuntu_2204" { filter { name = "image_names" values = ["ubuntu_2204_steph"] }}
# Usageresource "outscale_vm" "app" { image_id = data.outscale_images.ubuntu_2204.images[0].image_id # ...}Antipattern : référencer une OMI publique avec un nom comprenant latest. Pour la reproductibilité, fixer un nom de version explicite (ubuntu_2204_v3 plutôt que ubuntu_latest), c'est le métier de Packer (voir page « Référence Packer »).
outscale_subnet, outscale_security_group
Section intitulée « outscale_subnet, outscale_security_group »Les datasources utilisent le pattern filter { name = "..." values = [...] } validé sur la documentation officielle du provider v1.5.0. Le filtre par nom de groupe se fait via name = "security_group_names" (pluriel, c'est un nom de filtre, pas l'attribut singulier de la ressource).
data "outscale_subnet" "public_a" { filter { name = "tag_values" values = ["public-a"] }}
data "outscale_security_group" "web" { filter { name = "security_group_names" values = ["web-public"] }}Patterns Well-Architected
Section intitulée « Patterns Well-Architected »Les cinq patterns qui suivent ne portent pas sur une ressource en particulier mais sur l'organisation du code et sur la façon dont les changements atteignent la production. Ce sont eux qui font la différence entre un dépôt Terraform qui tient trois ans et un dépôt que plus personne n'ose exécuter. Chacun est rattaché aux piliers Well-Architected qu'il sert.
Stacks séparées par lifecycle
Section intitulée « Stacks séparées par lifecycle »WAF, Operational Excellence, Reliability. Découper le code Terraform en stacks (modules logiques avec leur propre backend) selon le cycle de vie : réseau (rare changement), compute (changements applicatifs), bastion (sécurité). L'arborescence type :
terraform/├── infrastructure/ # Net, Subnets, IGW, NAT, SG (fondations)├── bastion/ # VM bastion + clé SSH├── workloads/ # VMs applicatives└── shared/ # Resources transverses (DNS, certificats)Chaque répertoire pointe vers une key distincte du backend OOS (infrastructure/terraform.tfstate, bastion/terraform.tfstate, etc.) pour éviter les blast radius cross-stack.
Tagging unifié systématique
Section intitulée « Tagging unifié systématique »WAF, Operational Excellence, Cost. Cinq tags structurants à appliquer sur toutes les ressources facturées : Name, env, project, owner, cost-center. Sur OUTSCALE, le tagging Terraform suit la syntaxe à blocs tags { key = "..." value = "..." } (différent du tags = { ... } AWS provider).
resource "outscale_vm" "app" { # ... tags { key = "Name" value = "app-prod-01" } tags { key = "env" value = "prod" } tags { key = "project" value = "billing-api" } tags { key = "owner" value = "platform-team" } tags { key = "cost-center" value = "BU-DSI" }}Le contrôle CI sur la présence des tags rend la discipline non-négociable. Voir Pilier Operational Excellence.
Pipeline IaC, porte d'entrée unique
Section intitulée « Pipeline IaC, porte d'entrée unique »WAF, Operational Excellence, Security. Toute modification de la production passe par un commit Git → revue PR → exécution Terraform sur runner CI dédié. Pas de terraform apply depuis un poste développeur sur la production. Le compte EIM utilisé par le runner est dédié au pipeline avec une politique scopée à ce qu'il a réellement le droit de modifier.
Une break-glass procedure documente les rares cas où une intervention directe est autorisée (incident majeur, indisponibilité du pipeline) avec enregistrement systématique et commit de réconciliation dans les 24 heures.
Articulation Terraform / Packer / Ansible
Section intitulée « Articulation Terraform / Packer / Ansible »WAF, Operational Excellence, Security. Les trois outils ont des rôles complémentaires :
- Packer construit des OMI durcies (image immuable + Ansible côté provisionneur).
- Terraform déploie l'infrastructure à partir de ces OMI.
- Ansible configure le runtime sur les VMs déployées (déploiement applicatif, secrets injectés au runtime).
Le découpage évite l'antipattern « Terraform qui fait tout » (lent, fragile sur les mises à jour applicatives) et le complémentaire « Ansible qui provisionne l'infra » (peu reproductible).
Inventaire dynamique Ansible via le plugin AWS
Section intitulée « Inventaire dynamique Ansible via le plugin AWS »WAF, Operational Excellence. OUTSCALE étant compatible AWS sur l'API EC2, le plugin d'inventaire Ansible amazon.aws.aws_ec2 fonctionne pour découvrir les VMs taguées. Configuration minimale :
plugin: amazon.aws.aws_ec2aws_profile: outscaleregions: - eu-west-2keyed_groups: - key: tags.Application separator: '' - key: tags.env separator: ''hostnames: - ip-address - private-ip-addressL'inventaire dynamique se synchronise automatiquement avec ce que Terraform a déployé, à condition que le tagging soit discipliné (cf. pattern Tagging unifié).
Antipatterns à éviter
Section intitulée « Antipatterns à éviter »Ces six erreurs reviennent régulièrement sur des dépôts Terraform en production. Elles ont un point commun : aucune ne provoque d'échec immédiat, toutes se paient plus tard, au moment d'une rotation d'image, d'un travail à plusieurs ou d'une montée de version du provider.
Hardcoder des IDs. Référencer un image_id = "ami-a3ca408c" directement dans le code. Le code casse à la moindre rotation de l'OMI. Préférer le datasource outscale_images avec un filtre par nom versionné.
Provisionner depuis Cockpit puis « faire du Terraform ». Créer des ressources via le Cockpit puis tenter d'importer dans Terraform a posteriori. Le résultat est une dette technique persistante. Démarrer Terraform-first dès le J1.
Backend local en équipe. Stocker l'état dans terraform.tfstate localement quand plusieurs personnes travaillent sur la stack. Les conflits d'état arrivent au premier apply concurrent. Backend OOS centralisé dès le J1.
Mélange tags = { ... } AWS-style et tags { key = "..." value = "..." } natif. Le provider OUTSCALE utilise la syntaxe à blocs. Le mélange provoque des erreurs de validation ou un tagging silencieusement perdu.
Région au niveau provider (deprecated). Utiliser region = "eu-west-2" à la racine du bloc provider "outscale" est deprecated en v1.5.0. Migrer vers api { region = "..." }.
Une seule stack géante. Tout dans un seul main.tf → blast radius énorme, terraform plan interminable, conflits d'équipe permanents. Découper par cycle de vie.
À retenir
Section intitulée « À retenir »- Provider
outscale/outscalev1.5.0, auth viaaccess_key_id+secret_key_id, configuration par service dansapi { ... }etoks { ... }. - Backend OOS centralisé avec versioning, chiffrement, accès restreint via rôle EIM dédié.
- Format TINA natif
tinavW.cXrYpZpourvm_type, pas les noms AWS-style. - Tagging unifié,
Name,env,project,owner,cost-centersur toutes les ressources facturées, contrôlé en CI. - Stacks séparées par cycle de vie (réseau, bastion, workloads), backend
keydistinct par stack. - Pipeline IaC comme porte d'entrée unique des changements production, break-glass documentée.
- Articulation Packer / Terraform / Ansible, OMI durcie, infra déployée, runtime configuré.
Pour aller plus loin
Section intitulée « Pour aller plus loin »- Inventaire dynamique Ansible : Cibler les VMs créées par Terraform à partir de leurs tags, sans maintenir d'inventaire statique.
- Pilier Operational Excellence : Le pipeline IaC comme porte d'entrée des changements, avec tagging contrôlé en CI.
- Pilier Security : Le pattern SG-to-SG, le compte EIM scopé et la journalisation OMS côté pipeline.