Terraform module to run ECS cluster, with ASG + Launch Template + Scaling policies via capacity provider. See details in the corresponding AWS blog post Amazon ECS Cluster Auto Scaling is Now Generally Available.
- ECS cluster manages ASG capacity automatically.
- ASG with optional spot instances support.
- It's possible to specify various instance types for your cluster.
- EC2 instance profile with SSM policy - you can connect to the instances using the Session Manager.
- Default ECS task role allows creating a log group.
- Default security group for ECS nodes allow inbound connections from configurable list of network CIDRs.
- It's possible to specify additional security groups for ECS nodes.
- Latest ECS Optimized AMI with
amd64
orarm64
architectures. - Additional EBS disks.
- ASG lifecycle hooks.
Minimal
module "example_ecs_cluster" {
source = "github.com/jetbrains-infra/terraform-aws-ecs-cluster?ref=vX.X.X" // see https://github.com/jetbrains-infra/terraform-aws-ecs-cluster/releases
cluster_name = "FooBar"
// subnets where the ECS nodes are hosted
subnets_ids = [
aws_subnet.private_subnet_1.id,
aws_subnet.private_subnet_2.id
]
}
Full example
module "example_ecs_cluster" {
source = "github.com/jetbrains-infra/terraform-aws-ecs-cluster?ref=vX.X.X" // see https://github.com/jetbrains-infra/terraform-aws-ecs-cluster/releases
cluster_name = "FooBar"
spot = true
arm64 = true
target_capacity = 100
instance_types = {
"t4g.large" = 1
"t4g.xlarge" = 2
}
// subnets with ALB and bastion host e.g..
trusted_cidr_blocks = [
aws_subnet.public_subnet_1.cidr_block,
aws_subnet.public_subnet_2.cidr_block
]
ebs_disks = {
"/dev/sda" = 100
}
// subnets where the ECS nodes are hosted
subnets_ids = [
aws_subnet.private_subnet_1.id,
aws_subnet.private_subnet_2.id
]
lifecycle_hooks = [
{
name = "Example"
lifecycle_transition = "autoscaling:EC2_INSTANCE_LAUNCHING"
default_result = "CONTINUE"
heartbeat_timeout = 2000
role_arn = aws_iam_role.example.arn
notification_target_arn = "arn:aws:sqs:us-east-1:444455556666:queue1"
notification_metadata = <<EOF
{
"foo": "bar"
}
EOF
}
]
}
The following input variables are required:
Description: Cluster name.
Type: any
Description: IDs of subnets. Use subnets from various availability zones to make the cluster more reliable.
Type: list(string)
The following input variables are optional (have default values):
Description: ECS node architecture.
Type: bool
Default: false
Description: The maximum size the auto scaling group (measured in EC2 instances).
Type: number
Default: 100
Description: The minimum size the auto scaling group (measured in EC2 instances).
Type: number
Default: 0
Description: A list of additional EBS disks.
Type: map(string)
Default: {}
Description: ECS node instance types. Maps of pairs like type = weight
. Where weight gives the instance type a proportional weight to other instance types.
Type: map(any)
Default:
{
"t3a.small": 2
}
Description: A list of maps containing the name,lifecycle_transition,default_result,heartbeat_timeout,role_arn,notification_target_arn keys.
Type:
list(object({
name = string
lifecycle_transition = string
default_result = string
heartbeat_timeout = number
role_arn = string
notification_target_arn = string
notification_metadata = string
}))
Default: []
Description: The minimum number of on-demand EC2 instances.
Type: number
Default: 0
Description: The autoscaling group will not select instances with this setting for termination during scale in events.
Type: bool
Default: true
Description: Additional security group IDs. Default security group would be merged with the provided list.
Type: list
Default: []
Description: Choose should we use spot instances or on-demand to populate ECS cluster.
Type: bool
Default: false
Description: The target utilization for the cluster. A number between 1 and 100.
Type: string
Default: "100"
Description: List of trusted subnets CIDRs with hosts that should connect to the cluster. E.g., subnets with ALB and bastion hosts.
Type: list(string)
Default:
[
""
]
Description: A shell script will be executed at once at EC2 instance start.
Type: string
Default: ""
The following outputs are exported:
Description: Cluster ARN.
Description: capacity provider name (the same name for ASG).
Description: ECS default task role ARN.
Description: ECS default task role name.
Description: ECS service role ARN.
Description: ECS service role name.
Description: IAM instance profile ARN.
Description: IAM instance profile name.
Description: IAM instance role name.
Description: Cluster ID.
Description: Cluster name.
Description: The ID of the ECS nodes security group.
Description: The name of the ECS nodes security group.
The following providers are used by this module:
The following resources are used by this module:
- aws_autoscaling_group.ecs_nodes (resource)
- aws_ecs_capacity_provider.asg (resource)
- aws_ecs_cluster.default (resource)
- aws_iam_instance_profile.ecs_node (resource)
- aws_iam_role.ec2_instance_role (resource)
- aws_iam_role.ecs_service_role (resource)
- aws_iam_role.ecs_task_role (resource)
- aws_iam_role_policy.allow_create_log_groups (resource)
- aws_iam_role_policy_attachment.default_task_role (resource)
- aws_iam_role_policy_attachment.ecs_instance_role (resource)
- aws_iam_role_policy_attachment.service_role (resource)
- aws_iam_role_policy_attachment.ssm_core_role (resource)
- aws_launch_template.node (resource)
- aws_security_group.ecs_nodes (resource)
- aws_security_group_rule.egress (resource)
- aws_security_group_rule.ingress (resource)
- aws_iam_policy_document.allow_create_log_groups (data source)
- aws_iam_policy_document.ec2_instance_assume_role_policy (data source)
- aws_iam_policy_document.ecs_service_role_policy (data source)
- aws_iam_policy_document.ecs_task_role_policy (data source)
- aws_ssm_parameter.ecs_ami (data source)
- aws_ssm_parameter.ecs_ami_arm64 (data source)
- aws_subnet.default (data source)
- cloudinit_config.config (data source)