See variables.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. pip3 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:
Note: during upgrade, if desired_capacity * 2 > max_size then ASG max size will be updated to desired_capacity * 2 for the period of upgrade, to disable this behaviour - pass --keep-max-size argument.
To avoid the need to install python dependencies on your local machine, you may choose 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 configure cluster autoscaling?
ECS Clusters support two tiers of autoscaling:
Autoscaling of ECS Service and Tasks, where ECS will horizontally or vertically scale your ECS Tasks by provisioning
more replicas of the Task or replacing them with Tasks that have more resources allocated to it.
Autoscaling of the ECS Cluster, where the AWS Autoscaling Group will horizontally scale the worker nodes by
provisioning more.
The ecs-cluster module supports configuring ECS Cluster Autoscaling by leveraging ECS Capacity
Providers. You can read
more about how cluster autoscaling works with capacity providers in the official
documentation.
To enable capacity providers for cluster autoscaling on your ECS cluster, you will want to configure the following
variables:
# Turn on capacity providers for autoscaling
capacity_provider_enabled = true
# Enable Multi AZ capacity providers to balance autoscaling load across AZs. This should be true in production. Can be# false in dev and stage.
multi_az_capacity_provider = true
# Configure target utilization for the ECS cluster. This number influences when scale out happens, and when instances# should be scaled in. For example, a setting of 90 means that new instances will be provisioned when all instances are# at 90% utilization, while instances that are only 10% utilized (CPU and Memory usage from tasks = 10%) will be scaled# in. A recommended default to start with is 90.
capacity_provider_target = 90# The following are optional configurations, and configures how many instances should be scaled out or scaled in at one# time. Defaults to 1.# capacity_provider_max_scale_step = 1# capacity_provider_min_scale_step = 1
Note on toggling capacity providers on existing ECS Clusters
Each EC2 instance must be registered with Capacity Providers to be considered in the pool. This means that when you
enable Capacity Providers on an existing ECS cluster that did not have Capacity Providers, you must rotate the EC2
instances to ensure all the instances get associated with the new Capacity Provider.
To rotate the instances, you can run the
roll-out-ecs-cluster-update.py
script in the terraform-aws-ecs module. Refer to the
documentation
for more information on the script.
Questions? Ask away.
We're here to talk about our services, answer any questions, give advice, or just to chat.
{"treedata":{"name":"root","toggled":true,"children":[{"name":".circleci","children":[{"name":"config.yml","path":".circleci/config.yml","sha":"36b477bc857fffcdc84207000b431d7cbe708ca3"},{"name":"post-upgrade-test-results.sh","path":".circleci/post-upgrade-test-results.sh","sha":"a4867e8fbdc334b7a90259568ee41ea577fbe764"},{"name":"set-upgrade-test-vars.sh","path":".circleci/set-upgrade-test-vars.sh","sha":"04ccab865d51c1169f7ae4648c38a3d98a9889ab"}]},{"name":".github","children":[{"name":"ISSUE_TEMPLATE","children":[{"name":"bug_report.md","path":".github/ISSUE_TEMPLATE/bug_report.md","sha":"fda415fea4a0439c480c37b51958745bb7be5a70"},{"name":"feature_request.md","path":".github/ISSUE_TEMPLATE/feature_request.md","sha":"3f29bb49f5cdb78e7a2c2766d0b2249bd43945ef"}]},{"name":"pull_request_template.md","path":".github/pull_request_template.md","sha":"6b100e40e323b5b07f40ed30616277c51c9f4b9e"}]},{"name":".gitignore","path":".gitignore","sha":"fd639dbdd9eb8402900eaf2baf5708e36ff44431"},{"name":".patcher","children":[{"name":"patches","children":[{"name":"v0.31.0","children":[{"name":"upgrade-aws-provider","children":[{"name":"bump_aws_provider.sh","path":".patcher/patches/v0.31.0/upgrade-aws-provider/bump_aws_provider.sh","sha":"355825dd0598ac9ea07dd406637cc010dec21724"},{"name":"create_script_for_terraform_init.sh","path":".patcher/patches/v0.31.0/upgrade-aws-provider/create_script_for_terraform_init.sh","sha":"a29c419c9c914f82471c0e5bf073bd9552dbf33e"},{"name":"patch.yaml","path":".patcher/patches/v0.31.0/upgrade-aws-provider/patch.yaml","sha":"1498a411e69314a83433b6120b6f94e7d8a7c215"}]}]},{"name":"v0.32.0","children":[{"name":"terraform-1.1-upgrade","children":[{"name":"bump_required_version.sh","path":".patcher/patches/v0.32.0/terraform-1.1-upgrade/bump_required_version.sh","sha":"30abb1d075dbc85ce83dc415869de1c9c8560b0d"},{"name":"patch.yaml","path":".patcher/patches/v0.32.0/terraform-1.1-upgrade/patch.yaml","sha":"151598d0d058c97f47066847e8426c4eabb1a6dc"}]}]},{"name":"v0.33.0","children":[{"name":"drop-python-2","children":[{"name":"create_script_for_python_3.sh","path":".patcher/patches/v0.33.0/drop-python-2/create_script_for_python_3.sh","sha":"b66088ecbbe7a09429cddac4cfcf69d04a142314"},{"name":"patch.yaml","path":".patcher/patches/v0.33.0/drop-python-2/patch.yaml","sha":"68dd714fdef7b31a68fd2c125f874d6a58cd61a9"}]}]}]}]},{"name":".pre-commit-config.yaml","path":".pre-commit-config.yaml","sha":"521a07813be53bb7e25ac822ae33f5065b4e9c8b"},{"name":"CODEOWNERS","path":"CODEOWNERS","sha":"d1ea744a2fffde1dd2918c8bca418aa2dd1b86bd"},{"name":"LICENSE.txt","path":"LICENSE.txt","sha":"f4e3d9bd4717a044ed31ad847a300eee74371a78"},{"name":"README.adoc","path":"README.adoc","sha":"87a2c42f3bfbe38d38c0232201e9a10ffa2dc893"},{"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":"43acea16b9efbbee1b4b7e23e0340840ac09a853"},{"name":"examples","children":[{"name":"deploy-ecs-scheduled-task","children":[{"name":"containers","children":[{"name":"container-definitions.json","path":"examples/deploy-ecs-scheduled-task/containers/container-definitions.json","sha":"1de2f83af666b622739f89debacc7c7faed35a08"}]},{"name":"main.tf","path":"examples/deploy-ecs-scheduled-task/main.tf","sha":"28c75d56d8c043936f27d683be0a8f50f08202a9"},{"name":"outputs.tf","path":"examples/deploy-ecs-scheduled-task/outputs.tf","sha":"fde450d4a6a52b47d101e50d0a128d2790c7cd41"},{"name":"user-data","children":[{"name":"user-data.sh","path":"examples/deploy-ecs-scheduled-task/user-data/user-data.sh","sha":"38ecd4127fac4ee0a05f6df37c86bbbf33629d4b"}]},{"name":"variables.tf","path":"examples/deploy-ecs-scheduled-task/variables.tf","sha":"942d6d88da2d864f9c4f4c12214484dcc3e5b2a8"}]},{"name":"deploy-ecs-task","children":[{"name":"README.md","path":"examples/deploy-ecs-task/README.md","sha":"21aae5e552219147d78080324d62f48c018b6324"},{"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":"6a9f707c6b6569370c95b1d4d37d3474d6b4dedc"},{"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":"variables.tf","path":"examples/deploy-ecs-task/variables.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":"3d2168c3b0c6a2970a28ea07c7a598a4187df377"},{"name":"outputs.tf","path":"examples/docker-daemon-service/outputs.tf","sha":"2a294a1174fdc88601ebe62f9ab3dd4faf2d89fd"},{"name":"variables.tf","path":"examples/docker-daemon-service/variables.tf","sha":"820dd6293298357da998f1b34283b17d4d204b4f"}]},{"name":"docker-fargate-service-with-alb","children":[{"name":"README.md","path":"examples/docker-fargate-service-with-alb/README.md","sha":"a4a806a58539ba75b88b70f71ead85da08c1a4ec"},{"name":"containers","children":[{"name":"container-definition.json","path":"examples/docker-fargate-service-with-alb/containers/container-definition.json","sha":"657699ec82e7ff57f127e94e65fb804a3771b877"}]},{"name":"main.tf","path":"examples/docker-fargate-service-with-alb/main.tf","sha":"3453333c447d9e41c81fd13f76a37f5d62e319be"},{"name":"outputs.tf","path":"examples/docker-fargate-service-with-alb/outputs.tf","sha":"f6b5bea9f779eaaa2b792f363657e7ba326b605e"},{"name":"variables.tf","path":"examples/docker-fargate-service-with-alb/variables.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":"283dd6bfde71e3de96e5a12fa28082878277e082"},{"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":"347375acbab375c3ed161d3d279ac7575b64a561"},{"name":"outputs.tf","path":"examples/docker-fargate-service-with-efs-volume/outputs.tf","sha":"2a10149cd88dc1b73415185c4aaa3ade4bf879bb"},{"name":"variables.tf","path":"examples/docker-fargate-service-with-efs-volume/variables.tf","sha":"112e34fa0892d613126d7b7f5f4acd5d09fba0e1"}]},{"name":"docker-fargate-service-with-nlb","children":[{"name":"README.md","path":"examples/docker-fargate-service-with-nlb/README.md","sha":"82d8e921550c588bc4fc8ec696fc8d409dcda466"},{"name":"containers","children":[{"name":"container-definition.json","path":"examples/docker-fargate-service-with-nlb/containers/container-definition.json","sha":"578cf99bd6afdf8f30382603fb6eb10e69df9122"}]},{"name":"main.tf","path":"examples/docker-fargate-service-with-nlb/main.tf","sha":"a8cc8948fbe9bd3a3d37074f6dd6bdbdc9b892b0"},{"name":"outputs.tf","path":"examples/docker-fargate-service-with-nlb/outputs.tf","sha":"cd3a662c0a122b9bc276ebe207956b84ca203f31"},{"name":"variables.tf","path":"examples/docker-fargate-service-with-nlb/variables.tf","sha":"79ea2304ef0b31aec2925753e493a2bef0555b8b"}]},{"name":"docker-fargate-service-without-lb","children":[{"name":"README.md","path":"examples/docker-fargate-service-without-lb/README.md","sha":"c77781208f465fae225169901cd6228779d47a9f"},{"name":"containers","children":[{"name":"container-definition.json","path":"examples/docker-fargate-service-without-lb/containers/container-definition.json","sha":"0b0b64d1050ebd6c5488fdf408053b5ebfa0c2ed"}]},{"name":"main.tf","path":"examples/docker-fargate-service-without-lb/main.tf","sha":"36edd2a6d94645e2014225147a5d20d53e7d72e6"},{"name":"outputs.tf","path":"examples/docker-fargate-service-without-lb/outputs.tf","sha":"2a10149cd88dc1b73415185c4aaa3ade4bf879bb"},{"name":"variables.tf","path":"examples/docker-fargate-service-without-lb/variables.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":"57ba5698469db3e09255f66406a036eeb4d92752"},{"name":"containers","children":[{"name":"container-definition.json","path":"examples/docker-fargate-spot-service-with-alb/containers/container-definition.json","sha":"657699ec82e7ff57f127e94e65fb804a3771b877"}]},{"name":"main.tf","path":"examples/docker-fargate-spot-service-with-alb/main.tf","sha":"5318a8ab67d1171222a1a7289d7d7d5d088235d4"},{"name":"outputs.tf","path":"examples/docker-fargate-spot-service-with-alb/outputs.tf","sha":"f6b5bea9f779eaaa2b792f363657e7ba326b605e"},{"name":"variables.tf","path":"examples/docker-fargate-spot-service-with-alb/variables.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":"f5079fe054f27546ea78cebe0ca7de52055cca43"},{"name":"main.tf","path":"examples/docker-service-with-alb-and-nlb/main.tf","sha":"bc8597d7320fe06eb78c15fc38a5324ee45974b4"},{"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":"variables.tf","path":"examples/docker-service-with-alb-and-nlb/variables.tf","sha":"402938bdd18823d212db48fa56bdad9504a11425"}]},{"name":"docker-service-with-alb-autoscaling","children":[{"name":"README.md","path":"examples/docker-service-with-alb-autoscaling/README.md","sha":"8b250d46da14a22c7749f2f0533dde004909cb92"},{"name":"containers","children":[{"name":"container-definition.json","path":"examples/docker-service-with-alb-autoscaling/containers/container-definition.json","sha":"d12e590e2d71b5717998941cf7cb85efa804e26c"}]},{"name":"main.tf","path":"examples/docker-service-with-alb-autoscaling/main.tf","sha":"9758650306a2189ec022c336ea00a9561aef7277"},{"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":"variables.tf","path":"examples/docker-service-with-alb-autoscaling/variables.tf","sha":"18c248f34f93e2bd896c69a2ff1b89df36a9513e"}]},{"name":"docker-service-with-alb-canary","children":[{"name":"README.md","path":"examples/docker-service-with-alb-canary/README.md","sha":"4ea6c55f115724ae77a9b3b86dab57838a71c089"},{"name":"containers","children":[{"name":"container-definition.json","path":"examples/docker-service-with-alb-canary/containers/container-definition.json","sha":"d12e590e2d71b5717998941cf7cb85efa804e26c"}]},{"name":"main.tf","path":"examples/docker-service-with-alb-canary/main.tf","sha":"bda504a6d82d11ec09f9b6f6a143f14ed83884fb"},{"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":"variables.tf","path":"examples/docker-service-with-alb-canary/variables.tf","sha":"57788ff3bef9deb283cb77c8b29e5c3a321faa88"}]},{"name":"docker-service-with-alb","children":[{"name":"README.md","path":"examples/docker-service-with-alb/README.md","sha":"aac8088b2f1342aa3b6321d07d2084c94dd25320"},{"name":"containers","children":[{"name":"container-definition.json","path":"examples/docker-service-with-alb/containers/container-definition.json","sha":"3dc641bce3647b86a602779688cca40ecb457f90"}]},{"name":"main.tf","path":"examples/docker-service-with-alb/main.tf","sha":"1615023569bf4220ffc171d91c995ff4ca9da38b"},{"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":"variables.tf","path":"examples/docker-service-with-alb/variables.tf","sha":"1899eddd5d6d51101c95d4f64f16367ca08d3fcc"}]},{"name":"docker-service-with-autoscaling","children":[{"name":"README.md","path":"examples/docker-service-with-autoscaling/README.md","sha":"01fa504a880b73e35d0e80fcc772ee37fe337058"},{"name":"containers","children":[{"name":"container-definition.json","path":"examples/docker-service-with-autoscaling/containers/container-definition.json","sha":"24cd7978210344f80257d578f5b3f08671762395"}]},{"name":"main.tf","path":"examples/docker-service-with-autoscaling/main.tf","sha":"04b155e902b269590c44df31bee748f83f966d81"},{"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":"variables.tf","path":"examples/docker-service-with-autoscaling/variables.tf","sha":"1be3144d0d4b2539239ec5d6d4882eb0f3c07c3f"}]},{"name":"docker-service-with-canary-deployment","children":[{"name":"README.md","path":"examples/docker-service-with-canary-deployment/README.md","sha":"a834379556fe449d71adf853cd446668ed580ee9"},{"name":"containers","children":[{"name":"container-definition.json","path":"examples/docker-service-with-canary-deployment/containers/container-definition.json","sha":"b946781dd2aab6ec41f080ecb797f4f28aa0a0d7"}]},{"name":"main.tf","path":"examples/docker-service-with-canary-deployment/main.tf","sha":"82e49f8d9ed21e793bfda3b5aadfc40dc7e2c822"},{"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":"variables.tf","path":"examples/docker-service-with-canary-deployment/variables.tf","sha":"813e14d8e563ad9e5e91ff64f22a144514c7d1a7"}]},{"name":"docker-service-with-elb","children":[{"name":"README.md","path":"examples/docker-service-with-elb/README.md","sha":"9fe41265d3fdba73113eac416901f6be7ab0a1b3"},{"name":"containers","children":[{"name":"container-definition.json","path":"examples/docker-service-with-elb/containers/container-definition.json","sha":"24cd7978210344f80257d578f5b3f08671762395"}]},{"name":"main.tf","path":"examples/docker-service-with-elb/main.tf","sha":"72883b000e2452b147ddf8286358a1eb6319a2eb"},{"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":"variables.tf","path":"examples/docker-service-with-elb/variables.tf","sha":"89d55cedb7ba91daed4d64e98fb129fb97ccd33b"}]},{"name":"docker-service-with-private-discovery","children":[{"name":"README.md","path":"examples/docker-service-with-private-discovery/README.md","sha":"0b4cca356ffaefda757ed87383292915dee15b45"},{"name":"containers","children":[{"name":"container-definition.json","path":"examples/docker-service-with-private-discovery/containers/container-definition.json","sha":"d83f91ccac477598cc51c3ce80a3a404e388dbf0"}]},{"name":"main.tf","path":"examples/docker-service-with-private-discovery/main.tf","sha":"9da040190c702d6dc7493bcd66106e7b3c6fbad1"},{"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":"variables.tf","path":"examples/docker-service-with-private-discovery/variables.tf","sha":"dc7faeb68bb8f6b9d002cc0ee1d75459fe4cd324"}]},{"name":"docker-service-with-public-discovery","children":[{"name":"README.md","path":"examples/docker-service-with-public-discovery/README.md","sha":"8240ca76c71446eaeff6549299107537b3c77961"},{"name":"containers","children":[{"name":"container-definition.json","path":"examples/docker-service-with-public-discovery/containers/container-definition.json","sha":"d83f91ccac477598cc51c3ce80a3a404e388dbf0"}]},{"name":"main.tf","path":"examples/docker-service-with-public-discovery/main.tf","sha":"99d9885a53b19fbf495766d1b1237ea2a7dba042"},{"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":"variables.tf","path":"examples/docker-service-with-public-discovery/variables.tf","sha":"59e7cc6a095de1bf8fefa19c7eb918964fca1610"}]},{"name":"docker-service-without-elb","children":[{"name":"README.md","path":"examples/docker-service-without-elb/README.md","sha":"0db4d357c7967144b176d0ac462d57313e3f061d"},{"name":"containers","children":[{"name":"container-definition.json","path":"examples/docker-service-without-elb/containers/container-definition.json","sha":"24cd7978210344f80257d578f5b3f08671762395"}]},{"name":"main.tf","path":"examples/docker-service-without-elb/main.tf","sha":"e5e8d7e410a79a499af27ca12b230293d7bbb382"},{"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":"variables.tf","path":"examples/docker-service-without-elb/variables.tf","sha":"0663828c7959ea063a544f60ce1996e6b6203728"}]},{"name":"docker-vpc-service-with-alb","children":[{"name":"README.md","path":"examples/docker-vpc-service-with-alb/README.md","sha":"654268efbb32c0c98dd1b020e6fedda4adbedb36"},{"name":"main.tf","path":"examples/docker-vpc-service-with-alb/main.tf","sha":"8152c9c26e81bd043c415aa8477738327ea4a2a1"},{"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":"variables.tf","path":"examples/docker-vpc-service-with-alb/variables.tf","sha":"7db799cde779942474d1612279f99bad4ca85a2f"}]},{"name":"example-docker-image","children":[{"name":"Dockerfile","path":"examples/example-docker-image/Dockerfile","sha":"e507f58e13693a2cd1b57f63cfc952f58469fb3e"},{"name":"README.md","path":"examples/example-docker-image/README.md","sha":"272b6c12cad7ba326582bfca11fce195912021c4"},{"name":"server.js","path":"examples/example-docker-image/server.js","sha":"6a0cd2caa4cd7ee9bc3a81249a0686cddda2b2f3"}]},{"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":"bb8f946ac8c4aff7dabd8ee89cfc975b7a00e012"}]},{"name":"example-vpc","children":[{"name":"README.md","path":"examples/example-vpc/README.md","sha":"d84ff0ae78abd7732973f26005c76c6aa0f73442"},{"name":"main.tf","path":"examples/example-vpc/main.tf","sha":"e5cc305ae6760c41b650d7f6e843924c22ff14fb"},{"name":"outputs.tf","path":"examples/example-vpc/outputs.tf","sha":"29fe3a59a33e3648c3cdf0afbcc6b7224e1b81ea"},{"name":"variables.tf","path":"examples/example-vpc/variables.tf","sha":"668e867d5bc0938a092cc35a52093d05ede78cfe"}]}]},{"name":"modules","children":[{"name":"ecs-cluster","children":[{"name":"README.md","path":"modules/ecs-cluster/README.md","sha":"6b944e332545ed63550145e59a3356156ac2576a","toggled":true},{"name":"main.tf","path":"modules/ecs-cluster/main.tf","sha":"ca5e062525d9fa4f3c5b737aea3173b33c4231fa"},{"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":"391b4f6d21b5d08e85159513cb5a3c5cefb0e8c2"},{"name":"variables.tf","path":"modules/ecs-cluster/variables.tf","sha":"03dc6e5cc890c1335172e2da0bc94cf79629f51c"}],"toggled":true},{"name":"ecs-daemon-service","children":[{"name":"README.md","path":"modules/ecs-daemon-service/README.md","sha":"3335d6f5fc8c250bed5682bd02910b309a87292a"},{"name":"main.tf","path":"modules/ecs-daemon-service/main.tf","sha":"48c8a5e7c21d574c6c37d5e5df11fe63c84f5061"},{"name":"outputs.tf","path":"modules/ecs-daemon-service/outputs.tf","sha":"b14be6c2f9498c05be9d3843437940b933b3b669"},{"name":"variables.tf","path":"modules/ecs-daemon-service/variables.tf","sha":"939c556009e98468ec9af8d32f821f2253e04f39"}]},{"name":"ecs-deploy-check-binaries","children":[{"name":"README.md","path":"modules/ecs-deploy-check-binaries/README.md","sha":"476b73eebe55f642ba46684e7d9765c0562ab8b9"},{"name":"bin","children":[{"name":"check-ecs-service-deployment","path":"modules/ecs-deploy-check-binaries/bin/check-ecs-service-deployment","sha":"6e556e9d064bf9d03c77bbd31f550cf9ed131981"},{"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":"08167bef81f28b383bd68fce0096d12d873f4843"},{"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":"e15d0efff63f204df8891b1d02e2236134d2d7ef"}]},{"name":"ecs-deploy","children":[{"name":"README.md","path":"modules/ecs-deploy/README.md","sha":"4bf327f86dab318ad23558afe0cb3d07be205083"},{"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":"fd24f00ac8a0f4cd37c42a589839f1230c45804a"}]},{"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":"0763095a74fe4a0123fdc74ff8611b6954351f84"},{"name":"README.adoc","path":"modules/ecs-service/README.adoc","sha":"418ebd6775f96616e0139638fdf356fe601d34e0"},{"name":"auto_scaling.tf","path":"modules/ecs-service/auto_scaling.tf","sha":"7131efebd7c0ecfa3a911576af589d56201345c5"},{"name":"core-concepts.md","path":"modules/ecs-service/core-concepts.md","sha":"2dd341838d6c35375e4e4ae5f287ab84511984a9"},{"name":"deployment_check.tf","path":"modules/ecs-service/deployment_check.tf","sha":"fbfef8291c0b904b5cd832b70ea839c5b6e65eef"},{"name":"elb.tf","path":"modules/ecs-service/elb.tf","sha":"e00440050a622d4a66df91c2315fcfc74693188d"},{"name":"main.tf","path":"modules/ecs-service/main.tf","sha":"fdfa495e25036936f9d0265c75bf33cd8080a91f"},{"name":"outputs.tf","path":"modules/ecs-service/outputs.tf","sha":"0323af2fbe25f6f72fbf409bf92f1d36fd317e67"},{"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":"73dd13d1c9470e820e024db0e1445bd4857166c9"},{"name":"variables.tf","path":"modules/ecs-service/variables.tf","sha":"2f360c0174e8c75af6e0c6720826fc8b844ddf54"}]},{"name":"ecs-task-scheduler","children":[{"name":"README.md","path":"modules/ecs-task-scheduler/README.md","sha":"4bd4b259b979fd7b20b600758f44abd3d4ed41a8"},{"name":"bin","children":[{"name":"check-ecs-tasks","path":"modules/ecs-task-scheduler/bin/check-ecs-tasks","sha":"a739a5da8710dcb348f33f47d919a68c61394c58"}]},{"name":"main.tf","path":"modules/ecs-task-scheduler/main.tf","sha":"57648ee9a28334185ab2ed9d50cb1652f1d85601"},{"name":"outputs.tf","path":"modules/ecs-task-scheduler/outputs.tf","sha":"b6a8d2137696a4a5a524d21be548c4702ce648e4"},{"name":"variables.tf","path":"modules/ecs-task-scheduler/variables.tf","sha":"ce70be84674a4645c87158090d713c4483f24aae"}]}],"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":"2a539a451e7fc594839829f5c25fe27dd799f52e"},{"name":"common","children":[{"name":"docker_service_failure_testing_utils.go","path":"test/common/docker_service_failure_testing_utils.go","sha":"e16b3371f04a6c0b6e05b3927cd102e1fd1cfccf"},{"name":"docker_service_utils.go","path":"test/common/docker_service_utils.go","sha":"b9bd1081dd81b99262db46368e606abdcec6e6d8"},{"name":"terratest_options.go","path":"test/common/terratest_options.go","sha":"ff2d7189bf154eb1250a1172fef743c27e2e44e8"},{"name":"test_helpers.go","path":"test/common/test_helpers.go","sha":"721bd358f2562398093c6e21229cf53371726cbd"}]},{"name":"ec2","children":[{"name":"deploy_ecs_scheduled_task_test.go","path":"test/ec2/deploy_ecs_scheduled_task_test.go","sha":"e76a1324f95bb6be3436d7f4a1bf1238658d957e"},{"name":"deploy_ecs_task_test.go","path":"test/ec2/deploy_ecs_task_test.go","sha":"41eb2e13f0620e3c4b65006ba3b739bc5200ae1d"},{"name":"docker_daemon_service_test.go","path":"test/ec2/docker_daemon_service_test.go","sha":"17f9071ef1d398ea34630f1150a5cc3a649b8582"},{"name":"docker_ec2_service_test.go","path":"test/ec2/docker_ec2_service_test.go","sha":"65d4ea3a0d5e20baeaf8a5b5e842c355dd91c1ee"},{"name":"docker_service_with_alb_and_nlb_test.go","path":"test/ec2/docker_service_with_alb_and_nlb_test.go","sha":"bd1b81611ecf54fb6d01a8bbb3104623951186a7"},{"name":"docker_service_with_alb_deployment_check_fail_test.go","path":"test/ec2/docker_service_with_alb_deployment_check_fail_test.go","sha":"641e0fd4475ac157ecae0863351a5a37bbd32109"},{"name":"docker_service_with_alb_test.go","path":"test/ec2/docker_service_with_alb_test.go","sha":"4870f37814afbffd84b9a9d089e2667d54ce7e1c"},{"name":"docker_service_with_autoscaling_test.go","path":"test/ec2/docker_service_with_autoscaling_test.go","sha":"95558be9bd7434d02f67fd63acd724603c0256ac"},{"name":"docker_service_with_canary_deployment_check_fail_test.go","path":"test/ec2/docker_service_with_canary_deployment_check_fail_test.go","sha":"bb5b13a28b0be05ecf9ab58361074eac574c7dd2"},{"name":"docker_service_with_canary_deployment_test.go","path":"test/ec2/docker_service_with_canary_deployment_test.go","sha":"9563b599a9c71a357428d9424e46b2ab8fab599d"},{"name":"docker_service_with_discovery_check_fail_test.go","path":"test/ec2/docker_service_with_discovery_check_fail_test.go","sha":"86cef5081c22df6bbaae74f32b41d2a625693ee8"},{"name":"docker_service_with_discovery_test.go","path":"test/ec2/docker_service_with_discovery_test.go","sha":"9b4d7262690ffef830331b0bbb769a077c3b6ea8"},{"name":"docker_service_with_elb_deployment_check_fail_test.go","path":"test/ec2/docker_service_with_elb_deployment_check_fail_test.go","sha":"95084370cb419e73911d9ae1a26a83f09d96262b"},{"name":"docker_service_with_elb_test.go","path":"test/ec2/docker_service_with_elb_test.go","sha":"031c553b2d9905770eb533dc5a7e244fa4a97a47"},{"name":"docker_service_without_elb_deployment_check_fail_test.go","path":"test/ec2/docker_service_without_elb_deployment_check_fail_test.go","sha":"50146027679868fb203061e27531716e05acf646"},{"name":"docker_service_without_elb_test.go","path":"test/ec2/docker_service_without_elb_test.go","sha":"443494f87c6583c9b5d689765f612cb36432f3ef"},{"name":"docker_vpc_service_with_alb_test.go","path":"test/ec2/docker_vpc_service_with_alb_test.go","sha":"a5206fdc66b80ce49dcd01fa5223c068d63133bf"},{"name":"ec2_amazon_linux2_test.go","path":"test/ec2/ec2_amazon_linux2_test.go","sha":"66360c7b21a64a44611b47a8deb908bef2d94407"},{"name":"terratest_options.go","path":"test/ec2/terratest_options.go","sha":"3f1135fb93058b32f911ec51114ea17d38d288f8"}]},{"name":"fargate","children":[{"name":"docker_fargate_service_alb_deployment_check_fail_by_container_test.go","path":"test/fargate/docker_fargate_service_alb_deployment_check_fail_by_container_test.go","sha":"cae40eba384db05ec8e994dee7f75916ef7c7e52"},{"name":"docker_fargate_service_nlb_deployment_check_fail_by_container_test.go","path":"test/fargate/docker_fargate_service_nlb_deployment_check_fail_by_container_test.go","sha":"bd43e7f186695a13a7c9fc4c7e04f5e5f481cc42"},{"name":"docker_fargate_service_with_alb_test.go","path":"test/fargate/docker_fargate_service_with_alb_test.go","sha":"f032257ac1c0afab9f29bdb85d831110f0cd255b"},{"name":"docker_fargate_service_with_efs_volume_test.go","path":"test/fargate/docker_fargate_service_with_efs_volume_test.go","sha":"6398577f85e2c043d22360d85177fb1cbf222efd"},{"name":"docker_fargate_service_with_nlb_test.go","path":"test/fargate/docker_fargate_service_with_nlb_test.go","sha":"2314a84cb16e7c417be7a3850ef044bcfdcd2826"},{"name":"docker_fargate_service_without_lb_deployment_check_fail_by_container_test.go","path":"test/fargate/docker_fargate_service_without_lb_deployment_check_fail_by_container_test.go","sha":"ef6dd4240594abec1a8a9f8d1d5141b4af1aceaf"},{"name":"docker_fargate_service_without_lb_test.go","path":"test/fargate/docker_fargate_service_without_lb_test.go","sha":"358a5c22c5b72f6013fb370eed8aabf5e53b9b23"},{"name":"docker_fargate_spot_service_with_alb_test.go","path":"test/fargate/docker_fargate_spot_service_with_alb_test.go","sha":"0db6cba4695864a8a8b47a374c48d9231958148c"},{"name":"terratest_options.go","path":"test/fargate/terratest_options.go","sha":"1be5ddaa4ca5f6908d0479c41f277ddf2bdbe240"}]},{"name":"go.mod","path":"test/go.mod","sha":"70b44e4690e58d4a4e44cb75ac3547caa61071ee"},{"name":"go.sum","path":"test/go.sum","sha":"4e9c6d3e43d5f9baff6b9dfdd7bf05af5f38fba2"},{"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":"f1b96782e711f3dbf230026ba91f78818299406f"},{"name":"test_check_ecs_service_deployment.py","path":"test/script_tests/test_check_ecs_service_deployment.py","sha":"31b07df008ef2409dd670cc7b9034244f97007ec"},{"name":"tox.ini","path":"test/script_tests/tox.ini","sha":"0777a50ac1fd8f6e44c25ac941d61a335a5e3d76"}]},{"name":"upgrades","children":[{"name":"upgrade_test.go","path":"test/upgrades/upgrade_test.go","sha":"8f5bac68ecb74b6d5d018f1b6f4d868441dfe3c8"}]},{"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.34.2/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.34.2/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.34.2/module-ecs/examples\" class=\"preview__body--description--blue\">examples</a> folder for example usage.</li>\n<li>See <a href=\"/repos/v0.34.2/module-ecs/modules/ecs-cluster/variables.tf\" class=\"preview__body--description--blue\">variables.tf</a> for all the variables you can set on this module.</li>\n<li>See the <a href=\"/repos/v0.34.2/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.34.2/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.34.2/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>pip3 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>python3 roll-<span class=\"hljs-keyword\">out</span>-ecs-<span class=\"hljs-keyword\">cluster</span>-<span class=\"hljs-keyword\">update</span>.py <span class=\"hljs-comment\">--asg-name ASG_NAME --cluster-name CLUSTER_NAME --aws-region AWS_REGION</span>\n</pre>\n<p>If you have your output variables configured as shown in <a href=\"/repos/v0.34.2/module-ecs/examples/docker-service-with-elb/outputs.tf\" class=\"preview__body--description--blue\">outputs.tf</a>\nof the <a href=\"/repos/v0.34.2/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>python3 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><strong>Note</strong>: during upgrade, if <code>desired_capacity * 2 > max_size</code> then ASG max size will be updated to <code>desired_capacity * 2</code> for the period of upgrade, to disable this behaviour - pass <code>--keep-max-size</code> argument.</p>\n<p>To avoid the need to install python dependencies on your local machine, you may choose 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 <span class=\"hljs-builtin-name\">run</span> \\\n -it --rm -v <span class=\"hljs-string\">\"<span class=\"hljs-variable\">$PWD</span>\"</span>:/usr/src -w /usr/src \\\n --env-file <(aws-vault exec <span class=\"hljs-attribute\">--assume-role-ttl</span>=1h<span class=\"hljs-built_in\"> PROFILE </span>-- env | grep AWS) \\\n python:3.10-alpine \\\n sh -c <span class=\"hljs-string\">\"pip3 install boto3 && python3 roll-out-ecs-cluster-update.py \\\n --asg-name ASG_NAME \\\n --cluster-name CLUSTER_NAME \\\n --aws-region AWS_REGION\"</span>\n</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-configure-cluster-autoscaling\">How do you configure cluster autoscaling?</h2>\n<p>ECS Clusters support two tiers of autoscaling:</p>\n<ul>\n<li>Autoscaling of ECS Service and Tasks, where ECS will horizontally or vertically scale your ECS Tasks by provisioning\nmore replicas of the Task or replacing them with Tasks that have more resources allocated to it.</li>\n<li>Autoscaling of the ECS Cluster, where the AWS Autoscaling Group will horizontally scale the worker nodes by\nprovisioning more.</li>\n</ul>\n<p>The <code>ecs-cluster</code> module supports configuring ECS Cluster Autoscaling by leveraging <a href=\"https://docs.aws.amazon.com/AmazonECS/latest/developerguide/cluster-capacity-providers.html\" class=\"preview__body--description--blue\" target=\"_blank\">ECS Capacity\nProviders</a>. You can read\nmore about how cluster autoscaling works with capacity providers in the <a href=\"https://docs.aws.amazon.com/AmazonECS/latest/developerguide/cluster-auto-scaling.html\" class=\"preview__body--description--blue\" target=\"_blank\">official\ndocumentation</a>.</p>\n<p>To enable capacity providers for cluster autoscaling on your ECS cluster, you will want to configure the following\nvariables:</p>\n<pre><span class=\"hljs-comment\"># Turn on capacity providers for autoscaling</span>\ncapacity_provider_enabled = true\n\n<span class=\"hljs-comment\"># Enable Multi AZ capacity providers to balance autoscaling load across AZs. This should be true in production. Can be</span>\n<span class=\"hljs-comment\"># false in dev and stage.</span>\nmulti_az_capacity_provider = true\n\n<span class=\"hljs-comment\"># Configure target utilization for the ECS cluster. This number influences when scale out happens, and when instances</span>\n<span class=\"hljs-comment\"># should be scaled in. For example, a setting of 90 means that new instances will be provisioned when all instances are</span>\n<span class=\"hljs-comment\"># at 90% utilization, while instances that are only 10% utilized (CPU and Memory usage from tasks = 10%) will be scaled</span>\n<span class=\"hljs-comment\"># in. A recommended default to start with is 90.</span>\ncapacity_provider_target = <span class=\"hljs-number\">90</span>\n\n<span class=\"hljs-comment\"># The following are optional configurations, and configures how many instances should be scaled out or scaled in at one</span>\n<span class=\"hljs-comment\"># time. Defaults to 1.</span>\n<span class=\"hljs-comment\"># capacity_provider_max_scale_step = 1</span>\n<span class=\"hljs-comment\"># capacity_provider_min_scale_step = 1</span>\n</pre>\n<h3 class=\"preview__body--subtitle\" id=\"note-on-toggling-capacity-providers-on-existing-ecs-clusters\">Note on toggling capacity providers on existing ECS Clusters</h3>\n<p>Each EC2 instance must be registered with Capacity Providers to be considered in the pool. This means that when you\nenable Capacity Providers on an existing ECS cluster that did not have Capacity Providers, you must rotate the EC2\ninstances to ensure all the instances get associated with the new Capacity Provider.</p>\n<p>To rotate the instances, you can run the\n<a href=\"/repos/v0.34.2/module-ecs/modules/ecs-cluster/roll-out-ecs-cluster-update.py\" class=\"preview__body--description--blue\">roll-out-ecs-cluster-update.py</a>\nscript in the <code>terraform-aws-ecs</code> module. Refer to the\n<a href=\"#how-do-you-make-changes-to-the-ec2-instances-in-the-cluster\" class=\"preview__body--description--blue\">documentation</a>\nfor more information on the script.</p>\n","repoName":"module-ecs","repoRef":"v0.34.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."}