Workflow core 01
Le cycle quotidien.
terraform initinit backend + providersterraform init -upgrademettre à jour les providersterraform init -reconfigurereconfigurer le backendterraform init -migrate-statemigrer l'état vers un autre backendterraform planprévoir les changementsterraform plan -out=plan.binsauvegarder le planterraform plan -target=<addr>cibler une ressourceterraform plan -var='k=v'variable inlineterraform plan -var-file=prod.tfvarsfichier de variablesterraform applyappliquer (confirmation)terraform apply plan.binappliquer un plan sauvegardéterraform apply -auto-approvesans confirmation (CI)terraform apply -replace=<addr>remplacer (ex-taint)terraform destroytout détruireterraform destroy -target=<addr>détruire une ressourceValidation · Format 02
Qualité du code avant commit.
terraform fmtformatter le dossierterraform fmt -recursivesous-dossiers inclusterraform fmt -check -diffvérif (CI), diffterraform validatevérif syntaxiqueterraform validate -jsonsortie JSONterraform providersarbre des providersterraform providers lockverrouiller hashes multi-OSterraform versionversion CLI + providerstflintlinter (externe, recommandé)tfsec · trivyaudit sécurité (externe)Output · Console 03
Lire l'état sans apply.
terraform outputtous les outputsterraform output <name>output précisterraform output -raw <name>sans guillemetsterraform output -jsonformat JSONterraform consoleREPL HCL sur l'étatterraform graphgraphe DOT des dépendancesterraform showétat en lecture humaineterraform show -jsonétat JSONterraform show plan.bininspecter un plan binaireState management 04
Toucher l'état — avec précaution.
terraform state listadresses géréesterraform state list module.xdans un moduleterraform state show <addr>détails d'une ressourceterraform state pulldump du state distantterraform state pushpousser un state localterraform state mv A Brenommer / déplacerterraform state rm <addr>retirer du state (pas du cloud)terraform state replace-provider <old> <new>switch de providerterraform force-unlock <ID>casser un lock bloquéterraform refreshresync (déprécié, utiliser plan -refresh-only)terraform plan -refresh-onlyresync en planImport · Taint · Replace 05
Absorber ou recréer une ressource.
terraform import <addr> <id>adopter une resourceterraform plan -generate-config-out=gen.tfbloc import → génère HCLterraform apply -replace=<addr>force la recréationterraform taint <addr>⚠ déprécié (utiliser -replace)terraform untaint <addr>annuler un taint legacy# Bloc import (TF ≥ 1.5)
import { to = aws_s3_bucket.logs id = "my-bucket" }
Workspaces 06
Isolations d'états légers.
terraform workspace listworkspaces disponiblesterraform workspace showworkspace courantterraform workspace new <n>créerterraform workspace select <n>basculerterraform workspace delete <n>supprimer# Dans le HCL
name = "app-${terraform.workspace}"
⚠ Pour des environnements lourds (prod vs stg), préférer des dossiers séparés avec des backends distincts.
Variables 07
Priorité (haut → bas gagne).
1. -var / -var-file (CLI) 2. *.auto.tfvars[.json] 3. terraform.tfvars[.json] 4. TF_VAR_<name> # env 5. default # dans le bloc variable
# Déclaration
variable "region" { type = string default = "eu-west-3" validation { condition = contains(["eu-west-3","eu-west-1"], var.region) error_message = "Region non supportée" } }
# Types composés
list(string) · set(string)
map(string) · object({ a=string, b=number })
tuple([string, number])
Modules 08
Composer plutôt que copier.
module "vpc" { source = "terraform-aws-modules/vpc/aws" version = "5.5.0" name = "prod" cidr = "10.0.0.0/16" }
# Sources possibles
"./modules/app" # local "github.com/ns/repo//path?ref=v1" # git "git::ssh://git@host/repo.git" # SSH "s3::https://…/mod.zip" # archive "ns/mod/aws" # registry
terraform gettélécharger les modulesterraform get -updateforcer la mise à jourMeta-arguments 09
Modifient le comportement d'un bloc.
countN instances d'une ressourcefor_eachmap/set → instances nomméesdepends_ondépendance expliciteprovideralias de providerlifecyclecreate_before_destroy / prevent_destroy / ignore_changes# Boucle for_each
resource "aws_iam_user" "u" { for_each = toset(["alice","bob"]) name = each.key }
# Lifecycle
lifecycle { create_before_destroy = true prevent_destroy = true ignore_changes = [tags["last_deploy"]] }
Fonctions utiles 10
Les plus rentables au quotidien.
concat(a,b)concat listesmerge(a,b)fusion de mapslookup(m,k,def)map get avec défautcoalesce(a,b,c)1er non-nulltry(expr, def)fallback si erreurlength(x)taille liste/map/stringjsonencode · jsondecodeJSON ↔ HCLyamlencode · yamldecodeYAML ↔ HCLfile("path")lire un fichiertemplatefile("t.tpl", {})templatingformat("%s-%d", n, i)printf-likejoin("-", list)joinsplit("/", s)splitcidrsubnet · cidrhostarithmétique CIDRbase64encode · base64decodeencodingsha256 · md5 · uuidhash / idtimestamp() · formatdate(…)datesDebug · Logs 11
Variables d'environnement qui sauvent.
TF_LOG=DEBUG # TRACE, DEBUG, INFO, WARN, ERROR TF_LOG_PATH=tf.log TF_LOG_CORE=TRACE TF_LOG_PROVIDER=DEBUG TF_INPUT=0 # pas d'input interactif TF_IN_AUTOMATION=1 # sortie condensée (CI) TF_CLI_ARGS_plan="-parallelism=30" TF_DATA_DIR=./.tf # déplacer .terraform/ TF_PLUGIN_CACHE_DIR=~/.tf/cache
terraform plan -parallelism=1linéariser pour tracer une erreurterraform consoleinspecter une expressionBackends remote 12
Stockage de l'état partagé.
terraform { required_version = ">= 1.7" backend "s3" { bucket = "my-tfstate" key = "prod/terraform.tfstate" region = "eu-west-3" encrypt = true dynamodb_table = "tf-locks" } required_providers { aws = { source = "hashicorp/aws" version = "~> 5.0" } } }
# Autres backends courants
backend "gcs" { bucket = "…" } backend "azurerm" { …storage_account } backend "remote" { hostname = "app.terraform.io" } backend "http" { address = "…" }
CLI flags utiles 13
Transverses à plan/apply/destroy.
-target=<addr>cibler (debug only)-replace=<addr>forcer la recréation-refresh=falseskip refresh-lock=falsedésactiver le lock (risqué)-parallelism=Nnb de workers (def. 10)-input=falsepas d'interactif-no-colorsortie sans ANSI-jsonsortie structurée (CI)-detailed-exitcode0=no change · 2=diff