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. | |
| lifecycle | Controls lifecycle behaviors like creation, update, and destruction. | |
| provider | Defines which provider to use for a resource, enabling orchestration across providers. | |
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 | |
Use for modularizing infrastructure |
| data | Fetches external data for use in configuration | |
Allows referencing external resources |
| output | Exports values from a module or stack | |
Used for inter-stack communication |
| remote state | References state from another Terraform stack | |
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 |
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 initto initialize the working directory - Run
terraform planto generate an execution plan - Review the plan for any unexpected changes
- Run
terraform applyto 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
.tfstatefiles
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.