Skip to main content

Using Terraform Stacks

1. Understanding Terraform Stacks

Aspect Description Notes
Stack Definition Collection of Terraform configurations that manage a set of resources Stacks help organize and manage infrastructure as code
Modularity Each stack can contain one or more modules Modules encapsulate reusable infrastructure components
State Management Each stack maintains its own state file (e.g., terraform.tfstate) State files are used to track resource metadata and dependencies
Resource Isolation Resources in one stack do not directly affect others Enables better control and separation of concerns
Configuration Hierarchy Stacks can reference other stacks or modules via module blocks Allows composition and reuse across different infrastructure layers

Example: Basic Stack Structure

stacks/
├── vpc/
│   ├── main.tf
│   └── variables.tf
├── web-app/
│   ├── main.tf
│   └── outputs.tf
└── terraform.tfvars
Note: Terraform stacks are not a built-in feature but rather an organizational pattern using modules and workspaces.

Stacks vs Workspaces

  • Stacks: Logical grouping of configurations, often managed with separate directories or state files
  • Workspaces: Isolated environments within a single Terraform configuration

2. Creating Stack Configuration

Property Description Example
stack.name Name of the stack "production-api"
stack.environment Environment type (e.g., dev, staging, prod) "production"
stack.dependencies List of other stacks this stack depends on ["shared-vpc", "monitoring"]
stack.variables Input variables for the stack { "instance_type": "t3.medium" }

Example: Stack Configuration File

{
  "name": "production-api",
  "environment": "production",
  "dependencies": [
    "shared-vpc",
    "monitoring"
  ],
  "variables": {
    "instance_type": "t3.medium",
    "ami_id": "ami-12345678"
  }
}

3. Defining Stack Deployments

Property Description Example
stacks List of stack configurations to deploy ["prod", "staging"]
deployment.target Target environment for the stack "aws"
deployment.region Region to deploy resources in "us-west-2"

Example: Defining a Stack Deployment

stacks = ["prod", "staging"]

deployment "prod" {
  target = "aws"
  region = "us-west-2"
}

deployment "staging" {
  target = "aws"
  region = "us-east-1"
}
Note: Stack deployments are defined in a stacks.tf file or within the root module.

4. Using Orchestration Rules

Terraform stacks can be orchestrated using rules that define dependencies, execution order, and resource relationships. These rules ensure that resources are created, updated, or destroyed in the correct sequence.

Rule Type Description Example
depends_on Ensures a resource is created after another resource.
resource "aws_instance" "web" {
  depends_on = [aws_instance.db]
}
lifecycle Controls lifecycle behaviors like creation, update, and destruction.
lifecycle {
  ignore_changes = [tags]
}
provider Defines which provider to use for a resource, enabling orchestration across providers.
resource "aws_s3_bucket" "example" {
  provider = aws.us_west_2
}

Example: Orchestration with depends_on

resource "aws_vpc" "main" {
  cidr_block = "10.0.0.0/16"
}

resource "aws_subnet" "main" {
  depends_on = [aws_vpc.main]
  vpc_id     = aws_vpc.main.id
  cidr_block = "10.0.1.0/24"
}
Note: Orchestration rules in Terraform are declarative, meaning you define the desired state and dependencies, not the steps to achieve it.

5. Managing Stack Dependencies

Dependency Type Description Usage Notes
module References another module as a dependency
module "vpc" {
  source = "./modules/vpc"
}
Use for modularizing infrastructure
data Fetches external data for use in configuration
data "aws_ami" "latest" {
  most_recent = true
  filter {
    name   = "name"
    values = ["ubuntu/images/ubuntu-20.04/*"]
  }
}
Allows referencing external resources
output Exports values from a module or stack
output "vpc_id" {
  value = aws_vpc.main.id
}
Used for inter-stack communication
remote state References state from another Terraform stack
data "terraform_remote_state" "shared" {
  backend = "s3"
  config = {
    bucket = "my-terraform-state"
    key    = "shared/terraform.tfstate"
  }
}
Enables cross-stack references

Example: Using remote state to reference another stack

data "terraform_remote_state" "vpc" {
  backend = "s3"
  config = {
    bucket = "my-terraform-state"
    key    = "vpc/terraform.tfstate"
  }
}

resource "aws_security_group" "allow_http" {
  vpc_id = data.terraform_remote_state.vpc.outputs.vpc_id
  ingress {
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }
}
Note: Dependencies between stacks are managed through Terraform's state and module system. Ensure proper state locking and versioning to avoid conflicts.

6. Using Stack Variables

Variable Type Description Default Value
stack_name string Name of the stack "default-stack"
environment string Environment type (dev, staging, prod) "dev"
region string AWS region to deploy resources "us-east-1"
instance_type string EC2 instance type for the stack "t3.micro"

Example: Defining Stack Variables in HCL

variable "stack_name" {
  type = string
  default = "default-stack"
}

variable "environment" {
  type = string
  default = "dev"
}

variable "region" {
  type = string
  default = "us-east-1"
}

variable "instance_type" {
  type = string
  default = "t3.micro"
}

Example: Using Stack Variables in Resource Configuration

resource "aws_instance" "web_server" {
  ami           = "ami-0c55b159cbfafe1d0"
  instance_type = var.instance_type
  region        = var.region

  tags = {
    Name        = "${var.stack_name}-web-server"
    Environment = var.environment
  }
}

7. Implementing Stack Outputs

Output Name Type Description Usage
output.name string Name of the output variable Used to reference this output in parent stacks or modules
output.value any Value to be exposed by the output Can be a string, number, list, or map
output.sensitive boolean Flag to mark output as sensitive Prevents the value from being displayed in logs or console

Example: Defining Stack Outputs

output "vpc_id" {
  value = aws_vpc.main.id
}

output "public_subnet_ids" {
  value = aws_subnet.public.*.id
}

output "database_password" {
  value = aws_db_instance.main.password
  sensitive = true
}
Note: Outputs are evaluated after the plan and apply phases, so they can reference resources created during the apply phase.

Example: Using Outputs in Parent Stacks

module "network" {
  source = "./network-stack"
}

module "web" {
  source = "./web-stack"
  vpc_id = module.network.vpc_id
}

8. Deploying Stacks

Command Description Notes
terraform init Initializes a Terraform working directory Must be run before any other commands
terraform plan Generates and displays an execution plan Shows what changes will be made to infrastructure
terraform apply Applies the changes required to reach a desired state Executes the plan and creates/updates resources
terraform destroy Destroys the Terraform-managed infrastructure Removes all resources managed by the stack

Example: Deploying a Stack

terraform init
terraform plan -out=tfplan
terraform apply tfplan
Note: The -out flag in terraform plan saves the plan to a file for later use with terraform apply. This is useful for review and approval processes.
Warning: Running terraform apply without review can lead to unintended infrastructure changes. Always verify the plan before applying.

Deployment Workflow

  • Run terraform init to initialize the working directory
  • Run terraform plan to generate an execution plan
  • Review the plan for any unexpected changes
  • Run terraform apply to execute the plan and deploy resources

9. Managing Stack State

Property Description Default Notes
backend Defines where Terraform stores its state file local Can be remote, s3, gcs, etc.
workspace Name of the current workspace default Each workspace has its own state file

Example: Configure S3 Backend

terraform {
  backend "s3" {
    bucket = "my-terraform-state"
    key    = "prod/terraform.tfstate"
    region = "us-west-2"
  }
}
Note: State files can become locked during operations. Use terraform state list to inspect current state.
Warning: Never commit backend configuration secrets to version control. Use terraform.tfvars or environment variables.

State Management Best Practices

  • Use remote backends (e.g. S3, GCS) for team collaboration
  • Enable state locking to prevent concurrent modifications
  • Regularly backup state files
  • Avoid manual edits to .tfstate files

10. Using Stacks with Terraform Cloud

Property Description Values
stacks.enabled Enables or disables stacks functionality true / false
stacks.workspace Workspace name for stack deployment string
stacks.organization Terraform Cloud organization name string

Example: Enabling Stacks in Terraform Cloud

terraform {
  cloud {
    organization = "myorg"
    workspaces {
      name = "my-stack"
    }
  }
}
Note: Stacks in Terraform Cloud require a terraform cloud block with organization and workspace defined.
Warning: Ensure that the organization and workspace names match exactly in your Terraform Cloud settings.

Stacks with Terraform Cloud Summary

  • Stacks allow for modular composition of infrastructure
  • Requires Terraform Cloud integration
  • Organization and workspace must be configured correctly

Was this article helpful?