Terraform by HashiCorp is a popular infrastructure as code (IaC) tool used to provision and manage resources and infrastructure in any cloud. Organizing Terraform code effectively can significantly improve the maintainability and scalability of your infrastructure projects. This guide outlines several Terraform project structures, providing detailed examples and explaining how each approach can be beneficial depending on your project’s needs.
Basic project structure
A basic Terraform project structure might look something like this:
terraform-project/│├── main.tf # Main Terraform configuration file├── variables.tf # Variable definitions├── outputs.tf # Output values└── terraform.tfvars # Values for the declared variables
Explanation:
- main.tf: This file contains the primary configuration details, such as provider configuration and resource declarations.
- variables.tf: This file declares variables to be used within your Terraform configuration, enhancing modularity and reusability.
- outputs.tf: Outputs useful data about your resources, which can be used for referencing in other Terraform projects or for external use.
- terraform.tfvars: Typically contains values for the variables defined in
variables.tf
, allowing for customization per environment without altering the main configuration.
Module-based project structure
For larger projects, a module-based structure is recommended. It might look like this:
terraform-project/│├── main.tf├── variables.tf├── outputs.tf├── terraform.tfvars│└── modules/├── network/│ ├── main.tf│ ├── variables.tf│ └── outputs.tf├── compute/│ ├── main.tf│ ├── variables.tf│ └── outputs.tf└── database/├── main.tf├── variables.tf└── outputs.tf
- modules/: This directory contains subdirectories for each module (e.g., network, compute, database), which encapsulate specific components of the infrastructure.
- network/: Contains Terraform files managing networking resources like VPCs, subnets, and NAT gateways.
- compute/: Manages compute resources such as EC2 instances or Kubernetes clusters.
- database/: Manages database components, for example, RDS instances or DynamoDB tables.
- By using modules, you can reuse code across different projects and keep your Terraform code DRY (Don't Repeat Yourself).
Environment-specific project structure
When you need to manage multiple environments (like development, staging, and production), an environment-specific structure can be used:
terraform-project/│├── global/│ ├── main.tf│ ├── variables.tf│ └── outputs.tf│└── environments/├── development/│ ├── main.tf│ ├── terraform.tfvars│ └── outputs.tf├── staging/│ ├── main.tf│ ├── terraform.tfvars│ └── outputs.tf└── production/├── main.tf├── terraform.tfvars└── outputs.tf
- global/: Contains Terraform configurations that are common across all environments, such as IAM roles or S3 buckets.
- environments/: Each subdirectory represents a specific environment with its own configurations that override or extend the global settings.
- This structure allows for clear separation of environments, minimizing the risk of changes in one environment affecting another.
Workspaces-based approach
Terraform workspaces allow you to manage state files separately for the same configuration, making it easier to manage different environments with minimal duplication of code:
terraform-project/│├── main.tf├── variables.tf├── outputs.tf└── environments.tfvars├── development.tfvars├── staging.tfvars└── production.tfvars
- environments.tfvars/: Contains variable files for each workspace (environment). You switch between workspaces using
terraform workspace select development
, for example. - This setup uses the same set of Terraform files for each environment, differing only in the variable values provided by the tfvars files corresponding to each workspace.
Choosing the right project structure for your Terraform code depends largely on the size of your infrastructure, the complexity of the environments, and how distinct the configurations are across these environments. Each structure offers different benefits, such as modularity, reusability, and separation of concerns, which can help streamline operations and reduce errors as your infrastructure scales.
For more information on Terraform project structure, see the official Terraform docs.