Skip to main content

Terraform Team Collaboration

Introduction

When working with Terraform in a team environment, collaboration becomes crucial for maintaining consistent, reliable infrastructure. While Terraform is powerful for individual use, it truly shines when teams collaborate effectively to manage infrastructure as code. This guide explores best practices for Terraform team collaboration, helping you transition from solo development to efficient team workflows.

Terraform team collaboration involves:

  • Sharing and managing Terraform state
  • Organizing code for multiple contributors
  • Establishing consistent workflows and standards
  • Implementing proper version control practices
  • Setting up collaboration tools and processes

Let's dive into how you can set up your team for success with Terraform.

State Management in Team Environments

Remote State Storage

When working alone, local state files might suffice. In a team environment, remote state storage becomes essential.

hcl
terraform {
backend "s3" {
bucket = "my-terraform-state"
key = "prod/terraform.tfstate"
region = "us-west-2"
dynamodb_table = "terraform-locks"
encrypt = true
}
}

This configuration:

  • Stores state in an S3 bucket
  • Uses DynamoDB for state locking
  • Encrypts the state file for security

State Locking

State locking prevents concurrent modifications that could corrupt your infrastructure state.

hcl
terraform {
backend "azurerm" {
resource_group_name = "tfstate"
storage_account_name = "tfstate1234"
container_name = "tfstate"
key = "prod.terraform.tfstate"
}
}

Output when another team member tries to apply changes simultaneously:

Error: Error locking state: Error acquiring the state lock: storage: service returned error: 
StatusCode=409, ErrorCode=LeaseAlreadyPresent, ErrorMessage=There is already a lease present.

Workspace Isolation

Use workspaces to isolate different environments or team projects:

bash
# Create and switch to a new workspace
terraform workspace new dev-feature-x

# List available workspaces
terraform workspace list

# Select a workspace
terraform workspace select dev-feature-x

Code Organization for Team Collaboration

Module Sharing

Create shared modules for common infrastructure patterns:

project-root/
├── modules/
│ ├── networking/
│ │ ├── main.tf
│ │ ├── variables.tf
│ │ └── outputs.tf
│ └── database/
│ ├── main.tf
│ ├── variables.tf
│ └── outputs.tf
├── prod/
│ ├── main.tf
│ └── terraform.tfvars
└── dev/
├── main.tf
└── terraform.tfvars

Example module usage:

hcl
module "vpc" {
source = "../modules/networking"

vpc_cidr = "10.0.0.0/16"
environment = "production"
}

Repository Structure

Organize repositories to support team collaboration:

Workflow Standardization

Terraform Version Control

Use .terraform-version files to standardize Terraform versions across team members:

# .terraform-version
1.5.4

Combined with tools like tfenv, this ensures consistent Terraform versions.

Pre-commit Hooks

Implement pre-commit hooks to maintain code quality:

yaml
# .pre-commit-config.yaml
repos:
- repo: https://github.com/antonbabenko/pre-commit-terraform
rev: v1.77.1
hooks:
- id: terraform_fmt
- id: terraform_docs
- id: terraform_tflint
- id: terraform_validate

This configuration:

  • Formats Terraform code consistently
  • Updates documentation automatically
  • Performs static analysis
  • Validates Terraform configurations

Documentation Standards

Standardize documentation for modules:

hcl
/**
* # Networking Module
*
* This module creates a standard VPC with public and private subnets.
*
* ## Usage
* ```hcl
* module "vpc" {
* source = "./modules/networking"
* vpc_cidr = "10.0.0.0/16"
* }
* ```
*/

variable "vpc_cidr" {
description = "CIDR block for the VPC"
type = string
}

Collaborative Development Practices

Pull Request Workflow

Implement a pull request workflow for Terraform changes:

  1. Create a feature branch
  2. Make infrastructure changes
  3. Run terraform plan and commit the plan output
  4. Open a pull request with the plan output
  5. Review the plan as a team
  6. Merge and apply changes

Example plan output to include in PR description:

Terraform will perform the following actions:

# aws_instance.example will be created
+ resource "aws_instance" "example" {
+ ami = "ami-0c55b159cbfafe1f0"
+ instance_type = "t2.micro"
+ vpc_security_group_ids = [
+ "sg-12345678",
]
# ... other attributes
}

Plan: 1 to add, 0 to change, 0 to destroy.

CI/CD Integration

Integrate Terraform with CI/CD pipelines:

yaml
# .github/workflows/terraform.yml
name: "Terraform"

on:
push:
branches: [ main ]
pull_request:

jobs:
terraform:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3

- name: Setup Terraform
uses: hashicorp/setup-terraform@v2

- name: Terraform Format
run: terraform fmt -check

- name: Terraform Init
run: terraform init

- name: Terraform Validate
run: terraform validate

- name: Terraform Plan
run: terraform plan -no-color
if: github.event_name == 'pull_request'

Managing Secrets and Variables

Variable Hierarchy

Implement a variable hierarchy to manage environment-specific values:

project/
├── terraform.tfvars # Common variables
├── prod.tfvars # Production overrides
├── staging.tfvars # Staging overrides
└── dev.tfvars # Development overrides

Example variable file:

hcl
# terraform.tfvars - Common variables
region = "us-west-2"
instance_type = "t2.micro"

# prod.tfvars - Production overrides
instance_type = "t2.large"
high_availability = true

Secret Management

Use secure methods to manage sensitive variables:

hcl
# Using environment variables
provider "aws" {
region = var.region
access_key = var.aws_access_key
secret_key = var.aws_secret_key
}
bash
# Export secrets as environment variables
export TF_VAR_aws_access_key="AKIAIOSFODNN7EXAMPLE"
export TF_VAR_aws_secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"

Real-world Team Collaboration Example

Let's walk through a complete example of how a team might collaborate on a Terraform project.

Project Structure

terraform-project/
├── .github/
│ └── workflows/
│ └── terraform.yml
├── modules/
│ ├── networking/
│ │ ├── main.tf
│ │ ├── variables.tf
│ │ └── outputs.tf
│ └── webserver/
│ ├── main.tf
│ ├── variables.tf
│ └── outputs.tf
├── environments/
│ ├── dev/
│ │ ├── main.tf
│ │ └── terraform.tfvars
│ └── prod/
│ ├── main.tf
│ └── terraform.tfvars
└── README.md

Workflow Example

  1. New Feature Development

    Developer creates a new branch for a feature:

    bash
    git checkout -b feature/add-load-balancer
  2. Module Development

    Create a new load balancer module:

    hcl
    # modules/load_balancer/main.tf
    resource "aws_lb" "example" {
    name = var.lb_name
    internal = var.internal
    load_balancer_type = "application"
    security_groups = var.security_groups
    subnets = var.subnets

    enable_deletion_protection = var.environment == "prod" ? true : false

    tags = {
    Environment = var.environment
    Project = var.project_name
    }
    }
  3. Module Usage

    Update the environment configuration:

    hcl
    # environments/dev/main.tf
    module "vpc" {
    source = "../../modules/networking"
    vpc_cidr = "10.0.0.0/16"
    environment = "dev"
    }

    module "load_balancer" {
    source = "../../modules/load_balancer"
    lb_name = "dev-lb"
    internal = false
    security_groups = [module.vpc.security_group_id]
    subnets = module.vpc.public_subnets
    environment = "dev"
    project_name = "example-project"
    }
  4. Local Testing

    bash
    cd environments/dev
    terraform init
    terraform plan
  5. Pull Request

    bash
    git add .
    git commit -m "Add load balancer module and implement in dev environment"
    git push origin feature/add-load-balancer
    # Create PR through GitHub interface
  6. CI Process

    The CI pipeline automatically runs:

    • Terraform format check
    • Terraform init
    • Terraform validate
    • Terraform plan
  7. Code Review

    Team members review:

    • The module implementation
    • The plan output
    • Security considerations
    • Compliance with team standards
  8. Approval and Merge

    After approval, the PR is merged to main.

  9. Deployment

    bash
    cd environments/dev
    terraform apply

Summary

Effective Terraform team collaboration requires:

  1. Remote State Management: Implement remote state storage with locking to prevent conflicts.
  2. Code Organization: Structure your code with modules and consistent repository organization.
  3. Workflow Standardization: Establish consistent practices for versioning, formatting, and documentation.
  4. Collaboration Tools: Use pull requests, code reviews, and CI/CD pipelines.
  5. Security Practices: Implement secure methods for managing secrets and sensitive data.

By following these practices, your team can work together efficiently on Terraform projects, reducing conflicts and maintaining infrastructure consistency across environments.

Additional Resources

  • Terraform Registry - Discover and use pre-built modules
  • Terraform Cloud - Managed service for Terraform state and workflows
  • Atlantis - Terraform pull request automation
  • Terragrunt - Thin wrapper for Terraform that provides extra tools for working with multiple Terraform modules

Exercises

  1. Set up a remote state backend for your Terraform project using S3 or another provider.
  2. Create a reusable module for a common infrastructure component your team uses.
  3. Implement a GitHub Actions workflow for Terraform validation and planning.
  4. Practice a pull request workflow with a team member, including code review of Terraform changes.
  5. Configure workspace isolation for different environments in your Terraform project.


If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)