7. Terraform Infrastructure Organization
← Back to Table of Contents | Previous: Kiro Hooks | Next: GitLab CI/CD →
7.1 Terraform Module Structure
Each AWS resource type is encapsulated in a reusable Terraform module.
infra-repo/
├── modules/
│ ├── vpc/
│ │ ├── main.tf
│ │ ├── variables.tf
│ │ └── outputs.tf
│ │
│ ├── ecs-cluster/
│ │ ├── main.tf
│ │ ├── variables.tf
│ │ └── outputs.tf
│ │
│ ├── ecs-service/
│ │ ├── main.tf
│ │ ├── variables.tf
│ │ └── outputs.tf
│ │
│ ├── rds/
│ │ ├── main.tf
│ │ ├── variables.tf
│ │ └── outputs.tf
│ │
│ ├── alb/
│ │ ├── main.tf
│ │ ├── variables.tf
│ │ └── outputs.tf
│ │
│ ├── ecr/
│ │ ├── main.tf
│ │ ├── variables.tf
│ │ └── outputs.tf
│ │
│ ├── iam/
│ │ ├── main.tf
│ │ ├── variables.tf
│ │ └── outputs.tf
│ │
│ └── cloudwatch/
│ ├── main.tf
│ ├── variables.tf
│ └── outputs.tf
│
├── environments/
│ ├── dev/
│ ├── staging/
│ └── prod/
7.2 Environment Configuration
Each environment composes the shared modules with environment-specific values.
File: environments/dev/main.tf
terraform {
required_version = ">= 1.6.0"
backend "s3" {
bucket = "myapp-terraform-state"
key = "dev/terraform.tfstate"
region = "eu-west-1"
dynamodb_table = "myapp-terraform-locks"
encrypt = true
}
}
provider "aws" {
region = var.aws_region
default_tags {
tags = {
Project = var.project_name
Environment = var.environment
ManagedBy = "terraform"
}
}
}
module "vpc" {
source = "../../modules/vpc"
project = var.project_name
environment = var.environment
cidr_block = var.vpc_cidr
}
module "ecs_cluster" {
source = "../../modules/ecs-cluster"
project = var.project_name
environment = var.environment
}
module "auth_service" {
source = "../../modules/ecs-service"
project = var.project_name
environment = var.environment
service_name = "auth"
cluster_id = module.ecs_cluster.cluster_id
vpc_id = module.vpc.vpc_id
subnet_ids = module.vpc.private_subnet_ids
image_uri = "${module.ecr.repository_urls["auth"]}:latest"
}
module "billing_service" {
source = "../../modules/ecs-service"
project = var.project_name
environment = var.environment
service_name = "billing"
cluster_id = module.ecs_cluster.cluster_id
vpc_id = module.vpc.vpc_id
subnet_ids = module.vpc.private_subnet_ids
image_uri = "${module.ecr.repository_urls["billing"]}:latest"
}
7.3 Terraform Naming Convention
All resources follow:
{project}-{environment}-{module}-{resource-type}
Examples:
myapp-dev-auth-ecs-service
myapp-prod-billing-rds-instance
myapp-staging-vpc-main
7.4 State Management
| Concern | Solution |
|---|---|
| Remote state | S3 bucket with versioning |
| State locking | DynamoDB table |
| State per environment | Separate state files per env |
| State encryption | S3 server-side encryption |
7.5 Secrets Management
- No secrets in
.tffiles or.tfvars - Use AWS Secrets Manager for application secrets
- Use SSM Parameter Store for configuration values
- Reference secrets in Terraform via
datasources
data "aws_secretsmanager_secret_version" "db_password" {
secret_id = "${var.project}-${var.environment}-db-password"
}
← Back to Table of Contents | Previous: Kiro Hooks | Next: GitLab CI/CD →