ECS Cluster Module
Creates an ECS cluster with service discovery namespace. Supports both Fargate and EC2 capacity providers.
Capacity Providers
The module configures Fargate capacity providers by default. Use fargate_spot_weight to balance between on-demand and spot capacity.
EC2 capacity providers can be enabled when specific instance requirements exist (GPU, custom AMIs, etc.) by setting create_ec2_capacity_provider = true.
EC2 Network Modes
The ec2_enable_task_eni variable controls how containers connect to the network:
| Setting | Network Mode | Description | Use Case |
|---|---|---|---|
true (default) |
awsvpc | Each task gets its own ENI with dedicated IP address | Standard deployments, Fargate compatibility |
false |
bridge | Containers share the host's network stack via Docker bridge | Running many services on a single EC2 instance |
awsvpc mode (default): - Each task gets its own Elastic Network Interface (ENI) - Tasks have dedicated IP addresses - Limited by instance ENI capacity (~4 ENIs for t3.large/xlarge) - Compatible with Fargate task definitions
bridge mode:
- Containers share the host's network stack
- Uses dynamic port mapping (ports 32768-65535)
- Allows many more tasks per instance (limited by CPU/memory only)
- Requires ECS Service Connect for service-to-service communication
- ALB target groups must use instance target type instead of ip
Examples
Basic (Fargate)
module "ecs_cluster" {
source = "./modules/ecs_cluster"
cluster_name = "my-cluster"
namespace_name = "my-namespace"
vpc_id = var.vpc_id
fargate_spot_weight = 50
rds_writer_endpoint = module.rds.writer_endpoint
rds_reader_endpoint = module.rds.reader_endpoint
}
EC2 Capacity Provider with Bridge Mode
module "ecs_cluster" {
source = "./modules/ecs_cluster"
cluster_name = "my-cluster"
namespace_name = "my-namespace"
vpc_id = var.vpc_id
fargate_spot_weight = 50
# Enable EC2 capacity provider
create_ec2_capacity_provider = true
ec2_instance_type = "t3a.xlarge"
ec2_subnet_ids = var.private_subnet_ids
ec2_desired_capacity = 1
ec2_min_size = 0
ec2_max_size = 2
# Use bridge mode for running many services on single instance
ec2_enable_task_eni = false
}
Modules
| Name | Source | Version |
|---|---|---|
| ec2_autoscaling | terraform-aws-modules/autoscaling/aws | 9.0.2 |
| ecs_cluster | terraform-aws-modules/ecs/aws//modules/cluster | 6.10.0 |
Inputs
| Name | Description | Type | Default | Required |
|---|---|---|---|---|
| cluster_name | Cluster name | string |
n/a | yes |
| container_insights | Container Insights setting for the ECS cluster. Valid values: 'enhanced', 'enabled', 'disabled' | string |
"enabled" |
no |
| create | Create ECS cluster | bool |
true |
no |
| create_db_reader_sd | Create db reader service discovery | bool |
true |
no |
| create_db_writer_sd | Create db writer service discovery | bool |
true |
no |
| create_ec2_capacity_provider | Whether to create EC2 capacity provider infrastructure | bool |
false |
no |
| create_task_exec_iam_role | Create cluster-level task execution IAM role with broad permissions. Set to false if services create their own task execution roles with least-privilege permissions. | bool |
true |
no |
| ec2_additional_iam_policy_arns | Additional IAM policy ARNs to attach to EC2 instance role | list(string) |
[] |
no |
| ec2_desired_capacity | Desired number of EC2 instances in the ASG | number |
1 |
no |
| ec2_enable_task_eni | Enable task ENI for awsvpc network mode. Set to false for bridge mode where containers share the host's network stack. When true (default), each task gets its own ENI with dedicated IP address. When false, tasks use bridge networking with dynamic port mapping, allowing more tasks per instance but requiring Service Connect for service discovery. | bool |
true |
no |
| ec2_image_id | AMI ID for EC2 instances. If null, uses the latest ECS-optimized Amazon Linux 2023 AMI | string |
null |
no |
| ec2_instance_type | EC2 instance type for ECS container instances | string |
"t3a.large" |
no |
| ec2_key_pair_name | EC2 key pair name for SSH access (optional) | string |
null |
no |
| ec2_max_size | Maximum number of EC2 instances in the ASG | number |
2 |
no |
| ec2_min_size | Minimum number of EC2 instances in the ASG | number |
0 |
no |
| ec2_root_volume_size | Root volume size in GB for EC2 instances | number |
50 |
no |
| ec2_security_group_ids | Additional security group IDs to attach to EC2 instances | list(string) |
[] |
no |
| ec2_subnet_ids | Subnet IDs for EC2 instances | list(string) |
[] |
no |
| external_vpc_ids_for_cloudmap | Used to create vpc association authorization for external VPCs created by CloudMap. E.g. for XRoad account | list(string) |
[] |
no |
| fargate_spot_weight | Fargate spot weight | number |
n/a | yes |
| namespace_name | Namespace name | string |
n/a | yes |
| rds_reader_endpoint | RDS reader endpoint | string |
n/a | yes |
| rds_writer_endpoint | RDS writer endpoint | string |
n/a | yes |
| vpc_id | VPC ID | string |
n/a | yes |
Outputs
| Name | Description |
|---|---|
| cluster_arn | ARN of the cluster |
| cluster_id | ID of the cluster |
| cluster_name | Name of the cluster |
| ec2_capacity_provider_name | Name of the EC2 capacity provider (null if not created) |
| ec2_security_group_id | Security group ID for EC2 instances (null if not created) |
| namespace_arn | Arn of the namespace |
| namespace_hosted_zone | HTTP name of the namespace |
| namespace_id | ID of the namespace |
| namespace_name | Arn of the namespace |
| rds_reader_endpoint | RDS Reader Endpoint |
| rds_writer_endpoint | RDS Writer Endpoint |
| service_discovery_domain_name | Service discovery domain name |