terraform-stacks

Par hashicorp · agent-skills

Guide complet pour travailler avec HashiCorp Terraform Stacks. À utiliser lors de la création, modification ou validation de configurations Terraform Stack (fichiers `.tfcomponent.hcl`, `.tfdeploy.hcl`), pour travailler avec des composants et déploiements de stack provenant de modules locaux, du registre public ou de registres privés, pour gérer une infrastructure multi-région ou multi-environnement, ou pour résoudre des problèmes de syntaxe et de structure Terraform Stacks.

npx skills add https://github.com/hashicorp/agent-skills --skill terraform-stacks

Terraform Stacks

Terraform Stacks simplifient le provisionnement et la gestion d'infrastructure à grande échelle en fournissant une couche de configuration au-dessus des modules Terraform traditionnels. Les Stacks permettent l'orchestration déclarative de plusieurs composants dans les environnements, régions et comptes cloud.

Concepts fondamentaux

Stack : Une unité complète d'infrastructure composée de composants et de déploiements qui peuvent être gérés ensemble.

Composant : Une abstraction autour d'un module Terraform qui définit les éléments d'infrastructure. Chaque composant spécifie un module source, des entrées et des fournisseurs.

Déploiement : Une instance de tous les composants d'une Stack avec des valeurs d'entrée spécifiques. Utilisez les déploiements pour différents environnements (dev/staging/prod), régions ou comptes cloud.

Langage Stack : Un langage basé sur HCL distinct (pas le HCL Terraform standard) avec des blocs et des extensions de fichier distincts.

Structure de fichier

Terraform Stacks utilisent des extensions de fichier spécifiques :

  • Configuration de composant : .tfcomponent.hcl
  • Configuration de déploiement : .tfdeploy.hcl
  • Fichier de verrouillage du fournisseur : .terraform.lock.hcl (généré par la CLI)

Tous les fichiers de configuration doivent être au niveau racine du dépôt Stack. HCP Terraform traite tous les fichiers dans l'ordre des dépendances.

Organisation de fichier recommandée

my-stack/
├── .terraform-version               # La version Terraform requise pour cette Stack
├── variables.tfcomponent.hcl        # Déclarations de variables
├── providers.tfcomponent.hcl        # Configurations des fournisseurs
├── components.tfcomponent.hcl       # Définitions des composants
├── outputs.tfcomponent.hcl          # Sorties de Stack
├── deployments.tfdeploy.hcl         # Définitions de déploiement
├── .terraform.lock.hcl              # Fichier de verrouillage du fournisseur (généré)
└── modules/                         # Modules locaux (optionnel - uniquement si vous utilisez des modules locaux)
    ├── s3/
    └── compute/

Remarque : Le répertoire modules/ est nécessaire uniquement lors de l'utilisation de sources de modules locaux. Les composants peuvent faire référence à des modules à partir de :

  • Chemins de fichier locaux : ./modules/vpc
  • Registre public : terraform-aws-modules/vpc/aws
  • Registre privé : app.terraform.io/<org-name>/vpc/aws
  • Git : git::https://github.com/org/repo.git//path?ref=v1.0.0

HCP Terraform traite tous les fichiers .tfcomponent.hcl et .tfdeploy.hcl dans l'ordre des dépendances.

Version Terraform requise (.terraform-version)

Utilisez Terraform v1.13.x ou ultérieur pour accéder au plugin CLI Stacks et exécuter les commandes terraform stacks CLI. Commencez par ajouter un fichier .terraform-version au répertoire racine de votre Stack pour spécifier la version Terraform requise pour votre Stack. Par exemple, le fichier suivant spécifie Terraform v1.14.5 :

1.14.5

Configuration de composant (.tfcomponent.hcl)

Bloc Variable

Déclarez les variables d'entrée pour la configuration Stack. Les variables doivent définir un champ type et ne supportent pas l'argument validation.

variable "aws_region" {
  type        = string
  description = "AWS region for deployments"
  default     = "us-west-1"
}

variable "identity_token" {
  type        = string
  description = "OIDC identity token"
  ephemeral   = true  # Does not persist to state file
}

variable "instance_count" {
  type     = number
  nullable = false
}

Important : Utilisez ephemeral = true pour les identifiants et jetons (jetons d'identité, clés API, mots de passe) pour les empêcher de persister dans les fichiers d'état. Utilisez stable pour les valeurs de longue durée comme les clés de licence qui doivent persister entre les exécutions.

Bloc required_providers

required_providers {
  aws = {
    source  = "hashicorp/aws"
    version = "~> 6.0"
  }
  random = {
    source  = "hashicorp/random"
    version = "~> 3.5.0"
  }
}

Bloc Provider

Les blocs Provider diffèrent de Terraform traditionnel :

  1. Supportent l'argument méta for_each
  2. Définissent les alias dans l'en-tête de bloc (pas en tant qu'argument)
  3. Acceptent la configuration via un bloc config

Configuration de fournisseur unique :

provider "aws" "this" {
  config {
    region = var.aws_region
    assume_role_with_web_identity {
      role_arn           = var.role_arn
      web_identity_token = var.identity_token
    }
  }
}

Configurations de fournisseur multiples avec for_each :

provider "aws" "configurations" {
  for_each = var.regions

  config {
    region = each.value
    assume_role_with_web_identity {
      role_arn           = var.role_arn
      web_identity_token = var.identity_token
    }
  }
}

Bonne pratique d'authentification : Utilisez l'identité de charge de travail (OIDC) comme méthode d'authentification préférée pour les Stacks. Cette approche :

  • Évite les identifiants statiques de longue durée
  • Fournit des identifiants temporaires et délimités par déploiement
  • S'intègre avec IAM du fournisseur cloud (AWS IAM Roles, Azure Managed Identities, GCP Service Accounts)
  • Élimine le besoin de variables d'environnement gérées par la plateforme

Configurez l'identité de charge de travail en utilisant les blocs identity_token et assume_role_with_web_identity dans la configuration du fournisseur. Pour des instructions de configuration détaillées pour AWS, Azure et GCP, voir : https://developer.hashicorp.com/terraform/cloud-docs/dynamic-provider-credentials

Bloc Component

Chaque Stack nécessite au moins un bloc component. Ajoutez un composant pour chaque module à inclure dans la Stack. Les composants référencent les modules à partir de chemins locaux, de registres ou de Git.

component "vpc" {
  source  = "app.terraform.io/my-org/vpc/aws"  # Local, registry, or Git URL
  version = "2.1.0"          # For registry modules

  inputs = {
    cidr_block  = var.vpc_cidr
    name_prefix = var.name_prefix
  }

  providers = {
    aws = provider.aws.this
  }
}

Voir references/component-blocks.md pour des exemples de dépendances, for_each, modules de registre public, sources Git, et plus.

Points clés :

  • Références de sortie : component.<name>.<output> ou component.<name>[key].<output> pour for_each
  • Dépendances déduites automatiquement à partir des références de composants
  • Agrégation avec les expressions for : [for x in component.s3 : x.bucket_name]
  • Pour les composants avec for_each, référencez les instances spécifiques : component.<name>[each.value].<output>
  • Les références de fournisseur sont des valeurs normales : provider.<type>.<alias> ou provider.<type>.<alias>[each.value]

Bloc Output

Les sorties nécessitent un argument type et ne supportent pas les preconditions :

output "vpc_id" {
  type        = string
  description = "VPC ID"
  value       = component.vpc.vpc_id
}

output "endpoint_urls" {
  type      = map(string)
  value     = {
    for region, comp in component.api : region => comp.endpoint_url
  }
  sensitive = false
}

Bloc Locals

Les blocs Locals fonctionnent de la même manière dans les fichiers .tfcomponent.hcl et .tfdeploy.hcl :

locals {
  common_tags = {
    Environment = var.environment
    ManagedBy   = "Terraform Stacks"
    Project     = var.project_name
  }

  region_config = {
    for region in var.regions : region => {
      name_suffix = "${var.environment}-${region}"
    }
  }
}

Bloc Removed

Utilisez pour supprimer en toute sécurité des composants d'une Stack. HCP Terraform nécessite les fournisseurs du composant pour le supprimer.

removed {
  from   = component.old_component
  source = "./modules/old-module"

  providers = {
    aws = provider.aws.this
  }
}

Configuration de déploiement (.tfdeploy.hcl)

Bloc Identity Token

Générez les jetons JWT pour l'authentification OIDC avec les fournisseurs cloud :

identity_token "aws" {
  audience = ["aws.workload.identity"]
}

identity_token "azure" {
  audience = ["api://AzureADTokenExchange"]
}

Référencez les jetons dans les déploiements en utilisant identity_token.<name>.jwt

Bloc Store

Accédez aux ensembles de variables HCP Terraform dans les déploiements Stack :

store "varset" "aws_credentials" {
  id       = "varset-ABC123"  # Alternatively use: name = "varset_name"
  source   = "tfc-cloud-shared"
  category = "terraform"      # Alternatively use: category = "env" for environment variables
}

deployment "production" {
  inputs = {
    aws_access_key = store.varset.aws_credentials.AWS_ACCESS_KEY_ID
  }
}

Utilisez pour centraliser les identifiants et partager les variables entre les Stacks. Voir references/deployment-blocks.md pour les détails.

Bloc Deployment

Définissez les instances de déploiement (minimum 1, maximum 20 par Stack) :

deployment "production" {
  inputs = {
    aws_region     = "us-west-1"
    instance_count = 3
    role_arn       = local.role_arn
    identity_token = identity_token.aws.jwt
  }
}

# Create multiple deployments for different environments
deployment "development" {
  inputs = {
    aws_region     = "us-east-1"
    instance_count = 1
    name_suffix    = "dev"
    role_arn       = local.role_arn
    identity_token = identity_token.aws.jwt
  }
}

Pour détruire un déploiement : Définissez destroy = true, téléchargez la configuration, approuvez la destruction, puis supprimez le bloc de déploiement. Voir references/deployment-blocks.md pour les détails.

Bloc Deployment Group

Regroupez les déploiements pour des paramètres partagés (fonctionnalité de niveau HCP Terraform Premium). Les niveaux Free/Standard utilisent des groupes par défaut nommés {deployment-name}_default.

deployment_group "canary" {
  auto_approve_checks = [deployment_auto_approve.safe_changes]
}

deployment "dev" {
  inputs = { /* ... */ }
  deployment_group = deployment_group.canary
}

Plusieurs déploiements peuvent référencer le même groupe. Voir references/deployment-blocks.md pour les détails.

Bloc Deployment Auto-Approve

Définissez les règles pour approuver automatiquement les plans de déploiement (fonctionnalité de niveau HCP Terraform Premium) :

deployment_auto_approve "safe_changes" {
  deployment_group = deployment_group.canary

  check {
    condition = context.plan.changes.remove == 0
    reason    = "Cannot auto-approve plans with resource deletions"
  }
}

Variables de contexte disponibles : context.plan.applyable, context.plan.changes.add/change/remove/total, context.success

Remarque : Les blocs orchestrate sont obsolètes. Utilisez plutôt deployment_group et deployment_auto_approve.

Voir references/deployment-blocks.md pour toutes les variables de contexte et les modèles.

Blocs Publish Output et Upstream Input

Liez les Stacks ensemble en publiant les sorties d'une Stack et en les consommant dans une autre :

# In network Stack - publish outputs
publish_output "vpc_id_network" {
  type  = string
  value = deployment.network.vpc_id
}

# In application Stack - consume outputs
upstream_input "network_stack" {
  type   = "stack"
  source = "app.terraform.io/my-org/my-project/networking-stack"
}

deployment "app" {
  inputs = {
    vpc_id = upstream_input.network_stack.vpc_id_network
  }
}

Voir references/linked-stacks.md pour la documentation complète et les exemples.

Terraform Stacks CLI

Remarque : Terraform Stacks est en disponibilité générale (GA) depuis Terraform CLI v1.13+. Les Stacks comptent maintenant pour les ressources sous gestion (RUM) pour la facturation HCP Terraform.

Initialiser et valider

terraform stacks init              # Download providers, modules, generate lock file
terraform stacks providers-lock    # Regenerate lock file (add platforms if needed)
terraform stacks validate          # Check syntax without uploading

Workflow de déploiement

Important : Aucune commande plan ou apply. Le téléchargement de la configuration déclenche automatiquement les exécutions de déploiement.

# 1. Upload configuration (triggers deployment runs)
terraform stacks configuration upload

# 2. Monitor deployments
terraform stacks deployment-run list                          # List runs (non-interactive)
terraform stacks deployment-group watch -deployment-group=... # Stream status updates

# 3. Approve deployments (if auto-approve not configured)
terraform stacks deployment-run approve-all-plans -deployment-run-id=...
terraform stacks deployment-group approve-all-plans -deployment-group=...
terraform stacks deployment-run cancel -deployment-run-id=...  # Cancel if needed

Gestion de la configuration

terraform stacks configuration list                    # List configuration versions
terraform stacks configuration fetch -configuration-id=...  # Download configuration
terraform stacks configuration watch                   # Monitor upload status

Autres commandes

terraform stacks create              # Create new Stack (interactive)
terraform stacks fmt                 # Format Stack files
terraform stacks list                # Show all Stacks
terraform stacks version             # Display version
terraform stacks deployment-group rerun -deployment-group=...  # Rerun deployment

Monitoring des déploiements avec l'API HCP Terraform

Pour le monitoring programmatique dans l'automatisation, CI/CD ou les environnements non interactifs (comme les agents IA), utilisez l'API HCP Terraform au lieu des commandes CLI watch. L'API fournit des endpoints pour :

  • Statut et validation de la configuration
  • Résumés des groupes de déploiement
  • Statut des exécutions de déploiement
  • Détails des étapes de déploiement (plan/apply)
  • Diagnostics d'erreur avec emplacements de fichier et extraits de code
  • Sorties Stack via endpoint d'artefacts

Points clés :

  • Les commandes CLI watch font du streaming indéfiniment et ne fonctionnent pas dans l'automatisation
  • Utilisez l'endpoint d'artefacts pour récupérer les sorties Stack : GET /api/v2/stack-deployment-steps/{step-id}/artifacts?name=apply-description
  • L'endpoint diagnostics nécessite le paramètre de requête stack_deployment_step_id
  • L'endpoint d'artefacts retourne une redirection HTTP 307 (utilisez curl -L)

Pour le workflow API complet, l'authentification, les meilleures pratiques de polling et les exemples de scripts, voir references/api-monitoring.md.

Modèles courants

Dépendances de composants : Les dépendances sont automatiquement déduites quand un composant référence la sortie d'un autre (par ex. subnet_ids = component.vpc.private_subnet_ids).

Déploiement multi-régions : Utilisez for_each sur les fournisseurs et les composants pour déployer sur plusieurs régions. Chaque région obtient sa propre configuration de fournisseur et ses instances de composants.

Modifications différées : Les Stacks supportent les modifications différées pour gérer les dépendances où les valeurs ne sont connues qu'après l'apply. Cela permet les déploiements complexes multi-composants où certaines ressources dépendent de valeurs d'exécution d'autres composants (endpoints de cluster, mots de passe générés, etc.).

Pour les exemples complets incluant les déploiements multi-régions, les dépendances de composants, les modèles de modifications différées et les Stacks liées, voir references/examples.md.

Bonnes pratiques

  1. Granularité des composants : Créez des composants pour les unités d'infrastructure logiques qui partagent un cycle de vie
  2. Compatibilité des modules :
    • Les modules utilisés avec les Stacks ne peuvent pas inclure de blocs provider (configurez les fournisseurs dans la configuration Stack)
    • Testez les modules du registre public avant de les utiliser dans les Stacks de production - certains modules peuvent avoir des problèmes de compatibilité
    • Envisagez d'utiliser des ressources brutes pour l'infrastructure critique si la compatibilité des modules est incertaine
    • Exemple : Certaines versions de terraform-aws-modules ont été trouvées avec des problèmes de compatibilité avec les Stacks (par ex. modules ALB et ECS)
  3. Isolation d'état : Chaque déploiement a son propre état isolé
  4. Variables d'entrée : Utilisez les variables pour les valeurs qui diffèrent entre les déploiements ; utilisez les locals pour les valeurs partagées
  5. Fichiers de verrouillage du fournisseur : Générez toujours et committez .terraform.lock.hcl au contrôle de version
  6. Conventions de nommage : Utilisez des noms descriptifs pour les composants et les déploiements
  7. Groupes de déploiement : Vous pouvez organiser les déploiements en groupes de déploiement. Les groupes de déploiement permettent les règles d'approbation automatique, l'organisation logique et fournissent une base pour la scalabilité. Les groupes de déploiement sont une fonctionnalité de niveau HCP Terraform Premium
  8. Tests : Testez les configurations Stack dans les déploiements dev/staging avant la production

Dépannage

Dépendances circulaires : Refactorisez pour briser les références circulaires ou utilisez des composants intermédiaires.

Destruction de déploiement : Impossible de détruire depuis l'UI. Définissez destroy = true dans le bloc de déploiement, téléchargez la configuration et HCP Terraform crée une destruction.

Diagnostics vides : Ajoutez le paramètre de requête requis stack_deployment_step_id aux requêtes de l'API diagnostics.

Compatibilité des modules : Testez les modules du registre public avant une utilisation en production. Certains modules peuvent avoir des problèmes de compatibilité avec les Stacks.

Références

Pour la documentation détaillée, voir :

  • references/component-blocks.md - Référence complète du bloc component avec tous les arguments et la syntaxe
  • references/deployment-blocks.md - Référence complète du bloc deployment avec toutes les options de configuration
  • references/linked-stacks.md - Publier les sorties et les entrées upstream pour lier les Stacks ensemble
  • references/examples.md - Exemples de travail complets pour les déploiements multi-régions et les dépendances de composants
  • references/api-monitoring.md - Workflow API complet pour le monitoring programmatique et l'automatisation
  • references/troubleshooting.md - Guide de dépannage détaillé pour les problèmes courants et les solutions

Skills similaires