To organize your Terraform infrastructure code into a clear and maintainable structure, especially for larger projects, you can adopt a modular approach. This helps in making the code scalable, reusable, and easier to manage. Below is a detailed guide on how to structure your Terraform directory for infrastructure, including best practices, examples, and a breakdown of each part of the directory structure.
1. Terraform Directory Structure Overview
A well-organized Terraform directory typically follows a modular approach, where configurations are divided into different folders based on functionality. Here’s an example of a directory structure:
2. Directory Breakdown
A. Root Level (Main Files)
The root of your Terraform project contains the global Terraform configurations, such as providers, versions, and main configuration files.
1. main.tf:
• This file typically contains the high-level infrastructure setup. It can include provider configurations, resource definitions, and module calls.
2. variables.tf:
• Defines the input variables for your Terraform setup. It’s a good practice to centralize all your input variables in this file.
3. outputs.tf:
• Defines the outputs, which are the results of your Terraform apply process. Outputs are typically used to pass information between modules or display important details.
4. terraform.tfvars:
• This is the file where you can set the actual values for your input variables defined in variables.tf. It is typically used to manage environment-specific configurations.
5. provider.tf:
• Contains the configuration for your cloud provider (e.g., AWS, Azure, Google Cloud). Here, you’ll set up your provider and authenticate Terraform with the respective cloud provider.
B. Modules Directory
Modules are reusable components of your infrastructure. They can be independently tested and reused across environments.
1. network module (/modules/network):
• This module contains resources related to networking. It might define VPCs, subnets, security groups, and route tables.
• Example files in network module:
• main.tf: Defines VPC, subnets, etc.
• variables.tf: Accepts variables like CIDR blocks, region, etc.
• outputs.tf: Outputs network-related information, like VPC ID or subnet CIDRs.
2. compute module (/modules/compute):
• This module defines the compute resources such as EC2 instances, autoscaling groups, or virtual machines.
• Example files in compute module:
• main.tf: EC2 instances, autoscaling configurations, etc.
• variables.tf: Instance types, AMI IDs, etc.
• outputs.tf: Instance IDs, public IPs, etc.
3. storage module (/modules/storage):
• This module manages storage resources such as S3 buckets, EBS volumes, etc.
• Example files in storage module:
• main.tf: S3 buckets, EBS volumes, etc.
• variables.tf: Bucket names, volume sizes, etc.
• outputs.tf: Bucket URL, volume IDs, etc.
4. iam module (/modules/iam):
• This module handles Identity and Access Management (IAM) roles, policies, and users.
• Example files in iam module:
• main.tf: IAM roles, users, and policies.
• variables.tf: User names, policy names, etc.
• outputs.tf: Role ARN, policy ARNs, etc.
C. Environments Directory
Environment-specific configurations are placed here. Each environment (dev, staging, prod) can have its own set of configurations, which helps in keeping the infrastructure isolated.
1. dev, prod, staging folders:
• These folders represent different environments. Each folder will have its own configuration files like main.tf, variables.tf, and outputs.tf.
• Example of dev/main.tf:
• Calls modules from /modules/ directory, overriding variables as necessary for the development environment.
D. Global Configuration
In the /global folder, you typically store reusable global configurations like providers, shared settings, and the main infrastructure definitions that might be common across environments.
• main.tf: You can call modules here and reference the environment-specific variables.
• variables.tf: Defines variables used globally across environments.
• outputs.tf: Stores global outputs.
3. Example Files
Example: main.tf in Root Directory
Example: variables.tf in Root Directory
Example: outputs.tf in Root Directory
Example: main.tf in dev Environment Folder
4. Best Practices
• Modularize: Break down large infrastructure configurations into smaller modules for better maintainability.
• Use Variables: Avoid hardcoding values. Use variables for flexibility across environments.
• Environment-Specific Configuration: Use separate files and directories for different environments (dev, staging, prod).
• State Management: Use remote backends like S3 with DynamoDB for state locking in a team environment.
5. Conclusion
With this directory structure, Terraform configurations are modular, reusable, and easy to manage, especially as your infrastructure grows. The separation of concerns into different modules and environment-specific configurations makes it easier to manage different setups for development, staging, and production environments.