Docker – TERRAFORM how do i have 1 ecs cluster with 2 or more ecs service/task definitions

amazon-ecsconsuldockerterraform

Using Terraform, I have tried the hardest to find out how to create 1 ECS cluster and have multiple services running under it. SO basically i have 2 different containers i want to run with this 1 ECS cluster.

How do i do this?
I have seen many examples but usually 1 service with 1 ECS cluster

So from this link i got a template https://www.terraform.io/docs/providers/aws/d/ecs_task_definition.html

# Simply specify the family to find the latest ACTIVE revision in that family.
data "aws_ecs_task_definition" "mongo" {
  task_definition = "${aws_ecs_task_definition.mongo.family}"
}

resource "aws_ecs_cluster" "foo" {
  name = "foo"
}

resource "aws_ecs_task_definition" "mongo" {
  family = "mongodb"

  container_definitions = <<DEFINITION
[
  {
    "cpu": 128,
    "environment": [{
      "name": "SECRET",
      "value": "KEY"
    }],
    "essential": true,
    "image": "mongo:latest",
    "memory": 128,
    "memoryReservation": 64,
    "name": "mongodb"
  }
]
DEFINITION
}

resource "aws_ecs_service" "mongo" {
  name          = "mongo"
  cluster       = "${aws_ecs_cluster.foo.id}"
  desired_count = 2

  # Track the latest ACTIVE revision
  task_definition = "${aws_ecs_task_definition.mongo.family}:${max("${aws_ecs_task_definition.mongo.revision}", "${data.aws_ecs_task_definition.mongo.revision}")}"
}

So lets say i want to add a node app service to that how will it look? And have them both run on the same cluster

Thanks!

Best Answer

You simply create another aws_ecs_service and aws_ecs_task_definition resources.

If you want it running on the same cluster, just specify the same cluster ID in the cluster param.

So it would look something like this

# Simply specify the family to find the latest ACTIVE revision in that family.
data "aws_ecs_task_definition" "mongo" {
  task_definition = "${aws_ecs_task_definition.mongo.family}"
}

data "aws_ecs_task_definition" "nginx" {
  task_definition = "${aws_ecs_task_definition.nginx.family}"
}

resource "aws_ecs_cluster" "foo" {
  name = "foo"
}


# ======================  TASKS ===================
resource "aws_ecs_task_definition" "mongo" {
  family = "mongodb"

  container_definitions = <<DEFINITION
[
  {
    "cpu": 128,
    "environment": [{
      "name": "SECRET",
      "value": "KEY"
    }],
    "essential": true,
    "image": "mongo:latest",
    "memory": 128,
    "memoryReservation": 64,
    "name": "mongodb"
  }
]
DEFINITION
}

resource "aws_ecs_task_definition" "nginx" {
  family = "nginx"

  container_definitions = <<DEFINITION
[
  {
    "cpu": 128,
    "environment": [{
      "name": "SECRET",
      "value": "KEY"
    }],
    "essential": true,
    "image": "nginx:latest",
    "memory": 128,
    "memoryReservation": 64,
    "name": "nginx"
  }
]
DEFINITION
}

# ======================  SERVICES ===================

resource "aws_ecs_service" "mongo" {
  name          = "mongo"
  cluster       = "${aws_ecs_cluster.foo.id}"
  desired_count = 2

  # Track the latest ACTIVE revision
  task_definition = "${aws_ecs_task_definition.mongo.family}:${max("${aws_ecs_task_definition.mongo.revision}", "${data.aws_ecs_task_definition.mongo.revision}")}"
}

resource "aws_ecs_service" "nginx" {
  name          = "nginx"
  cluster       = "${aws_ecs_cluster.foo.id}"
  desired_count = 2

  # Track the latest ACTIVE revision
  task_definition = "${aws_ecs_task_definition.nginx.family}:${max("${aws_ecs_task_definition.nginx.revision}", "${data.aws_ecs_task_definition.nginx.revision}")}"
}

There is another way of running multiple containers on ECS.

You can place both Nginx and MongoDB on the same instance and under the same Task/Service.

It would look like this

# Simply specify the family to find the latest ACTIVE revision in that family.
data "aws_ecs_task_definition" "webapp" {
  task_definition = "${aws_ecs_task_definition.webapp.family}"
}

resource "aws_ecs_cluster" "foo" {
  name = "foo"
}


# ======================  TASKS ===================

resource "aws_ecs_task_definition" "webapp" {
  family = "webapp"

  container_definitions = <<DEFINITION
[
  {
    "cpu": 128,
    "environment": [{
      "name": "SECRET",
      "value": "KEY"
    }],
    "essential": true,
    "image": "nginx:latest",
    "memory": 128,
    "memoryReservation": 64,
    "name": "nginx"
  },
  {
    "cpu": 128,
    "environment": [{
      "name": "SECRET",
      "value": "KEY"
    }],
    "essential": true,
    "image": "mongo:latest",
    "memory": 128,
    "memoryReservation": 64,
    "name": "mongodb"
  }
]
DEFINITION
}

# ======================  SERVICES ===================

resource "aws_ecs_service" "webapp" {
  name          = "webapp"
  cluster       = "${aws_ecs_cluster.foo.id}"
  desired_count = 1

  # Track the latest ACTIVE revision
  task_definition = "${aws_ecs_task_definition.webapp.family}:${max("${aws_ecs_task_definition.webapp.revision}", "${data.aws_ecs_task_definition.webapp.revision}")}"
}

The advantage of the first method is that you can scale and manage each container independently.

The advantage of the second method is that the containers will be placed on the same EC2 instance and can be linked but can not be scaled independently. When you set desired count to N, you will get N number of "webapp" (so both Nginx and MongoDB instances). With the first method you can have N number of Nginx and X number of MongoDB.

Hope this helps.

NOTE : Terraform code has not been tested.