Browse the Repo

file-type-icon.circleci
file-type-icon_docs
file-type-iconexamples
file-type-iconmodules
file-type-iconecs-cluster
file-type-iconREADME.md
file-type-iconmain.tf
file-type-iconoutputs.tf
file-type-iconroll-out-ecs-cluster-update.py
file-type-iconvars.tf
file-type-iconecs-daemon-service
file-type-iconecs-deploy-check-binaries
file-type-iconecs-deploy
file-type-iconecs-fargate
file-type-iconecs-scripts
file-type-iconecs-service-with-alb
file-type-iconecs-service-with-discovery
file-type-iconecs-service
file-type-icontest
file-type-icon.gitignore
file-type-icon.pre-commit-config.yaml
file-type-iconCODEOWNERS
file-type-iconLICENSE.txt
file-type-iconREADME.adoc
file-type-iconcore-concepts.md
file-type-iconsetup.cfg

Browse the Repo

file-type-icon.circleci
file-type-icon_docs
file-type-iconexamples
file-type-iconmodules
file-type-iconecs-cluster
file-type-iconREADME.md
file-type-iconmain.tf
file-type-iconoutputs.tf
file-type-iconroll-out-ecs-cluster-update.py
file-type-iconvars.tf
file-type-iconecs-daemon-service
file-type-iconecs-deploy-check-binaries
file-type-iconecs-deploy
file-type-iconecs-fargate
file-type-iconecs-scripts
file-type-iconecs-service-with-alb
file-type-iconecs-service-with-discovery
file-type-iconecs-service
file-type-icontest
file-type-icon.gitignore
file-type-icon.pre-commit-config.yaml
file-type-iconCODEOWNERS
file-type-iconLICENSE.txt
file-type-iconREADME.adoc
file-type-iconcore-concepts.md
file-type-iconsetup.cfg
ECS Service

ECS Service

Deploy an ECS service with zero-downtime, rolling deployment, IAM Role, auto scaling, and more.

Code Preview

Preview the Code

mobile file icon

README.md

down

ECS Cluster Module

This Terraform Module launches an EC2 Container Service Cluster that you can use to run Docker containers and services (see the ecs-service module).

How do you use this module?

  • See the root README for instructions on using Terraform modules.
  • See the examples folder for example usage.
  • 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.

How do you run Docker containers on the cluster?

See the service module.

How do you add additional security group rules?

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:

module "ecs_cluster" {
  # (arguments omitted)
}

resource "aws_security_group_rule" "allow_inbound_http_from_anywhere" {
  type = "ingress"
  from_port = 8080
  to_port = 8080
  protocol = "tcp"
  cidr_blocks = ["0.0.0.0/0"]

  security_group_id = "${module.ecs_cluster.ecs_instance_security_group_id}"
}

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:

module "ecs_cluster" {
  # (arguments omitted)
}

resource "aws_iam_role_policy" "access_s3_bucket" {
    name = "access_s3_bucket"
    role = "${module.ecs_cluster.ecs_instance_iam_role_name}"
    policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "",
      "Effect":"Allow",
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::examplebucket/*"
    }
  ]
}
EOF
}

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:

  1. 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.

  2. Update the Terraform code with your changes (e.g. update the cluster_instance_ami variable to a new AMI).

  3. Run terraform apply.

  4. Run the script:

    python roll-out-ecs-cluster-update.py --asg-name ASG_NAME --cluster-name CLUSTER_NAME --aws-region AWS_REGION
    

    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:

    python roll-out-ecs-cluster-update.py \
      --asg-name $(terragrunt output -no-color asg_name) \
      --cluster-name $(terragrunt output -no-color ecs_cluster_name) \
      --aws-region $(terragrunt output -no-color aws_region)
    

To avoid the need to install python dependencies on your local machine, you may chose to use docker.

  1. Navigate to the directory that you have downloaded roll-out-ecs-cluster-update.py:

  2. 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

    docker run \
        -it --rm -v "$PWD":/usr/src -w /usr/src \
        --env-file <(aws-vault exec --assume-role-ttl=1h PROFIE -- env | grep AWS) \
        python:2.7-alpine \
        sh -c "pip install boto3 && python roll-out-ecs-cluster-update.py \
        --asg-name ASG_NAME \
        --cluster-name CLUSTER_NAME \
        --aws-region AWS_REGION"
    

How roll-out-ecs-cluster-update.py works

The roll-out-ecs-cluster-update.py script does the following:

  1. 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.
  2. Put all the old ECS Instances in DRAINING state so all ECS Tasks are migrated off of them to the new Instances.
  3. Wait for all ECS Tasks to migrate off the old Instances.
  4. Set the desired capacity of the Auto Scaling Group back to its original value.

Questions? Ask away.

We're here to talk about our services, answer any questions, give advice, or just to chat.

Ready to hand off the Gruntwork?