See vars.tf for all the variables you can set on this module.
See the ecs-service module for how to run Docker containers across this cluster.
What is an ECS Cluster?
To use ECS with the EC2 launch type, you first deploy one or more EC2 Instances into a "cluster". The ECS scheduler can
then deploy Docker containers across any of the instances in this cluster. Each instance needs to have the Amazon ECS
Agent installed so it can communicate with
ECS and register itself as part of the right cluster.
To add additional security group rules to the EC2 Instances in the ECS cluster, you can use the
aws_security_group_rule resource, and set its
security_group_id argument to the Terraform output of this module called ecs_instance_security_group_id. For
example, here is how you can allow the EC2 Instances in this cluster to allow incoming HTTP requests on port 8080:
Note: The security group rules you add will apply to ALL Docker containers running on these EC2 Instances. There is
currently no way in ECS to manage security group rules on a per-Docker-container basis.
How do you add additional IAM policies?
To add additional IAM policies to the EC2 Instances in the ECS cluster, you can use the
aws_iam_role_policy or
aws_iam_policy_attachment resources, and
set the IAM role id to the Terraform output of this module called ecs_instance_iam_role_name . For example, here is how
you can allow the EC2 Instances in this cluster to access an S3 bucket:
Note: The IAM policies you add will apply to ALL Docker containers running on these EC2 Instances. There is
currently no way in ECS to manage IAM policies on a per-Docker-container basis.
How do you make changes to the EC2 Instances in the cluster?
To deploy an update to an ECS Service, see the ecs-service module. To deploy an update to the
EC2 Instances in your ECS cluster, such as a new AMI, read on.
Terraform and AWS do not provide a way to automatically roll out a change to the Instances in an ECS Cluster. Due to
Terraform limitations (see here for a discussion), there is
currently no way to implement this purely in Terraform code. Therefore, we've created a script called
roll-out-ecs-cluster-update.py that can do a zero-downtime roll out for you.
How to use the roll-out-ecs-cluster-update.py script
First, make sure you have the latest version of the AWS Python SDK (boto3) installed
(e.g. pip install boto3).
To deploy a change such as rolling out a new AMI to all ECS Instances:
Make sure the cluster_max_size is at least twice the size of cluster_min_size. The extra capacity will be used
to deploy the updated instances.
Update the Terraform code with your changes (e.g. update the cluster_instance_ami variable to a new AMI).
If you have your output variables configured as shown in outputs.tf
of the docker-service-with-elb example, you can use the terraform output
command to fill in most of the arguments automatically:
To avoid the need to install python dependencies on your local machine, you may chose to use docker.
Navigate to the directory that you have downloaded roll-out-ecs-cluster-update.py:
If you use aws-vault, you can run the following to make your aws
credentials available to the container. If you do not use aws-vault, you will have to manually use the --env
option of docker run
The roll-out-ecs-cluster-update.py script does the following:
Double the desired capacity of the Auto Scaling Group that powers the ECS Cluster. This causes EC2 Instances to
deploy with the new launch configuration.
Put all the old ECS Instances in DRAINING state so all ECS Tasks are migrated to the new Instances.
Wait for all ECS Tasks to migrate to the new Instances.
Detach the now drained instances from the Auto Scaling Group, decrementing the desired capacity back to the original value.
How do you destroy an ECS cluster with Capacity Providers?
This means that on destroy, the aws_ecs_cluster is destroyed first. However, this attempt fails because the
AutoScaling Group still exists, and thus you will have Container Instances that are still associated with the ECS
cluster (you can't destroy an ECS cluster with active container instances), leading to a circular dependency.
As such, to break the chain, you will need to first scale down the ECS cluster by setting min_size and max_size to
0 prior to invoking destroy.
ECS cluster shutdown workaround
Due to a Terraform bug, destroy is broken on ECS
clusters that use the Capacity Provider resources (which this module does). To work around this issue, this module
includes a provisioner that, on destroy, runs a Python script. This script terminates EC2 instances in your ECS
cluster so that destroy works without issues.
In order for this script to work, you MUST have the following on the computer where you run destroy:
Python must be installed and on PATH. Version 2 or 3 should work.
The aws CLI must be installed and on PATH.
If for some reason you don't want this script to run (e.g., the script has a bug), you can set the environment varibale
SKIP_CONTAINER_INSTANCE_SHUTDOWN:
{"treedata":{"name":"root","toggled":true,"children":[{"name":".circleci","children":[{"name":"config.yml","path":".circleci/config.yml","sha":"99ea89a34148db228d6cd94a9d37bbfe8b4f627d"}]},{"name":".gitignore","path":".gitignore","sha":"75a7f4fc360463f11aeaf0fd02f614df1856d06b"},{"name":".pre-commit-config.yaml","path":".pre-commit-config.yaml","sha":"521a07813be53bb7e25ac822ae33f5065b4e9c8b"},{"name":"CODEOWNERS","path":"CODEOWNERS","sha":"e111382d70d3ef9073fe42a695d799fc84010a09"},{"name":"LICENSE.txt","path":"LICENSE.txt","sha":"f4e3d9bd4717a044ed31ad847a300eee74371a78"},{"name":"README.adoc","path":"README.adoc","sha":"879c58bd0ffadc7d850be36eca94198d62f8d417"},{"name":"_docs","children":[{"name":"ecs-architecture.png","path":"_docs/ecs-architecture.png","sha":"7caa9342bfc7ff5c74f26626a9831f22e914ff8e"},{"name":"ecs-fargate-service-icon.png","path":"_docs/ecs-fargate-service-icon.png","sha":"b8825b62a8b9170889c747320e1c79a9298c9bcb"},{"name":"ecs-icon.png","path":"_docs/ecs-icon.png","sha":"8ffdf43575d96d27ceced3d492871fa12403140e"},{"name":"ecs-service-architecture.png","path":"_docs/ecs-service-architecture.png","sha":"1bef2e6b95cb016b8e2c0219679d2d2d3ddd1769"},{"name":"ecs-service-icon.png","path":"_docs/ecs-service-icon.png","sha":"30947a9dcd3612d12ab42f40095b81a13fbaaff4"}]},{"name":"core-concepts.md","path":"core-concepts.md","sha":"816b25e1b3df74a01f2f564447c10b5ea5f5dd55"},{"name":"examples","children":[{"name":"deploy-ecs-task","children":[{"name":"README.md","path":"examples/deploy-ecs-task/README.md","sha":"5de7a89dc7a156f82c016fed690214711943bff6"},{"name":"containers","children":[{"name":"container-definitions.json","path":"examples/deploy-ecs-task/containers/container-definitions.json","sha":"1de2f83af666b622739f89debacc7c7faed35a08"}]},{"name":"main.tf","path":"examples/deploy-ecs-task/main.tf","sha":"c64eb726cd904ae7596cd7e3ac8e50bddb73bd59"},{"name":"outputs.tf","path":"examples/deploy-ecs-task/outputs.tf","sha":"24163bba223940a17f70bd4746ffcd1a6eafaec0"},{"name":"user-data","children":[{"name":"user-data.sh","path":"examples/deploy-ecs-task/user-data/user-data.sh","sha":"38ecd4127fac4ee0a05f6df37c86bbbf33629d4b"}]},{"name":"vars.tf","path":"examples/deploy-ecs-task/vars.tf","sha":"70a5be0fe5f10906076763b1ec4df79dccf68c34"}]},{"name":"docker-daemon-service","children":[{"name":"containers","children":[{"name":"datadog-agent-ecs.json","path":"examples/docker-daemon-service/containers/datadog-agent-ecs.json","sha":"7f8de1f4c5b716bab279112f14adf7f8dc0f6024"}]},{"name":"main.tf","path":"examples/docker-daemon-service/main.tf","sha":"db0b31bf12308ae0b05b9440e0095ec52ee51fe5"},{"name":"outputs.tf","path":"examples/docker-daemon-service/outputs.tf","sha":"2a294a1174fdc88601ebe62f9ab3dd4faf2d89fd"},{"name":"vars.tf","path":"examples/docker-daemon-service/vars.tf","sha":"820dd6293298357da998f1b34283b17d4d204b4f"}]},{"name":"docker-fargate-service-with-alb","children":[{"name":"README.md","path":"examples/docker-fargate-service-with-alb/README.md","sha":"e8754bd39b109b5b181f52596fbddef00302ea15"},{"name":"containers","children":[{"name":"container-definition.json","path":"examples/docker-fargate-service-with-alb/containers/container-definition.json","sha":"9091667150daa61c453f31975da897f735812c7c"}]},{"name":"main.tf","path":"examples/docker-fargate-service-with-alb/main.tf","sha":"04ccad4a63ac4c094353b0e7a4cf1137669b2f4e"},{"name":"outputs.tf","path":"examples/docker-fargate-service-with-alb/outputs.tf","sha":"f6b5bea9f779eaaa2b792f363657e7ba326b605e"},{"name":"vars.tf","path":"examples/docker-fargate-service-with-alb/vars.tf","sha":"cf092a8bc6ec68219d988d141845aa08291eeb03"}]},{"name":"docker-fargate-service-with-efs-volume","children":[{"name":"README.md","path":"examples/docker-fargate-service-with-efs-volume/README.md","sha":"ad85406d663a5f4429cf568ba13c781c6c0090fc"},{"name":"containers","children":[{"name":"container-definition.json","path":"examples/docker-fargate-service-with-efs-volume/containers/container-definition.json","sha":"0b6cb6d9e9ab8eec112e6120b6eb4def8c94ef35"}]},{"name":"main.tf","path":"examples/docker-fargate-service-with-efs-volume/main.tf","sha":"2c8eb676eb8124fc52ea2939f47e7838961d37d0"},{"name":"outputs.tf","path":"examples/docker-fargate-service-with-efs-volume/outputs.tf","sha":"2a10149cd88dc1b73415185c4aaa3ade4bf879bb"},{"name":"vars.tf","path":"examples/docker-fargate-service-with-efs-volume/vars.tf","sha":"112e34fa0892d613126d7b7f5f4acd5d09fba0e1"}]},{"name":"docker-fargate-service-with-nlb","children":[{"name":"README.md","path":"examples/docker-fargate-service-with-nlb/README.md","sha":"d064e28aebebd7606143feb8e46584f8667c9136"},{"name":"containers","children":[{"name":"container-definition.json","path":"examples/docker-fargate-service-with-nlb/containers/container-definition.json","sha":"083fca39166d4b8f243e66cb96f6aa9fad72cbe6"}]},{"name":"main.tf","path":"examples/docker-fargate-service-with-nlb/main.tf","sha":"dd164af51968a441dbd8cda48aa0a41947c121d0"},{"name":"outputs.tf","path":"examples/docker-fargate-service-with-nlb/outputs.tf","sha":"cd3a662c0a122b9bc276ebe207956b84ca203f31"},{"name":"vars.tf","path":"examples/docker-fargate-service-with-nlb/vars.tf","sha":"79ea2304ef0b31aec2925753e493a2bef0555b8b"}]},{"name":"docker-fargate-service-without-lb","children":[{"name":"README.md","path":"examples/docker-fargate-service-without-lb/README.md","sha":"fb5e52151d29936dd194ef319fc8f3dda277b26c"},{"name":"containers","children":[{"name":"container-definition.json","path":"examples/docker-fargate-service-without-lb/containers/container-definition.json","sha":"205833de7c0eabb367be2b16406cd12455d8e94e"}]},{"name":"main.tf","path":"examples/docker-fargate-service-without-lb/main.tf","sha":"ba3e40caeca12c87e8694c99848147b656fa81b1"},{"name":"outputs.tf","path":"examples/docker-fargate-service-without-lb/outputs.tf","sha":"2a10149cd88dc1b73415185c4aaa3ade4bf879bb"},{"name":"vars.tf","path":"examples/docker-fargate-service-without-lb/vars.tf","sha":"833fd1fcafbf09d0d011e6ddcf46b48a554f0eb0"}]},{"name":"docker-fargate-spot-service-with-alb","children":[{"name":"README.md","path":"examples/docker-fargate-spot-service-with-alb/README.md","sha":"e1911050a7716c9148817d390d640e53a4e979c2"},{"name":"containers","children":[{"name":"container-definition.json","path":"examples/docker-fargate-spot-service-with-alb/containers/container-definition.json","sha":"9091667150daa61c453f31975da897f735812c7c"}]},{"name":"main.tf","path":"examples/docker-fargate-spot-service-with-alb/main.tf","sha":"87413bbb08faf1c6c590f5fd2b27d365ead6dd8b"},{"name":"outputs.tf","path":"examples/docker-fargate-spot-service-with-alb/outputs.tf","sha":"f6b5bea9f779eaaa2b792f363657e7ba326b605e"},{"name":"vars.tf","path":"examples/docker-fargate-spot-service-with-alb/vars.tf","sha":"4d10332b87159c66947e5cc9c5e3c01a0d1cf386"}]},{"name":"docker-service-with-alb-and-nlb","children":[{"name":"README.md","path":"examples/docker-service-with-alb-and-nlb/README.md","sha":"d8515f6083fb03e819d8bbf570396b500c128983"},{"name":"main.tf","path":"examples/docker-service-with-alb-and-nlb/main.tf","sha":"e88c813352717bf6f92a556d341fbe9410e699d8"},{"name":"outputs.tf","path":"examples/docker-service-with-alb-and-nlb/outputs.tf","sha":"4dc100d16915fb67a46359048d1a369aea150db6"},{"name":"user-data","children":[{"name":"user-data.sh","path":"examples/docker-service-with-alb-and-nlb/user-data/user-data.sh","sha":"a534ef17a47772e610f864b9f764c209657c9d97"}]},{"name":"vars.tf","path":"examples/docker-service-with-alb-and-nlb/vars.tf","sha":"402938bdd18823d212db48fa56bdad9504a11425"}]},{"name":"docker-service-with-alb-autoscaling","children":[{"name":"README.md","path":"examples/docker-service-with-alb-autoscaling/README.md","sha":"8ef7623bdc0058639976fed36e2540763aafac95"},{"name":"containers","children":[{"name":"container-definition.json","path":"examples/docker-service-with-alb-autoscaling/containers/container-definition.json","sha":"4e28c983a3050ab7a18fd3e9d9ac4730bd9b285e"}]},{"name":"main.tf","path":"examples/docker-service-with-alb-autoscaling/main.tf","sha":"02cc2cbc79e254401b4f3ca2b60275b2aaf33436"},{"name":"outputs.tf","path":"examples/docker-service-with-alb-autoscaling/outputs.tf","sha":"2d96077e349d62d3e60a0eea34529ceb33e4da52"},{"name":"user-data","children":[{"name":"user-data.sh","path":"examples/docker-service-with-alb-autoscaling/user-data/user-data.sh","sha":"a534ef17a47772e610f864b9f764c209657c9d97"}]},{"name":"vars.tf","path":"examples/docker-service-with-alb-autoscaling/vars.tf","sha":"18c248f34f93e2bd896c69a2ff1b89df36a9513e"}]},{"name":"docker-service-with-alb-canary","children":[{"name":"README.md","path":"examples/docker-service-with-alb-canary/README.md","sha":"d0036aaa886915db2ba8976fd7e21486f111e11c"},{"name":"containers","children":[{"name":"container-definition.json","path":"examples/docker-service-with-alb-canary/containers/container-definition.json","sha":"4e28c983a3050ab7a18fd3e9d9ac4730bd9b285e"}]},{"name":"main.tf","path":"examples/docker-service-with-alb-canary/main.tf","sha":"5598ef8d9346cc17026b27974daaa5fce30c2bd3"},{"name":"outputs.tf","path":"examples/docker-service-with-alb-canary/outputs.tf","sha":"2d96077e349d62d3e60a0eea34529ceb33e4da52"},{"name":"user-data","children":[{"name":"user-data.sh","path":"examples/docker-service-with-alb-canary/user-data/user-data.sh","sha":"a534ef17a47772e610f864b9f764c209657c9d97"}]},{"name":"vars.tf","path":"examples/docker-service-with-alb-canary/vars.tf","sha":"57788ff3bef9deb283cb77c8b29e5c3a321faa88"}]},{"name":"docker-service-with-alb","children":[{"name":"README.md","path":"examples/docker-service-with-alb/README.md","sha":"589149955be5732eb79a478aed058fc632dc371c"},{"name":"containers","children":[{"name":"container-definition.json","path":"examples/docker-service-with-alb/containers/container-definition.json","sha":"4a3a2851994cdf389b9a3a9a0bb324981f0d4d59"}]},{"name":"main.tf","path":"examples/docker-service-with-alb/main.tf","sha":"2260f12adf6468df581a3043ec78f6098d6507cc"},{"name":"outputs.tf","path":"examples/docker-service-with-alb/outputs.tf","sha":"5ca6edc9e60ae3bfb6ef13003fe8236ebbb39821"},{"name":"user-data","children":[{"name":"user-data.sh","path":"examples/docker-service-with-alb/user-data/user-data.sh","sha":"a534ef17a47772e610f864b9f764c209657c9d97"}]},{"name":"vars.tf","path":"examples/docker-service-with-alb/vars.tf","sha":"1899eddd5d6d51101c95d4f64f16367ca08d3fcc"}]},{"name":"docker-service-with-autoscaling","children":[{"name":"README.md","path":"examples/docker-service-with-autoscaling/README.md","sha":"a57a30c7214f71ffc08650301d46a2ea973aa1ba"},{"name":"containers","children":[{"name":"container-definition.json","path":"examples/docker-service-with-autoscaling/containers/container-definition.json","sha":"ddcd10cc00465f84a8ce9eb7d937f1cc648bfa7b"}]},{"name":"main.tf","path":"examples/docker-service-with-autoscaling/main.tf","sha":"7ad34b023161c5b56d41970d77b2af2f78808e76"},{"name":"outputs.tf","path":"examples/docker-service-with-autoscaling/outputs.tf","sha":"c30e145beded6bc152c3e290c6230b31cb89ff71"},{"name":"user-data","children":[{"name":"user-data.sh","path":"examples/docker-service-with-autoscaling/user-data/user-data.sh","sha":"a534ef17a47772e610f864b9f764c209657c9d97"}]},{"name":"vars.tf","path":"examples/docker-service-with-autoscaling/vars.tf","sha":"1be3144d0d4b2539239ec5d6d4882eb0f3c07c3f"}]},{"name":"docker-service-with-canary-deployment","children":[{"name":"README.md","path":"examples/docker-service-with-canary-deployment/README.md","sha":"2eeccfce1d53f5bc3b12fffaa830538a78400cd7"},{"name":"containers","children":[{"name":"container-definition.json","path":"examples/docker-service-with-canary-deployment/containers/container-definition.json","sha":"ddcd10cc00465f84a8ce9eb7d937f1cc648bfa7b"}]},{"name":"main.tf","path":"examples/docker-service-with-canary-deployment/main.tf","sha":"a48460ac6fdd77079c824e5748db1a59d550743f"},{"name":"outputs.tf","path":"examples/docker-service-with-canary-deployment/outputs.tf","sha":"c30e145beded6bc152c3e290c6230b31cb89ff71"},{"name":"user-data","children":[{"name":"user-data.sh","path":"examples/docker-service-with-canary-deployment/user-data/user-data.sh","sha":"a534ef17a47772e610f864b9f764c209657c9d97"}]},{"name":"vars.tf","path":"examples/docker-service-with-canary-deployment/vars.tf","sha":"813e14d8e563ad9e5e91ff64f22a144514c7d1a7"}]},{"name":"docker-service-with-elb","children":[{"name":"README.md","path":"examples/docker-service-with-elb/README.md","sha":"f22cb6c52c7e991992c9cf7683a5f71d60c904ae"},{"name":"containers","children":[{"name":"container-definition.json","path":"examples/docker-service-with-elb/containers/container-definition.json","sha":"ddcd10cc00465f84a8ce9eb7d937f1cc648bfa7b"}]},{"name":"main.tf","path":"examples/docker-service-with-elb/main.tf","sha":"92708085d8c1e4aaa46da614637cc1b5da57292f"},{"name":"outputs.tf","path":"examples/docker-service-with-elb/outputs.tf","sha":"9e06fbf3bd18efdea1c96669b89cf69ddbc69f39"},{"name":"user-data","children":[{"name":"user-data.sh","path":"examples/docker-service-with-elb/user-data/user-data.sh","sha":"e265eb38080d4cced1a9c75adffbade208fe4882"}]},{"name":"vars.tf","path":"examples/docker-service-with-elb/vars.tf","sha":"89d55cedb7ba91daed4d64e98fb129fb97ccd33b"}]},{"name":"docker-service-with-private-discovery","children":[{"name":"README.md","path":"examples/docker-service-with-private-discovery/README.md","sha":"03c1d0863e05e6be054b9f8ae83ddc236ecc4c0f"},{"name":"containers","children":[{"name":"container-definition.json","path":"examples/docker-service-with-private-discovery/containers/container-definition.json","sha":"d5beb20e8e729d072992009ac38fe67018ef684a"}]},{"name":"main.tf","path":"examples/docker-service-with-private-discovery/main.tf","sha":"012a98b27111c4f5fe85bb1e091ea5c438f0b49b"},{"name":"outputs.tf","path":"examples/docker-service-with-private-discovery/outputs.tf","sha":"ac153ce17150d268fb0567f0ba66cabce6daf63f"},{"name":"user-data","children":[{"name":"user-data.sh","path":"examples/docker-service-with-private-discovery/user-data/user-data.sh","sha":"a534ef17a47772e610f864b9f764c209657c9d97"}]},{"name":"vars.tf","path":"examples/docker-service-with-private-discovery/vars.tf","sha":"dc7faeb68bb8f6b9d002cc0ee1d75459fe4cd324"}]},{"name":"docker-service-with-public-discovery","children":[{"name":"README.md","path":"examples/docker-service-with-public-discovery/README.md","sha":"d7d87171441af601b8a554b3de49fc87b7fd0772"},{"name":"containers","children":[{"name":"container-definition.json","path":"examples/docker-service-with-public-discovery/containers/container-definition.json","sha":"d5beb20e8e729d072992009ac38fe67018ef684a"}]},{"name":"main.tf","path":"examples/docker-service-with-public-discovery/main.tf","sha":"33061892cc7e6562888c893ed8ad4602992a3dcf"},{"name":"outputs.tf","path":"examples/docker-service-with-public-discovery/outputs.tf","sha":"ac153ce17150d268fb0567f0ba66cabce6daf63f"},{"name":"user-data","children":[{"name":"user-data.sh","path":"examples/docker-service-with-public-discovery/user-data/user-data.sh","sha":"a534ef17a47772e610f864b9f764c209657c9d97"}]},{"name":"vars.tf","path":"examples/docker-service-with-public-discovery/vars.tf","sha":"59e7cc6a095de1bf8fefa19c7eb918964fca1610"}]},{"name":"docker-service-without-elb","children":[{"name":"README.md","path":"examples/docker-service-without-elb/README.md","sha":"178a8376a2225be3c9d760f26c72e46841e0c2b7"},{"name":"containers","children":[{"name":"container-definition.json","path":"examples/docker-service-without-elb/containers/container-definition.json","sha":"ddcd10cc00465f84a8ce9eb7d937f1cc648bfa7b"}]},{"name":"main.tf","path":"examples/docker-service-without-elb/main.tf","sha":"60e37ce78476e19a6ff392f9b0dd6f1744216a2b"},{"name":"outputs.tf","path":"examples/docker-service-without-elb/outputs.tf","sha":"ca3a10bee0379ce40a82d45806fa72350f5ae641"},{"name":"user-data","children":[{"name":"user-data.sh","path":"examples/docker-service-without-elb/user-data/user-data.sh","sha":"a534ef17a47772e610f864b9f764c209657c9d97"}]},{"name":"vars.tf","path":"examples/docker-service-without-elb/vars.tf","sha":"0663828c7959ea063a544f60ce1996e6b6203728"}]},{"name":"docker-vpc-service-with-alb","children":[{"name":"README.md","path":"examples/docker-vpc-service-with-alb/README.md","sha":"98fe3719c813f4920bcd12deed96520468048da7"},{"name":"main.tf","path":"examples/docker-vpc-service-with-alb/main.tf","sha":"22df374877894d0d3b4a3fe3b04d53c2ded31bf5"},{"name":"outputs.tf","path":"examples/docker-vpc-service-with-alb/outputs.tf","sha":"c5b02eee222895f5c56fcac0e0d42a04fa3cf08f"},{"name":"user-data","children":[{"name":"user-data.sh","path":"examples/docker-vpc-service-with-alb/user-data/user-data.sh","sha":"a534ef17a47772e610f864b9f764c209657c9d97"}]},{"name":"vars.tf","path":"examples/docker-vpc-service-with-alb/vars.tf","sha":"7db799cde779942474d1612279f99bad4ca85a2f"}]},{"name":"example-docker-image","children":[{"name":"Dockerfile","path":"examples/example-docker-image/Dockerfile","sha":"f2d4b71ade7473254eb2af4bc49f4e0088e4f77b"},{"name":"README.md","path":"examples/example-docker-image/README.md","sha":"272b6c12cad7ba326582bfca11fce195912021c4"},{"name":"server.js","path":"examples/example-docker-image/server.js","sha":"965b6a2342144bac9559d1328c09f64f31fb4501"}]},{"name":"example-ecs-instance-ami","children":[{"name":"README.md","path":"examples/example-ecs-instance-ami/README.md","sha":"0a239a9c1d5aa7e1a889d40650fbed1cb14f8e8a"},{"name":"build.json","path":"examples/example-ecs-instance-ami/build.json","sha":"0fad38e38b2c103c58c343fff2e4de931ed03e1b"}]},{"name":"example-vpc","children":[{"name":"README.md","path":"examples/example-vpc/README.md","sha":"f938024fd49977302bcb7982a0b7e9049574a78d"},{"name":"main.tf","path":"examples/example-vpc/main.tf","sha":"5395329f84ae38e879e483ec71887302329d2c25"},{"name":"outputs.tf","path":"examples/example-vpc/outputs.tf","sha":"29fe3a59a33e3648c3cdf0afbcc6b7224e1b81ea"},{"name":"vars.tf","path":"examples/example-vpc/vars.tf","sha":"668e867d5bc0938a092cc35a52093d05ede78cfe"}]}]},{"name":"modules","children":[{"name":"ecs-cluster","children":[{"name":"README.md","path":"modules/ecs-cluster/README.md","sha":"a75309127342c6204cb8daf9b4ffc94d78a21ce8","toggled":true},{"name":"main.tf","path":"modules/ecs-cluster/main.tf","sha":"d03d6a9b9a35998c9485f10ad29bfbc469ba0d56"},{"name":"outputs.tf","path":"modules/ecs-cluster/outputs.tf","sha":"055e5a2894d9bc994625d6004051404615932c7e"},{"name":"roll-out-ecs-cluster-update.py","path":"modules/ecs-cluster/roll-out-ecs-cluster-update.py","sha":"45943e2c81e886d64eb0b437183a52b87466efd2"},{"name":"shut-down-container-instances.py","path":"modules/ecs-cluster/shut-down-container-instances.py","sha":"c82c24df75e37164224e0198abe0aad2ba2bb734"},{"name":"vars.tf","path":"modules/ecs-cluster/vars.tf","sha":"aa3cec4113b7cf53a21df06e43046ac3c9b1a7db"}],"toggled":true},{"name":"ecs-daemon-service","children":[{"name":"README.md","path":"modules/ecs-daemon-service/README.md","sha":"93e576a1648fab47ad7b6bb013140f361d19c5ba"},{"name":"main.tf","path":"modules/ecs-daemon-service/main.tf","sha":"39a40d5497e63f1248ae58839d6aecc9fc623d24"},{"name":"outputs.tf","path":"modules/ecs-daemon-service/outputs.tf","sha":"b14be6c2f9498c05be9d3843437940b933b3b669"},{"name":"vars.tf","path":"modules/ecs-daemon-service/vars.tf","sha":"b2fd15f5b7ee84eed36100cfbadd0aa672229a7d"}]},{"name":"ecs-deploy-check-binaries","children":[{"name":"README.md","path":"modules/ecs-deploy-check-binaries/README.md","sha":"5f819dfaab1a1fe16f29314a2117cd14fcb4bb33"},{"name":"bin","children":[{"name":"check-ecs-service-deployment","path":"modules/ecs-deploy-check-binaries/bin/check-ecs-service-deployment","sha":"b162ec0c95bd1260995ccc383b89fb1528086d65"},{"name":"check_ecs_service_deployment_env.pex","path":"modules/ecs-deploy-check-binaries/bin/check_ecs_service_deployment_env.pex","sha":"089742e3c1d2b6d38c953adb7f66606858fd4ec1"},{"name":"entrypoint.py","path":"modules/ecs-deploy-check-binaries/bin/entrypoint.py","sha":"09af8e557b93844ce66a028e594b885498eef99c"}]},{"name":"build.sh","path":"modules/ecs-deploy-check-binaries/build.sh","sha":"c4195f1c571a197e2a40b46e8a5896080aa0c260"},{"name":"check_ecs_service_deployment","children":[{"name":"__init__.py","path":"modules/ecs-deploy-check-binaries/check_ecs_service_deployment/__init__.py","sha":"e69de29bb2d1d6434b8b29ae775ad8c2e48c5391"},{"name":"checker","children":[{"name":"__init__.py","path":"modules/ecs-deploy-check-binaries/check_ecs_service_deployment/checker/__init__.py","sha":"b3604eaedc6d77c18dd31a282af88377b642073d"},{"name":"active_tasks_checker.py","path":"modules/ecs-deploy-check-binaries/check_ecs_service_deployment/checker/active_tasks_checker.py","sha":"5aa07c2ef3265ecdd3396be3eca962dfed893975"},{"name":"base.py","path":"modules/ecs-deploy-check-binaries/check_ecs_service_deployment/checker/base.py","sha":"b43e7a9f8989b2b6ec9c428c02b7129146c03c9e"},{"name":"daemon_service_checker.py","path":"modules/ecs-deploy-check-binaries/check_ecs_service_deployment/checker/daemon_service_checker.py","sha":"2843fa595ebfb6137601051d3c5183727605c6ad"},{"name":"loadbalancer_checker.py","path":"modules/ecs-deploy-check-binaries/check_ecs_service_deployment/checker/loadbalancer_checker.py","sha":"54070f4b438a48ded5be35753fbc7469caff3cc0"}]},{"name":"exceptions.py","path":"modules/ecs-deploy-check-binaries/check_ecs_service_deployment/exceptions.py","sha":"12ef9651649f2c99ac6cba7a54314a8da197a2b3"},{"name":"utils.py","path":"modules/ecs-deploy-check-binaries/check_ecs_service_deployment/utils.py","sha":"d37d04f0265fe0a6a1faa0bad67358d4c21dc2ac"}]},{"name":"dev_requirements.txt","path":"modules/ecs-deploy-check-binaries/dev_requirements.txt","sha":"923be60db2d99bbeefbedf796478539f78712828"},{"name":"requirements.txt","path":"modules/ecs-deploy-check-binaries/requirements.txt","sha":"1b1257ceb0ad6adb051fe8a2c90392bd93d24a29"}]},{"name":"ecs-deploy","children":[{"name":"README.md","path":"modules/ecs-deploy/README.md","sha":"944a7f354a20ab2abde6ef87c5f49f0d855cb61e"},{"name":"bin","children":[{"name":"run-ecs-task","path":"modules/ecs-deploy/bin/run-ecs-task","sha":"a7cd4f0a8cd2240876f43489b3006da7e3425cf1"}]},{"name":"install.sh","path":"modules/ecs-deploy/install.sh","sha":"c322bebba62fd5a63e7bcb73010f9a52da1137f1"}]},{"name":"ecs-fargate","children":[{"name":"README.md","path":"modules/ecs-fargate/README.md","sha":"3eae9218a5c3fb18d3a4dd45f136df25052a93d9"}]},{"name":"ecs-scripts","children":[{"name":"README.md","path":"modules/ecs-scripts/README.md","sha":"4c357a9df12f3f2a56e447ae3a82b4e3e5bdc43a"},{"name":"bin","children":[{"name":"configure-ecs-instance","path":"modules/ecs-scripts/bin/configure-ecs-instance","sha":"3a35e5a10537a85c3525ca79672f4c561a40bacb"}]},{"name":"install.sh","path":"modules/ecs-scripts/install.sh","sha":"927760f5584ad2019b0ff31424ba8853a27aeffc"}]},{"name":"ecs-service-with-alb","children":[{"name":"README.md","path":"modules/ecs-service-with-alb/README.md","sha":"38c07b1b20f9dbf22479651763535225e716a28c"}]},{"name":"ecs-service-with-discovery","children":[{"name":"README.md","path":"modules/ecs-service-with-discovery/README.md","sha":"fe9dc7350327371959dacddf0471067f8ddbc42b"}]},{"name":"ecs-service","children":[{"name":"README-ECS-Fargate.adoc","path":"modules/ecs-service/README-ECS-Fargate.adoc","sha":"06c828c343a03aaa8fe84a291c8eeb0ce31d1669"},{"name":"README.adoc","path":"modules/ecs-service/README.adoc","sha":"58b54ea7d2da8140d067359fdbae3b0053d41e8b"},{"name":"auto_scaling.tf","path":"modules/ecs-service/auto_scaling.tf","sha":"76aef0cace989a2adfaa458c302f2557833d1644"},{"name":"core-concepts.md","path":"modules/ecs-service/core-concepts.md","sha":"9240d29e2f728f8cf5087ce16b86c81628a7c0ec"},{"name":"deployment_check.tf","path":"modules/ecs-service/deployment_check.tf","sha":"cf5a982a1804588fdab1fe78d6028e806f97b006"},{"name":"elb.tf","path":"modules/ecs-service/elb.tf","sha":"89908a33a91a980f42a7e26e7828837f6366827d"},{"name":"main.tf","path":"modules/ecs-service/main.tf","sha":"e0cdf6426110bfa9ff1025e6fdf4515471c99ba0"},{"name":"outputs.tf","path":"modules/ecs-service/outputs.tf","sha":"a93ac14a8866b5e4dbdecd368ef9164233099d7b"},{"name":"service_discovery.tf","path":"modules/ecs-service/service_discovery.tf","sha":"27096ac9b2593fdd4b78dc548ddfb05d0f26c10c"},{"name":"task_definition.tf","path":"modules/ecs-service/task_definition.tf","sha":"bad08334dc13032fa7fa3a08bd2ee175d4ef64a8"},{"name":"vars.tf","path":"modules/ecs-service/vars.tf","sha":"beae019441afe9a88764e9cb6b8897c0e671500f"}]}],"toggled":true},{"name":"setup.cfg","path":"setup.cfg","sha":"6deafc261704e20369c0983af88042e502ae4880"},{"name":"terraform-cloud-enterprise-private-module-registry-placeholder.tf","path":"terraform-cloud-enterprise-private-module-registry-placeholder.tf","sha":"ae586c0fe830819580e1009d41a9074f16e65bed"},{"name":"test","children":[{"name":"README.md","path":"test/README.md","sha":"85c0ba178e3f2d3784732b1e15af4d9a98474597"},{"name":"deploy_ecs_task_test.go","path":"test/deploy_ecs_task_test.go","sha":"796ae86f21a153aa085a428f5c26186037bf4467"},{"name":"docker_daemon_service_test.go","path":"test/docker_daemon_service_test.go","sha":"f473ce8d4ae6f9630bac968e4feb4b42bc8692ce"},{"name":"docker_ec2_service_test.go","path":"test/docker_ec2_service_test.go","sha":"a0d8a72a7e524aeae114dce255bc893c5a013db3"},{"name":"docker_fargate_service_alb_deployment_check_fail_by_container_test.go","path":"test/docker_fargate_service_alb_deployment_check_fail_by_container_test.go","sha":"b2e4eef2e3868262d653766927ce2da384a3bb28"},{"name":"docker_fargate_service_nlb_deployment_check_fail_by_container_test.go","path":"test/docker_fargate_service_nlb_deployment_check_fail_by_container_test.go","sha":"e2ee6b72b7400b344dadca3e26a0812a20457f57"},{"name":"docker_fargate_service_with_alb_test.go","path":"test/docker_fargate_service_with_alb_test.go","sha":"a2caf9f5032f3277738a1942cf579153f11a1019"},{"name":"docker_fargate_service_with_efs_volume_test.go","path":"test/docker_fargate_service_with_efs_volume_test.go","sha":"c0f5b4813746155894d2e46e9e2f2859b299d4c3"},{"name":"docker_fargate_service_with_nlb_test.go","path":"test/docker_fargate_service_with_nlb_test.go","sha":"70ba078049f129b3f6bb7eaf7c5f9c7d32bec985"},{"name":"docker_fargate_service_without_lb_deployment_check_fail_by_container_test.go","path":"test/docker_fargate_service_without_lb_deployment_check_fail_by_container_test.go","sha":"79cc5d902515349ecded94ce243ba5389e43dfe3"},{"name":"docker_fargate_service_without_lb_test.go","path":"test/docker_fargate_service_without_lb_test.go","sha":"dd8fcff52d2eed7b22834aa719b7554bda6961ac"},{"name":"docker_fargate_spot_service_with_alb_test.go","path":"test/docker_fargate_spot_service_with_alb_test.go","sha":"48d4eae21b10b2258bab3fce646f35533f491766"},{"name":"docker_service_failure_testing_utils.go","path":"test/docker_service_failure_testing_utils.go","sha":"69a9c18c777338e1b5a06e8d73f4aa60b5778311"},{"name":"docker_service_utils.go","path":"test/docker_service_utils.go","sha":"23bdf26f43f647511975409b0bf16c96aaa9998d"},{"name":"docker_service_with_alb_and_nlb_test.go","path":"test/docker_service_with_alb_and_nlb_test.go","sha":"70e277c15fbbfa65ac5e61f4dd62e6d4f64229dc"},{"name":"docker_service_with_alb_deployment_check_fail_test.go","path":"test/docker_service_with_alb_deployment_check_fail_test.go","sha":"a29b1ba563fce9a5575afe1824dd8eac04ab1e3e"},{"name":"docker_service_with_alb_test.go","path":"test/docker_service_with_alb_test.go","sha":"634d085812ab6e6d3223e10bd4afd7109c46ae7a"},{"name":"docker_service_with_autoscaling_deployment_check_fail_test.go","path":"test/docker_service_with_autoscaling_deployment_check_fail_test.go","sha":"db5993b87be2d0ff27c0cd651ad572d5d0f3c148"},{"name":"docker_service_with_autoscaling_test.go","path":"test/docker_service_with_autoscaling_test.go","sha":"719259060d0b51b32ba7082ed3a3305a04a1866c"},{"name":"docker_service_with_canary_deployment_check_fail_test.go","path":"test/docker_service_with_canary_deployment_check_fail_test.go","sha":"5b4f15526e137093db9599d4aee271d4cbe8665e"},{"name":"docker_service_with_canary_deployment_test.go","path":"test/docker_service_with_canary_deployment_test.go","sha":"0fc952bbf48182a11f02e9a54f5fc6c74b2269f0"},{"name":"docker_service_with_discovery_check_fail_test.go","path":"test/docker_service_with_discovery_check_fail_test.go","sha":"16ed1d879885c6b08389646e6978d4310a03630a"},{"name":"docker_service_with_discovery_test.go","path":"test/docker_service_with_discovery_test.go","sha":"1bb23ee2db08a16e8ec5d8d1159f6701456a8b43"},{"name":"docker_service_with_elb_deployment_check_fail_test.go","path":"test/docker_service_with_elb_deployment_check_fail_test.go","sha":"7511d8951bdd002d75f4fa0b0d1744edbd30f536"},{"name":"docker_service_with_elb_test.go","path":"test/docker_service_with_elb_test.go","sha":"abc9255d4d487375e47d44356b23a78fa4b66a56"},{"name":"docker_service_without_elb_deployment_check_fail_test.go","path":"test/docker_service_without_elb_deployment_check_fail_test.go","sha":"b60ee57bab6a76516fcddb081ebb53a687a396a7"},{"name":"docker_service_without_elb_test.go","path":"test/docker_service_without_elb_test.go","sha":"9b68c410ac075c3bdbeae908ee58e3e13941062b"},{"name":"docker_vpc_service_with_alb_test.go","path":"test/docker_vpc_service_with_alb_test.go","sha":"704aa7bb81da759322ec60963328861891565eae"},{"name":"ec2_amazon_linux2_test.go","path":"test/ec2_amazon_linux2_test.go","sha":"8d34c658442be08dce0fff2ddf2e2ec4a326cd9c"},{"name":"go.mod","path":"test/go.mod","sha":"527323269e38443fe3cd6aef1bea01b05483291e"},{"name":"go.sum","path":"test/go.sum","sha":"99cc986faa7524194c01968e9393cddd14ccfb09"},{"name":"script_tests","children":[{"name":"executor.sh","path":"test/script_tests/executor.sh","sha":"dedf71d5d3120275daa4df86b8a91c85b58a66b6"},{"name":"requirements.txt","path":"test/script_tests/requirements.txt","sha":"d1d1278133fea59fee5fc14c2a5db35c99bd6fe1"},{"name":"test_check_ecs_service_deployment.py","path":"test/script_tests/test_check_ecs_service_deployment.py","sha":"daabc761bdaeaf467cbfbca0cb2d91efb3179c4a"},{"name":"tox.ini","path":"test/script_tests/tox.ini","sha":"13e2809ee4d66cf9f05f0f3e18633ffe3114aac2"}]},{"name":"terratest_options.go","path":"test/terratest_options.go","sha":"4abf7ffc069e07905c137526fce02661de7d3ae2"},{"name":"test_helpers.go","path":"test/test_helpers.go","sha":"026512f6145427a16018826437562a17b45f4ee1"},{"name":"validation","children":[{"name":"validate_all_modules_and_examples_test.go","path":"test/validation/validate_all_modules_and_examples_test.go","sha":"74c928d0cbc2914e5cd708277bd857cb2375b660"}]}]}]},"detailsContent":"<h1 class=\"preview__body--title\" id=\"ecs-cluster-module\">ECS Cluster Module</h1><div class=\"preview__body--border\"></div><p>This Terraform Module launches an <a href=\"http://docs.aws.amazon.com/AmazonECS/latest/developerguide/ECS_clusters.html\" class=\"preview__body--description--blue\" target=\"_blank\">EC2 Container Service\nCluster</a> that you can use to run\nDocker containers and services (see the <a href=\"/repos/v0.29.0/module-ecs/modules/ecs-service/README.adoc\" class=\"preview__body--description--blue\">ecs-service module</a>).</p>\n<h2 class=\"preview__body--subtitle\" id=\"how-do-you-use-this-module\">How do you use this module?</h2>\n<ul>\n<li>See the <a href=\"/repos/v0.29.0/module-ecs/README.adoc\" class=\"preview__body--description--blue\">root README</a> for instructions on using Terraform modules.</li>\n<li>See the <a href=\"/repos/v0.29.0/module-ecs/examples\" class=\"preview__body--description--blue\">examples</a> folder for example usage.</li>\n<li>See <a href=\"/repos/v0.29.0/module-ecs/modules/ecs-cluster/vars.tf\" class=\"preview__body--description--blue\">vars.tf</a> for all the variables you can set on this module.</li>\n<li>See the <a href=\"/repos/v0.29.0/module-ecs/modules/ecs-service/README.adoc\" class=\"preview__body--description--blue\">ecs-service module</a> for how to run Docker containers across this cluster.</li>\n</ul>\n<h2 class=\"preview__body--subtitle\" id=\"what-is-an-ecs-cluster\">What is an ECS Cluster?</h2>\n<p>To use ECS with the EC2 launch type, you first deploy one or more EC2 Instances into a "cluster". The ECS scheduler can\nthen deploy Docker containers across any of the instances in this cluster. Each instance needs to have the <a href=\"http://docs.aws.amazon.com/AmazonECS/latest/developerguide/ECS_agent.html\" class=\"preview__body--description--blue\" target=\"_blank\">Amazon ECS\nAgent</a> installed so it can communicate with\nECS and register itself as part of the right cluster.</p>\n<h2 class=\"preview__body--subtitle\" id=\"how-do-you-run-docker-containers-on-the-cluster\">How do you run Docker containers on the cluster?</h2>\n<p>See the <a href=\"/repos/v0.29.0/module-ecs/modules/ecs-service/README.adoc\" class=\"preview__body--description--blue\">service module</a>.</p>\n<h2 class=\"preview__body--subtitle\" id=\"how-do-you-add-additional-security-group-rules\">How do you add additional security group rules?</h2>\n<p>To add additional security group rules to the EC2 Instances in the ECS cluster, you can use the\n<a href=\"https://www.terraform.io/docs/providers/aws/r/security_group_rule.html\" class=\"preview__body--description--blue\" target=\"_blank\">aws_security_group_rule</a> resource, and set its\n<code>security_group_id</code> argument to the Terraform output of this module called <code>ecs_instance_security_group_id</code>. For\nexample, here is how you can allow the EC2 Instances in this cluster to allow incoming HTTP requests on port 8080:</p>\n<pre>module <span class=\"hljs-string\">\"ecs_cluster\"</span> {\n # (arguments omitted)\n}\n<span class=\"hljs-built_in\">\nresource </span><span class=\"hljs-string\">\"aws_security_group_rule\"</span> <span class=\"hljs-string\">\"allow_inbound_http_from_anywhere\"</span> {\n <span class=\"hljs-built_in\"> type </span>= <span class=\"hljs-string\">\"ingress\"</span>\n from_port = 8080\n to_port = 8080\n protocol = <span class=\"hljs-string\">\"tcp\"</span>\n cidr_blocks = [<span class=\"hljs-string\">\"0.0.0.0/0\"</span>]\n\n security_group_id = <span class=\"hljs-string\">\"<span class=\"hljs-variable\">${module.ecs_cluster.ecs_instance_security_group_id}</span>\"</span>\n}\n</pre>\n<p><strong>Note</strong>: The security group rules you add will apply to ALL Docker containers running on these EC2 Instances. There is\ncurrently no way in ECS to manage security group rules on a per-Docker-container basis.</p>\n<h2 class=\"preview__body--subtitle\" id=\"how-do-you-add-additional-iam-policies\">How do you add additional IAM policies?</h2>\n<p>To add additional IAM policies to the EC2 Instances in the ECS cluster, you can use the\n<a href=\"https://www.terraform.io/docs/providers/aws/r/iam_role_policy.html\" class=\"preview__body--description--blue\" target=\"_blank\">aws_iam_role_policy</a> or\n<a href=\"https://www.terraform.io/docs/providers/aws/r/iam_policy_attachment.html\" class=\"preview__body--description--blue\" target=\"_blank\">aws_iam_policy_attachment</a> resources, and\nset the IAM role id to the Terraform output of this module called <code>ecs_instance_iam_role_name</code> . For example, here is how\nyou can allow the EC2 Instances in this cluster to access an S3 bucket:</p>\n<pre>module <span class=\"hljs-string\">\"ecs_cluster\"</span> {\n # (arguments omitted)\n}\n<span class=\"hljs-built_in\">\nresource </span><span class=\"hljs-string\">\"aws_iam_role_policy\"</span> <span class=\"hljs-string\">\"access_s3_bucket\"</span> {\n name = <span class=\"hljs-string\">\"access_s3_bucket\"</span>\n role = <span class=\"hljs-string\">\"<span class=\"hljs-variable\">${module.ecs_cluster.ecs_instance_iam_role_name}</span>\"</span>\n <span class=\"hljs-built_in\"> policy </span>= <<EOF\n{\n <span class=\"hljs-string\">\"Version\"</span>: <span class=\"hljs-string\">\"2012-10-17\"</span>,\n <span class=\"hljs-string\">\"Statement\"</span>: [\n {\n <span class=\"hljs-string\">\"Sid\"</span>: <span class=\"hljs-string\">\"\"</span>,\n <span class=\"hljs-string\">\"Effect\"</span>:<span class=\"hljs-string\">\"Allow\"</span>,\n <span class=\"hljs-string\">\"Action\"</span>: <span class=\"hljs-string\">\"s3:GetObject\"</span>,\n <span class=\"hljs-string\">\"Resource\"</span>: <span class=\"hljs-string\">\"arn:aws:s3:::examplebucket/*\"</span>\n }\n ]\n}\nEOF\n}\n</pre>\n<p><strong>Note</strong>: The IAM policies you add will apply to ALL Docker containers running on these EC2 Instances. There is\ncurrently no way in ECS to manage IAM policies on a per-Docker-container basis.</p>\n<h2 class=\"preview__body--subtitle\" id=\"how-do-you-make-changes-to-the-ec-2-instances-in-the-cluster\">How do you make changes to the EC2 Instances in the cluster?</h2>\n<p>To deploy an update to an ECS Service, see the <a href=\"/repos/v0.29.0/module-ecs/modules/ecs-service\" class=\"preview__body--description--blue\">ecs-service module</a>. To deploy an update to the\nEC2 Instances in your ECS cluster, such as a new AMI, read on.</p>\n<p>Terraform and AWS do not provide a way to automatically roll out a change to the Instances in an ECS Cluster. Due to\nTerraform limitations (see <a href=\"/repos/terraform-aws-ecs\" class=\"preview__body--description--blue\">here for a discussion</a>), there is\ncurrently no way to implement this purely in Terraform code. Therefore, we've created a script called\n<code>roll-out-ecs-cluster-update.py</code> that can do a zero-downtime roll out for you.</p>\n<h3 class=\"preview__body--subtitle\" id=\"how-to-use-the-roll-out-ecs-cluster-update-py-script\">How to use the roll-out-ecs-cluster-update.py script</h3>\n<p>First, make sure you have the latest version of the <a href=\"https://github.com/boto/boto3\" class=\"preview__body--description--blue\" target=\"_blank\">AWS Python SDK (boto3)</a> installed\n(e.g. <code>pip install boto3</code>).</p>\n<p>To deploy a change such as rolling out a new AMI to all ECS Instances:</p>\n<ol>\n<li>\n<p>Make sure the <code>cluster_max_size</code> is at least twice the size of <code>cluster_min_size</code>. The extra capacity will be used\nto deploy the updated instances.</p>\n</li>\n<li>\n<p>Update the Terraform code with your changes (e.g. update the <code>cluster_instance_ami</code> variable to a new AMI).</p>\n</li>\n<li>\n<p>Run <code>terraform apply</code>.</p>\n</li>\n<li>\n<p>Run the script:</p>\n<pre><span class=\"hljs-keyword\">python</span> <span class=\"hljs-keyword\">roll</span>-out-ecs-<span class=\"hljs-keyword\">cluster</span>-update.py --asg-name ASG_NAME --<span class=\"hljs-keyword\">cluster</span>-name CLUSTER_NAME --aws-region AWS_REGION\n</pre>\n<p>If you have your output variables configured as shown in <a href=\"/repos/v0.29.0/module-ecs/examples/docker-service-with-elb/outputs.tf\" class=\"preview__body--description--blue\">outputs.tf</a>\nof the <a href=\"/repos/v0.29.0/module-ecs/examples/docker-service-with-elb\" class=\"preview__body--description--blue\">docker-service-with-elb example</a>, you can use the <code>terraform output</code>\ncommand to fill in most of the arguments automatically:</p>\n<pre>python roll-out-ecs-cluster-update.py \\\n --asg-name <span class=\"hljs-constructor\">$(<span class=\"hljs-params\">terragrunt</span> <span class=\"hljs-params\">output</span> -<span class=\"hljs-params\">no</span>-<span class=\"hljs-params\">color</span> <span class=\"hljs-params\">asg_name</span>)</span> \\\n --cluster-name <span class=\"hljs-constructor\">$(<span class=\"hljs-params\">terragrunt</span> <span class=\"hljs-params\">output</span> -<span class=\"hljs-params\">no</span>-<span class=\"hljs-params\">color</span> <span class=\"hljs-params\">ecs_cluster_name</span>)</span> \\\n --aws-region <span class=\"hljs-constructor\">$(<span class=\"hljs-params\">terragrunt</span> <span class=\"hljs-params\">output</span> -<span class=\"hljs-params\">no</span>-<span class=\"hljs-params\">color</span> <span class=\"hljs-params\">aws_region</span>)</span>\n</pre>\n</li>\n</ol>\n<p>To avoid the need to install python dependencies on your local machine, you may chose to use docker.</p>\n<ol>\n<li>\n<p>Navigate to the directory that you have downloaded <code>roll-out-ecs-cluster-update.py</code>:</p>\n</li>\n<li>\n<p>If you use <a href=\"https://github.com/99designs/aws-vault\" class=\"preview__body--description--blue\" target=\"_blank\">aws-vault</a>, you can run the following to make your aws\ncredentials available to the container. If you do not use <code>aws-vault</code>, you will have to manually use the <code>--env</code>\noption of <code>docker run</code></p>\n<pre>docker run \\\n -<span class=\"ruby\">it --rm -v <span class=\"hljs-string\">\"$PWD\"</span><span class=\"hljs-symbol\">:/usr/src</span> -w /usr/src \\\n</span> -<span class=\"ruby\">-env-file <(aws-vault exec --assume-role-ttl=<span class=\"hljs-number\">1</span>h PROFIE -- env <span class=\"hljs-params\">| grep AWS) \\\n</span></span> python:2.7-alpine \\\n sh -c \"pip install boto3 && python roll-out-ecs-cluster-update.py \\\n -<span class=\"ruby\"><span class=\"hljs-params\">-asg-name ASG_NAME \\\n</span></span> -<span class=\"ruby\"><span class=\"hljs-params\">-cluster-name CLUSTER_NAME \\\n</span></span> -<span class=\"ruby\"><span class=\"hljs-params\">-aws-region AWS_REGION\"\n</span></span></pre>\n</li>\n</ol>\n<h3 class=\"preview__body--subtitle\" id=\"how-roll-out-ecs-cluster-update-py-works\">How roll-out-ecs-cluster-update.py works</h3>\n<p>The <code>roll-out-ecs-cluster-update.py</code> script does the following:</p>\n<ol>\n<li>Double the desired capacity of the Auto Scaling Group that powers the ECS Cluster. This causes EC2 Instances to\ndeploy with the new launch configuration.</li>\n<li>Put all the old ECS Instances in DRAINING state so all ECS Tasks are migrated to the new Instances.</li>\n<li>Wait for all ECS Tasks to migrate to the new Instances.</li>\n<li>Detach the now drained instances from the Auto Scaling Group, decrementing the desired capacity back to the original value.</li>\n</ol>\n<h2 class=\"preview__body--subtitle\" id=\"how-do-you-destroy-an-ecs-cluster-with-capacity-providers\">How do you destroy an ECS cluster with Capacity Providers?</h2>\n<p>When <a href=\"https://docs.aws.amazon.com/AmazonECS/latest/developerguide/cluster-capacity-providers.html\" class=\"preview__body--description--blue\" target=\"_blank\">enabling capacity providers with\nECS</a>, the following\ninternal dependency is made:</p>\n<pre>aws_ecs_cluster =<span class=\"hljs-function\"><span class=\"hljs-params\">depon</span>=></span> aws_ecs_capacity_provider =<span class=\"hljs-function\"><span class=\"hljs-params\">depon</span>=></span> aws_autoscaling_group\n</pre>\n<p>This means that on destroy, the <code>aws_ecs_cluster</code> is destroyed first. However, this attempt fails because the\nAutoScaling Group still exists, and thus you will have Container Instances that are still associated with the ECS\ncluster (you can't destroy an ECS cluster with active container instances), leading to a circular dependency.</p>\n<p>As such, to break the chain, you will need to first scale down the ECS cluster by setting <code>min_size</code> and <code>max_size</code> to\n<code>0</code> prior to invoking <code>destroy</code>.</p>\n<h2 class=\"preview__body--subtitle\" id=\"ecs-cluster-shutdown-workaround\">ECS cluster shutdown workaround</h2>\n<p>Due to a <a href=\"https://github.com/hashicorp/terraform-provider-aws/issues/11409\" class=\"preview__body--description--blue\" target=\"_blank\">Terraform bug</a>, <code>destroy</code> is broken on ECS\nclusters that use the Capacity Provider resources (which this module does). To work around this issue, this module\nincludes a <code>provisioner</code> that, on <code>destroy</code>, runs a Python script. This script terminates EC2 instances in your ECS\ncluster so that <code>destroy</code> works without issues.</p>\n<p>In order for this script to work, you MUST have the following on the computer where you run <code>destroy</code>:</p>\n<ol>\n<li>Python must be installed and on <code>PATH</code>. Version 2 or 3 should work.</li>\n<li>The <code>aws</code> CLI must be installed and on <code>PATH</code>.</li>\n</ol>\n<p>If for some reason you don't want this script to run (e.g., the script has a bug), you can set the environment varibale\n<code>SKIP_CONTAINER_INSTANCE_SHUTDOWN</code>:</p>\n<pre>export SKIP_CONTAINER_INSTANCE_SHUTDOWN=true\n<span class=\"hljs-keyword\">terraform</span> destroy\n</pre>\n","repoName":"module-ecs","repoRef":"v0.31.2","serviceDescriptor":{"serviceName":"ECS Service","serviceRepoName":"module-ecs","serviceRepoOrg":"gruntwork-io","serviceMainReadmePath":"/modules/ecs-service-with-alb","cloudProviders":["aws"],"description":"Deploy an ECS service with zero-downtime, rolling deployment, IAM Role, auto scaling, and more.","imageUrl":"ecs.png","licenseType":"subscriber","technologies":["Terraform","Python"],"compliance":[],"tags":[""]},"serviceCategoryName":"Docker services","fileName":"README.md","filePath":"/modules/ecs-cluster","title":"Repo Browser: ECS Service","description":"Browse the repos in the Gruntwork Infrastructure as Code Library."}