Module structure
Root module
Combines the cluster and service sub-modules into a single integrated entrypoint. One
module block provisions a cluster and any number of services together.Cluster sub-module
Creates an ECS cluster, capacity providers, CloudWatch log group, task execution IAM role, and — for ECS Managed Instances — the infrastructure IAM role, node IAM role, and security group.
Service sub-module
Creates one ECS service, its task definition, container definitions, autoscaling resources, security group, service IAM role, task execution IAM role (optionally), and tasks IAM role.
Container definition sub-module
A building block invoked internally by the service sub-module for each container entry. Produces the JSON-encoded container definition and optionally manages the CloudWatch log group.
Express service sub-module
Creates an
aws_ecs_express_gateway_service — a simplified, fully-managed ECS service type with built-in autoscaling. Use this when you want a minimal configuration surface without managing task definitions directly.Construct hierarchy
Amazon ECS resources follow a strict parent-child hierarchy. The module mirrors this hierarchy exactly:| Level | AWS construct | Module that creates it |
|---|---|---|
| 1 | ECS Cluster | cluster sub-module |
| 2 | ECS Service | service sub-module |
| 3 | Task Definition / Task Set | service sub-module |
| 4 | Container Definition (1–10 per task) | container-definition sub-module |
- A cluster may contain one or more services.
- A service manages one task definition or task set (this module assumes one per service).
- A task wraps one to ten container definitions. Think of a task as a Kubernetes pod and the task definition as a pod spec.
Root module vs. separate sub-modules
- Root module (integrated)
- Separate sub-modules
Use the root module when you want to manage the cluster and all of its services in a single Terraform configuration. The root module accepts a Best for: Single-team clusters where one Terraform workspace owns the cluster and all services.
services map and iterates over it with for_each, passing the cluster ARN and the cluster-level task execution role ARN to each service automatically.Capacity provider types
The cluster sub-module supports four capacity provider types. You cannot mix Fargate-based providers with EC2-based providers on the same cluster.| Type | How compute is provisioned | Key tradeoff |
|---|---|---|
| FARGATE | AWS manages serverless compute | Predictable pricing; no EC2 management |
| FARGATE_SPOT | Spot capacity for Fargate | Up to 70% cheaper; tasks can be interrupted |
| EC2 Auto Scaling Group | You supply an ASG (e.g., via terraform-aws-autoscaling); ECS manages scaling via managed scaling | Full EC2 control; you own the AMI and instance lifecycle |
| ECS Managed Instances | ECS provisions and manages EC2 instances via a fleet API; uses managed_instances_provider block | Fully managed EC2 nodes; requires infrastructure and node IAM roles |
Resources created by each module
Cluster sub-module
Cluster sub-module
| Resource | Terraform resource type | Condition |
|---|---|---|
| ECS cluster | aws_ecs_cluster | Always |
| Cluster capacity providers | aws_ecs_cluster_capacity_providers | Always |
| EC2 / Managed Instances capacity provider | aws_ecs_capacity_provider | When capacity_providers is set |
| CloudWatch log group | aws_cloudwatch_log_group | create_cloudwatch_log_group = true |
| Task execution IAM role | aws_iam_role (task_exec) | create_task_exec_iam_role = true |
| Task execution IAM policy | aws_iam_policy (task_exec) | create_task_exec_policy = true |
| Infrastructure IAM role | aws_iam_role (infrastructure) | Managed Instances enabled |
| Infrastructure IAM policy | aws_iam_policy (infrastructure) | Managed Instances enabled |
| Node IAM role | aws_iam_role (node) | Managed Instances enabled |
| Node IAM policy | aws_iam_policy (node) | Managed Instances enabled |
| Node instance profile | aws_iam_instance_profile | Managed Instances enabled |
| Security group (for managed nodes) | aws_security_group | Managed Instances enabled |
| Security group rules | aws_vpc_security_group_ingress_rule / aws_vpc_security_group_egress_rule | Managed Instances enabled |
Service sub-module
Service sub-module
| Resource | Terraform resource type | Condition |
|---|---|---|
| ECS service | aws_ecs_service (this or ignore_task_definition) | create_service = true |
| ECS task definition | aws_ecs_task_definition | create_task_definition = true |
| ECS task set | aws_ecs_task_set | External deployment controller |
| Container definitions (via sub-module) | module.container_definition | One per entry in container_definitions |
| Task execution IAM role | aws_iam_role (task_exec) | create_task_exec_iam_role = true |
| Task execution IAM policy | aws_iam_policy (task_exec) | create_task_exec_policy = true |
| Tasks IAM role | aws_iam_role (tasks) | create_tasks_iam_role = true |
| Tasks IAM policy | aws_iam_policy (tasks) | Statements or ECS Exec enabled |
| Service IAM role | aws_iam_role (service) | Non-awsvpc mode with load balancer |
| Service IAM policy | aws_iam_policy (service) | Non-awsvpc mode with load balancer |
| Autoscaling target | aws_appautoscaling_target | enable_autoscaling = true |
| Autoscaling policies | aws_appautoscaling_policy | enable_autoscaling = true |
| Autoscaling scheduled actions | aws_appautoscaling_scheduled_action | When configured |
| Security group (for tasks) | aws_security_group | create_security_group = true |
| Security group rules | aws_vpc_security_group_ingress_rule / aws_vpc_security_group_egress_rule | When configured |
Container definition sub-module
Container definition sub-module
| Resource | Terraform resource type | Condition |
|---|---|---|
| CloudWatch log group | aws_cloudwatch_log_group | create_cloudwatch_log_group = true and enable_cloudwatch_logging = true |
container_definition local — a map that is JSON-encoded by the service sub-module and passed to aws_ecs_task_definition.container_definitions.Express service sub-module
Express service sub-module
| Resource | Terraform resource type | Condition |
|---|---|---|
| Express gateway service | aws_ecs_express_gateway_service | Always |
| Execution IAM role | aws_iam_role (execution) | create_execution_iam_role = true |
| Infrastructure IAM role | aws_iam_role (infrastructure) | create_infrastructure_iam_role = true |
| Security group | aws_security_group | create_security_group = true |
| Security group rules | aws_vpc_security_group_ingress_rule / aws_vpc_security_group_egress_rule | When configured |

