Skip to content

Mouaadag/terraform-stack-deploy

Repository files navigation

Deploy a Stack with HCP Terraform

This project demonstrates how to deploy enterprise infrastructure using HCP Terraform Stacks across multiple teams, environments, and AWS regions with advanced orchestration, cost controls, and team isolation. HCP Terraform Stacks help you manage complex infrastructure deployments across multiple environments by providing a different model of infrastructure management from Terraform workspaces.

What are HCP Terraform Stacks?

Instead of loosely coupled workspaces, a Stack consists of a set of components that are organized into one or more deployments, each of which HCP Terraform will provision as a unit. Each of the deployments in your Stack will provision the same Terraform configuration, defined by your Stack's components. A component is a Terraform module, which you can customize with input variables.

Stacks allow you to manage the lifecycle of each of your deployments independently, since changes to one deployment in your Stack do not affect the others. Each deployment in a Stack represents a set of infrastructure that works together, such as a dev, test, or production environment. HCP Terraform will roll out changes to each deployment at a time, and allows you to track changes across your environments.

Key benefits:

  • Components: Terraform modules that can be customized with input variables
  • Deployments: Independent instances representing different environments (dev, test, production)
  • Lifecycle Management: Changes to one deployment don't affect others
  • Rollout Control: Deploy changes to each environment individually
  • Cross-Environment Tracking: Clear visibility of changes across all environments

Stack Architecture

graph TB
    subgraph "Core Infrastructure Stack"
        A[VPC & Networking]
        B[Security Groups]
        C[NAT Gateways]
    end
    
    subgraph "Shared Services Stack"
        D[RDS Database]
        E[Redis Cache]
        F[CloudWatch Logs]
    end
    
    subgraph "Team Stacks"
        G[Customer Team]
        H[Payment Team]
        I[Analytics Team]
    end
    
    A --> D
    A --> G
    A --> H
    A --> I
    D --> G
    D --> H
    D --> I
Loading

Review Components and Deployment

This Terraform Stack consists of multiple components organized into deployment configurations for enterprise-scale infrastructure:

Project Structure

terraform-stack-deploy/
├── LICENSE
├── README.md
├── deployments.tfdeploy.hcl       # Multi-environment deployment configurations
├── components.tfcomponent.hcl     # Stack component definitions
├── providers.tfcomponent.hcl      # Provider configurations with OIDC auth
├── variables.tfcomponent.hcl      # Stack-level variables and team configs
├── outputs.tfcomponent.hcl        # Comprehensive stack outputs
└── stacks/                        # Component source modules
    ├── core-infrastructure/       # VPC, subnets, security groups
    │   ├── main.tf
    │   ├── outputs.tf
    │   └── variables.tf
    ├── shared-services/           # RDS, Redis, monitoring
    │   ├── main.tf
    │   ├── outputs.tf
    │   └── variables.tf
    ├── application-team/          # Team-specific ECS applications
    │   └── (team application modules)
    └── java-app-module/           # Sample Java application module
        └── (Java application infrastructure)

The repository includes Stack configuration files with the extension .tfcomponent.hcl and a deployments file named deployments.tfdeploy.hcl. These configuration files serve as the blueprint for the enterprise infrastructure your Stack will manage across multiple teams and environments.

Prerequisites

This tutorial assumes that you are familiar with the Terraform and HCP Terraform workflows. If you are new to Terraform, complete the Get Started collection first. If you are new to HCP Terraform, complete the HCP Terraform Get Started tutorials first.

In order to complete this tutorial, you will need the following:

  • AWS account with appropriate permissions
  • HCP Terraform account with Stacks enabled for your organization
  • HCP Terraform variable set configured with your AWS credentials
  • Git repository connected to HCP Terraform workspace

Stack Configuration Files

HCP Terraform Stacks use specific file types to define your infrastructure:

Stack Configuration Files (.tfcomponent.hcl)

  • components.tfcomponent.hcl - Defines the components in your Stack
  • providers.tfcomponent.hcl - Configures providers for your Stack
  • variables.tfcomponent.hcl - Defines input variables for your Stack
  • outputs.tfcomponent.hcl - Defines output values from your Stack

Deployment Configuration Files (.tfdeploy.hcl)

  • deployments.tfdeploy.hcl - Defines deployments and their specific configurations

A Terraform Stack is made up of one or more components, each sourced from a Terraform module and configured with inputs and the module's specified providers. HCP Terraform will provision all of these components for each of the deployments in your Stack. Each deployment block defined in .tfdeploy.hcl files represents an independent deployment of this Stack's infrastructure.

Review Stack Components

Provider Configuration

The providers.tfcomponent.hcl file contains provider configurations for your Stack:

required_providers {
  aws = {
    source  = "hashicorp/aws"
    version = "~> 5.7.0"
  }
}

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

  config {
    region = each.value

    assume_role_with_web_identity {
      role_arn           = var.role_arn
      web_identity_token = var.identity_token
    }

    default_tags {
      tags = var.common_tags
    }
  }
}

The required_providers block defines the providers used in this configuration, and uses a syntax similar to the required_providers block nested inside the terraform block in Terraform configuration.

The provider configuration includes:

  • Multiple provider configurations: Using for_each to configure providers for multiple regions
  • OIDC authentication: Using assume_role_with_web_identity for secure authentication
  • Provider labels: The "configurations" label allows multiple configurations of the same provider type

The assume_role_with_web_identity block configures provider authentication to use a JWT identity token managed by trust relationship. Each of your deployments will pass the ARN of your trust relationship's IAM role and a corresponding JWT identity token generated by AWS each time you plan or apply your Stack.

Component Configuration

Components are defined in components.tfcomponent.hcl. This Stack includes enterprise-scale components:

component "core_infrastructure" {
  source = "./stacks/core-infrastructure"
  
  inputs = {
    environment        = var.environment
    aws_region         = var.aws_region
    vpc_cidr          = var.vpc_cidr
    availability_zones = var.availability_zones
    tags              = var.common_tags
  }
  
  providers = {
    aws = provider.aws.main
  }
}

component "shared_services" {
  source = "./stacks/shared-services"
  
  inputs = {
    environment              = var.environment
    aws_region              = var.aws_region
    vpc_id                  = component.core_infrastructure.vpc_id
    private_subnet_ids      = component.core_infrastructure.private_subnet_ids
    application_cidrs       = component.core_infrastructure.application_cidrs
    db_password             = var.db_password
    redis_auth_token        = var.redis_auth_token
    tags                    = var.common_tags
  }
  
  providers = {
    aws = provider.aws.main
  }
  
  depends_on = [component.core_infrastructure]
}

component "customer_team" {
  source = "./stacks/application-team"
  
  inputs = {
    team_name     = "customer-team"
    environment   = var.environment
    aws_region    = var.aws_region
    
    # Network dependencies from core infrastructure
    vpc_id             = component.core_infrastructure.vpc_id
    private_subnet_ids = component.core_infrastructure.private_subnet_ids
    
    # Shared services dependencies
    database_endpoint_ssm_path = component.shared_services.ssm_database_endpoint_path
    redis_endpoint_ssm_path    = component.shared_services.ssm_redis_endpoint_path
    
    # Team-specific configuration
    applications = var.customer_team_applications
    budget_amount = var.customer_team_budget
    tags = var.common_tags
  }
  
  providers = {
    aws = provider.aws.main
  }
  
  depends_on = [component.shared_services]
}

A Stack component includes a Terraform module as a source, input arguments for the module, and the providers that Terraform will use to provision your infrastructure. Each component can also include output values, and components can refer to the output values from other components.

Notice the component dependencies:

  • shared_services depends on core_infrastructure for VPC and networking
  • customer_team (and other teams) depend on shared_services for database and cache endpoints
  • This creates a deployment order: core infrastructure → shared services → application teams

Deployment Configuration

Each deployment represents an instance of all of the components in your Stack, which you customize with the inputs argument. You can use multiple deployments to manage self-contained instances of your Stack's infrastructure, such as development, test, and production environments.

Deployments are defined in deployments.tfdeploy.hcl:

# Identity token for AWS authentication using OIDC
identity_token "aws" {
  audience = ["aws.workload.identity"]
}

deployment "development" {
  inputs = {
    aws_regions    = ["us-east-1"]
    role_arn       = "arn:aws:iam::YOUR_ACCOUNT:role/YOUR_ROLE_NAME"
    identity_token = identity_token.aws.jwt
    common_tags   = { 
      stacks-preview-example = "lambda-component-expansion-stack"
      Project     = "scaling-terraform-stacks"
      Environment = "dev"
    }
    
    environment = "dev"
    aws_region  = "us-east-1"
    vpc_cidr    = "10.0.0.0/16"
    
    # Team configurations
    customer_team_applications = {
      customer_service = {
        app_name = "customer-service"
        # ... additional configuration
      }
    }
    # ... additional team configurations
  }
}

deployment "production" {
  inputs = {
    aws_regions    = ["us-east-1", "us-west-1"]
    role_arn       = "arn:aws:iam::YOUR_ACCOUNT:role/YOUR_ROLE_NAME"
    identity_token = identity_token.aws.jwt
    common_tags   = { 
      stacks-preview-example = "lambda-component-expansion-stack"
      Project     = "scaling-terraform-stacks"
      Environment = "production"
    }
    
    environment = "production"
    aws_region  = "us-east-1"
    vpc_cidr    = "10.1.0.0/16"
    # ... production-specific configuration
  }
}

Each deployment includes:

  • Independent environment: Self-contained instance of your infrastructure
  • Custom inputs: Environment-specific configuration values
  • Regional deployment: Can span multiple AWS regions
  • Team configurations: Isolated resources for different teams
  • OIDC authentication: Secure authentication using identity tokens

Create and Deploy Stack in HCP Terraform

Now that you have configured your Stack with the ARN of your AWS role, create and deploy your Stack.

Create a Project

  1. Log in to HCP Terraform and select the organization you wish to use for this tutorial.

  2. Enable Stacks for your organization by navigating to Settings > General. Ensure that the box next to Stacks is checked, and click the Update organization button.

  3. Create a new project by navigating to Projects, click the + New Project button, name your project (e.g., "Terraform Stacks Demo"), and click the Create button.

  4. Configure Variable Set for your project. Navigate to your organization's Settings > Variable sets page, and select your AWS credentials variable set. Under Variable set scope, select "Apply to specific projects and workspaces", and add your project to the list. Click the Save variable set button.

Provision Identity Token

Your Stack uses a JWT identity token to authenticate the AWS provider. You must first establish an OIDC trust relationship between your AWS account and HCP Terraform, and create an AWS role with the appropriate permissions.

  1. Fork the identity token repository from the HashiCorp tutorial template
  2. Create a workspace in your project to provision identity tokens
  3. Configure the workspace with your organization and project details
  4. Apply the configuration to create your OpenID provider, policy, and role
  5. Copy the role_arn output value for use in your deployments

Create the Stack

  1. In HCP Terraform, navigate to your project and select New > Stack.

  2. Connect to version control by selecting your GitHub account and choosing your repository.

  3. Configure the Stack by leaving the Stack name the same as your repository name, and click Create Stack.

  4. HCP Terraform will load your Stack configuration from your VCS repository.

Provision Infrastructure

Once HCP Terraform loads your configuration, it plans your changes. HCP Terraform plans each deployment separately, and you can choose when to apply each plan.

  1. Review deployments under "Deployments rollout" - HCP Terraform lists your development and production deployments with their current status.

  2. Deploy development environment:

    • Select your development deployment to review the plan
    • Click "Approve plan" to apply the changes
    • Monitor the deployment progress
  3. Deploy production environment:

    • Navigate to your production deployment
    • Review and apply the plan
    • Once complete, your Stack's status will change to "Rolled out"

Add a New Deployment

You can add new deployments by updating your deployments.tfdeploy.hcl file:

deployment "test" {
  inputs = {
    aws_regions    = ["us-east-1", "us-west-1"]
    role_arn       = "arn:aws:iam::YOUR_ACCOUNT:role/YOUR_ROLE_NAME"
    identity_token = identity_token.aws.jwt
    common_tags   = { 
      Environment = "test"
      Project     = "scaling-terraform-stacks"
    }
    
    environment = "test"
    # ... test-specific configuration
  }
}

Commit and push this change to your repository, and HCP Terraform will automatically add the new deployment to your Stack.

Deployment Workflow

Development Environment

# Validate configuration
tfstacks validate

# Plan deployment  
tfstacks plan  \                                                                                         
  -organization="ScalingDemo" \
  -stack="st-<STACK-ID>" \
  -deployment="development"

# Apply through HCP Terraform UI
# (HCP Terraform automatically triggers plan on git push)

Staging Environment

# Validate and plan
tfstacks validate
tfstacks plan  \                                                                                         
  -organization="ScalingDemo" \
  -stack="st-<STACK-ID>" \
  -deployment="staging"

# Apply with manual approval in HCP Terraform
# (Requires approval in HCP Terraform UI)

Production Environment

# Validate and plan with strict controls
tfstacks validate
tfstacks plan  \                                                                                         
  -organization="ScalingDemo" \
  -stack="st-<STACK-ID>" \
  -deployment="Production"
# Apply with senior approval in HCP Terraform
# (Requires multiple approvals in HCP Terraform UI)

Destroy Infrastructure

Before finishing this tutorial, destroy your infrastructure:

  1. Navigate to your Stack's Deployments page, and select each deployment
  2. Navigate to the Destruction and Deletion page and click "Create destroy plan"
  3. Approve the destroy plan to remove your resources
  4. Remove your Stack by navigating to your Stack's Destruction and Deletion page and clicking "Force delete Stack"
  5. Clean up identity token infrastructure by destroying your identity token workspace

Learning Outcomes

This project demonstrates how to:

  • Deploy enterprise infrastructure using HCP Terraform Stacks across multiple environments
  • Manage component dependencies between core infrastructure, shared services, and application teams
  • Use OIDC authentication for secure AWS provider authentication
  • Organize deployments for development, staging, and production environments
  • Scale infrastructure with team-specific configurations and budgets
  • Track changes across multiple environments independently
  • Implement team isolation with separate ECS applications and resource boundaries
  • Manage shared services like RDS databases and Redis cache across teams
  • Apply enterprise governance with cost controls and approval workflows

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages