Create an Amazon ECS Cluster with Terraform
Example Terraform to configure an AWS VPC, Elastic Container Service cluster, and supporting IAM roles
About
Terraform by HashiCorp is an infrastructure automation tool that can be used to provision and manage resources on AWS.
This pattern will demonstrate how to use the community terraform-aws-modules to deploy a VPC, and an ECS cluster. This will form the core infrastructure that can be used to deploy containerized services using Amazon ECS.
Dependencies
- Terraform (tested version v1.2.5 on darwin_amd64)
- Git (tested version 2.27.0)
- AWS CLI
- AWS test account with administrator role access
- Configure AWS credentials
Architecture
This pattern will create the following AWS resources:
- Networking
- VPC
- 3 public subnets, 1 per AZ. If a region has less than 3 AZs it will create same number of public subnets as AZs.
- 3 private subnets, 1 per AZ. If a region has less than 3 AZs it will create same number of private subnets as AZs.
- 1 NAT Gateway (see warning below)
- 1 Internet Gateway
- Associated Route Tables
- VPC
- 1 ECS Cluster with AWS CloudWatch Container Insights enabled.
- Task execution IAM role
- CloudWatch log groups
- CloudMap service discovery namespace default
⚠️ Warning: This pattern deploys a single shared NAT gateway in a single AZ. This saves cost in most cases but has the following downsides:
- The shared NAT gateway is a single point of failure if that AZ has an outage.
- In cases where you make heavy use of the NAT gateway because your application makes many outbound connections to the public internet, you may acrue additional cross AZ charges because resources in the other two AZ’s are generating cross AZ traffic to a NAT gateway hosted in a different AZ.
In these cases consider adding a NAT gateway for each AZ. This will be a higher baseline cost but safer and will limit cross AZ traffic.
Define the infrastructure
Download the following three files that define the core infrastructure:
You should have three files:
main.tf- Main file that defines the core infrastructure to createoutputs.tf- A list of output variables that will be passed to other Terraform modules you may wish to deployversions.tf- A definition of the underlying requirements for this module.
💡 Tip: For a production environment it is highly recommended to create a
backend.tffile that configures S3 for state storage and DynamoBD for resource locking, or Terraform Cloud for state management.The default setup will only track Terraform state locally, and if you lose the state files Terraform will no longer be able to managed the created infrastructure, and you will have to manually track down and delete every resource that Terraform had created.
Deploy the Terraform definition
First we need to download all the dependency modules (defined in versions.tf) that this pattern relies on:
terraform init
Next we can review the deployment plan, and then deploy it:
terraform plan
terraform apply --auto-approve
When the Terraform apply is complete you will see a list of outputs similar to this:
Outputs:
ecs_cluster_id = "arn:aws:ecs:us-west-2:209640446841:cluster/files"
ecs_cluster_name = "files"
ecs_task_execution_role_arn = "arn:aws:iam::209640446841:role/files-20230518161249649200000002"
ecs_task_execution_role_name = "files-20230518161249649200000002"
private_subnets = [
"subnet-0dcca4267e8b9894c",
"subnet-047d27c28c7891a90",
"subnet-0ab5512d135ce43cb",
]
private_subnets_cidr_blocks = tolist([
"10.0.10.0/24",
"10.0.11.0/24",
"10.0.12.0/24",
])
public_subnets = [
"subnet-0d976733da1d6dd08",
"subnet-013db9ca920c24554",
"subnet-0b9e7e3e45bb6a743",
]
service_discovery_namespaces = {
"arn" = "arn:aws:servicediscovery:us-west-2:209640446841:namespace/ns-aliplookapjwmjgo"
"description" = "Service discovery namespace.clustername.local"
"hosted_zone" = "Z0609025HGBC4TU4U285"
"id" = "ns-aliplookapjwmjgo"
"name" = "default.files.local"
"tags" = tomap({
"Blueprint" = "files"
"GithubRepo" = "github.com/aws-ia/ecs-blueprints"
})
"tags_all" = tomap({
"Blueprint" = "files"
"GithubRepo" = "github.com/aws-ia/ecs-blueprints"
})
"vpc" = "vpc-0c7ae3da22686c9cd"
}
vpc_id = "vpc-0c7ae3da22686c9cd"
Tear it Down
You can use the following command to teardown the infrastructure that was created.
terraform destroy
See Also
- Check out the ECS Blueprints repository on Github that this pattern is sourced from
- Add a load balanced web service on top of this cluster
- Prefer CloudFormation? Check out: