Skip to content
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.terraform
terraform.tfstate
*.tfstate*
terraform.tfvars
todo.txt
39 changes: 38 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,42 @@
# terraform-aws-ecs

Terraform module which creates AWS ECS resources

This module focuses purely on ECS and nothing else. Therefore only these resources can be created with this module:

* [ECS](https://www.terraform.io/docs/providers/aws/r/ecs_cluster.html)
* [IAM](https://www.terraform.io/docs/providers/aws/r/iam_instance_profile.html)

However, having said the above to have a proper ECS cluster up and running multiple resources are needed. In most cases creating these resources is heavily opinionated and or context-bound. That is why this module does not create these resources. But you still need them to have a production ready environment. Therefore the example area shows how to create everything needed for a production environment.

## Usage

```hcl
module "ecs" {
source = "terraform-aws-modules/ecs/aws"

name = "my-ecs"
}
```

## Conditional creation

Sometimes you need to have a way to create ECS resources conditionally but Terraform does not allow to use `count` inside `module` block, so the solution is to specify argument `create_ecs`.

```hcl
# ECS cluster will not be created
module "ecs" {
source = "terraform-aws-modules/ecs/aws"

create_ecs = false
# ... omitted
}
```

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a section Examples to describe each kind of example.

## Examples

* [Complete ECS](https://github.com/terraform-aws-modules/terraform-aws-ecs/tree/master/examples/complete-ecs)

## License

**WORK IN PROGRESS**
Apache 2 Licensed. See LICENSE for full details.
39 changes: 39 additions & 0 deletions examples/complete-ecs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Complete ECS

This example uses only verified Terraform modules to create all resources that are needed for an ECS cluster that is sufficient for staging or production environment.

While this example is still in the early stage there are other repositories that show how to create an ECS cluster:

* <https://github.com/anrim/terraform-aws-ecs>
* <https://github.com/arminc/terraform-ecs>
* <https://github.com/alex/ecs-terraform>
* <https://github.com/Capgemini/terraform-amazon-ecs>

## TODO

Things still needed in the example:

* AWS network infrastructure on what is created
* Full explanation on why certain resources are created
* Create EC2 instance specific SecurityGroup instead of using the default one from VPC module
* Push logs of default EC2 stuff (docker, ecs agent, etc...) to CloudWatch logs
* Add an example with ALB
* Add an example with NLB
* Add an example with ELB
* Create a Fargate example

## Usage

To run this example you need to execute:

```bash
terraform init
terraform plan
terraform apply
```

Note that this example may create resources which can cost money (AWS EC2 instances, for example). Run `terraform destroy` when you don't need these resources.

## Explanation

Current version creates an high-available VPC with instances that are attached to ECS. ECS tasks can be run on these instances but they are not exposed to anything.
113 changes: 113 additions & 0 deletions examples/complete-ecs/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
provider "aws" {
region = "eu-west-1"
}

provider "terraform" {}

locals {
name = "complete-ecs"
environment = "dev"

# This is the convention we use to know what belongs to each other
ec2_resources_name = "${local.name}-${local.environment}"
}

module "vpc" {
source = "terraform-aws-modules/vpc/aws"

name = "${local.name}"

cidr = "10.1.0.0/16"

azs = ["eu-west-1a", "eu-west-1b"]
private_subnets = ["10.1.1.0/24", "10.1.2.0/24"]
public_subnets = ["10.1.11.0/24", "10.1.12.0/24"]

enable_nat_gateway = true
single_nat_gateway = true

tags = {
Environment = "${local.name}"
Name = "${local.name}"
}
}

#----- ECS --------
module "ecs" {
source = "../../"
name = "${local.name}"
}

module "ec2-profile" {
source = "../../modules/ecs-instance-profile"
name = "${local.name}"
}

#----- ECS Services--------

module "hello-world" {
source = "service-hello-world"
cluser_id = "${module.ecs.ecs_cluster_id}"
}

#----- ECS Resources--------

#For now we only use the AWS ECS optimized ami <https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs-optimized_AMI.html>
data "aws_ami" "amazon_linux_ecs" {
most_recent = true

filter {
name = "name"
values = ["amzn-ami-*-amazon-ecs-optimized"]
}

filter {
name = "owner-alias"
values = ["amazon"]
}
}

module "this" {
source = "terraform-aws-modules/autoscaling/aws"

name = "${local.ec2_resources_name}"

# Launch configuration
lc_name = "${local.ec2_resources_name}"

image_id = "${data.aws_ami.amazon_linux_ecs.id}"
instance_type = "t2.micro"
security_groups = ["${module.vpc.default_security_group_id}"]
iam_instance_profile = "${module.ec2-profile.instance_profile_id}"
user_data = "${data.template_file.user_data.rendered}"

# Auto scaling group
asg_name = "${local.ec2_resources_name}"
vpc_zone_identifier = "${module.vpc.private_subnets}"
health_check_type = "EC2"
min_size = 0
max_size = 1
desired_capacity = 1
wait_for_capacity_timeout = 0

tags = [
{
key = "Environment"
value = "${local.environment}"
propagate_at_launch = true
},
{
key = "Cluster"
value = "${local.name}"
propagate_at_launch = true
},
]
}

data "template_file" "user_data" {
template = "${file("${path.module}/templates/user-data.sh")}"

vars {
cluster_name = "${local.name}"
}
}
38 changes: 38 additions & 0 deletions examples/complete-ecs/service-hello-world/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
resource "aws_cloudwatch_log_group" "hello_world" {
name = "hello_world"
retention_in_days = 1
}

resource "aws_ecs_task_definition" "hello_world" {
family = "hello_world"

container_definitions = <<EOF
[
{
"name": "hello_world",
"image": "hello-world",
"cpu": 0,
"memory": 128,
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-region": "eu-west-1",
"awslogs-group": "hello_world",
"awslogs-stream-prefix": "complete-ecs"
}
}
}
]
EOF
}

resource "aws_ecs_service" "hello_world" {
name = "hello_world"
cluster = "${var.cluser_id}"
task_definition = "${aws_ecs_task_definition.hello_world.arn}"

desired_count = 1

deployment_maximum_percent = 100
deployment_minimum_healthy_percent = 0
}
3 changes: 3 additions & 0 deletions examples/complete-ecs/service-hello-world/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
variable "cluser_id" {
description = "The ECS cluster ID"
}
10 changes: 10 additions & 0 deletions examples/complete-ecs/templates/user-data.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#!/bin/bash

# ECS config
{
echo "ECS_CLUSTER=${cluster_name}"
} >> /etc/ecs/ecs.config

start ecs

echo "Done"
13 changes: 13 additions & 0 deletions main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
terraform {
required_version = ">= 0.11.7"
}

provider "template" {
version = ">= 1.0.0"
}

resource "aws_ecs_cluster" "this" {
count = "${var.create_ecs ? 1 : 0}"

name = "${var.name}"
}
7 changes: 7 additions & 0 deletions modules/ecs-instance-profile/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# ECS instance policy

For an EC2 instance to connect itself to ECS it needs rights to do so.

* [Why do we need ECS instance policies?](http://docs.aws.amazon.com/AmazonECS/latest/developerguide/instance_IAM_role.html)
* [ECS roles explained](http://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs_managed_policies.html)
* [More ECS policy examples explained](http://docs.aws.amazon.com/AmazonECS/latest/developerguide/IAMPolicyExamples.html)
34 changes: 34 additions & 0 deletions modules/ecs-instance-profile/instance-policy.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
resource "aws_iam_role" "this" {
name = "${var.name}_ecs_instance_role"
path = "/ecs/"

assume_role_policy = <<EOF
{
"Version": "2008-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": ["ec2.amazonaws.com"]
},
"Effect": "Allow"
}
]
}
EOF
}

resource "aws_iam_instance_profile" "this" {
name = "${var.name}_ecs_instance_profile"
role = "${aws_iam_role.this.name}"
}

resource "aws_iam_role_policy_attachment" "ecs_ec2_role" {
role = "${aws_iam_role.this.id}"
policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonEC2ContainerServiceforEC2Role"
}

resource "aws_iam_role_policy_attachment" "ecs_ec2_cloudwatch_role" {
role = "${aws_iam_role.this.id}"
policy_arn = "arn:aws:iam::aws:policy/CloudWatchLogsFullAccess"
}
3 changes: 3 additions & 0 deletions modules/ecs-instance-profile/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
output "instance_profile_id" {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Name it this_iam_instance_profile_id

value = "${aws_iam_instance_profile.this.id}"
}
3 changes: 3 additions & 0 deletions modules/ecs-instance-profile/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
variable "name" {
description = "Name to be used on all the resources as identifier"
}
3 changes: 3 additions & 0 deletions outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
output "ecs_cluster_id" {
value = "${element(concat(aws_ecs_cluster.this.*.id, list("")), 0)}"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Name this this_ecs_cluster_id

}
8 changes: 8 additions & 0 deletions variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
variable "create_ecs" {
description = "Controls if ECS should be created"
default = true
}

variable "name" {
description = "Name to be used on all the resources as identifier, also the name of the ECS cluster"
}