--- layout: docs page_title: Migrate Existing Tasks - AWS ECS description: >- Migrate Existing Tasks --- # Migrate Existing Tasks This guide explains how to migrate your existing ECS Tasks to use our [`mesh-task` Terraform module](https://registry.terraform.io/modules/hashicorp/consul-ecs/aws/latest/submodules/mesh-task). ## Define Tasks in Terraform Your tasks must first be specified in Terraform using [`ecs_task_definition`](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ecs_task_definition) and [`ecs_service`](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ecs_service) resources so that they can later be converted to use the [`mesh-task` module](https://registry.terraform.io/modules/hashicorp/consul-ecs/aws/latest/submodules/mesh-task). For example, your tasks should be defined with Terraform similar to the following: ```hcl resource "aws_ecs_task_definition" "my_task" { family = "my_task" requires_compatibilities = ["FARGATE"] network_mode = "awsvpc" cpu = 256 memory = 512 execution_role_arn = "arn:aws:iam::111111111111:role/execution-role" task_role_arn = "arn:aws:iam::111111111111:role/task-role" container_definitions = jsonencode( [{ name = "example-client-app" image = "docker.io/org/my_task:v0.0.1" essential = true portMappings = [ { containerPort = 9090 hostPort = 9090 protocol = "tcp" } ] cpu = 0 mountPoints = [] volumesFrom = [] }] ) } resource "aws_ecs_service" "my_task" { name = "my_task" cluster = "arn:aws:ecs:us-east-1:111111111111:cluster/my-cluster" task_definition = aws_ecs_task_definition.my_task.arn desired_count = 1 network_configuration { subnets = ["subnet-abc123"] } launch_type = "FARGATE" } ``` ## Convert Tasks to Mesh Module In order to add the necessary sidecar containers for your task to join the mesh, you must use the [`mesh-task` module](https://registry.terraform.io/modules/hashicorp/consul-ecs/aws/latest/submodules/mesh-task). The `mesh-task` module uses inputs similar to your old ECS task definition but creates a new version of the task definition with additional containers. The `mesh-task` module is used as follows: ```hcl module "my_task" { source = "hashicorp/consul/aws-ecs//modules/mesh-task" version = "" family = "my_task" container_definitions = [ { name = "example-client-app" image = "docker.io/org/my_task:v0.0.1" essential = true portMappings = [ { containerPort = 9090 hostPort = 9090 protocol = "tcp" } ] cpu = 0 mountPoints = [] volumesFrom = [] } ] port = "9090" retry_join = "
" } ``` All possible inputs are documented on the [module reference documentation](https://registry.terraform.io/modules/hashicorp/consul-ecs/aws/latest/submodules/mesh-task?tab=inputs) however there are some important inputs worth highlighting: - You do not need the `execution_role_arn` or `task_role_arn` fields. The `mesh-task` module will create the task and execution roles. - `family` is used as the [task definition family](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_definition_parameters.html#family) and the name of the service that is registered in Consul. - `container_definitions` accepts an array of [container definitions](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_definition_parameters.html#container_definitions). These are your application containers and are the same as `container_definitions` key in the `aws_ecs_task_definition` resource without the `jsonencode() function`. For example, if your original task definition looked like: ```hcl resource "aws_ecs_task_definition" "my_task" { ... container_definitions = jsonencode( [ { name = "example-client-app" image = "docker.io/org/my_task:v0.0.1" essential = true ... } ] ) } ``` Then remove the `jsonencode()` function and use the rest of the value as the input for the `mesh-task` module: ```hcl module "my_task" { source = "hashicorp/consul/aws-ecs//modules/mesh-task" version = "" ... container_definitions = [ { name = "example-client-app" image = "docker.io/org/my_task:v0.0.1" essential = true ... } ] } ``` - `port` is the port that your application listens on. This should be set to a string, not an integer, i.e. `port = "9090"`, not `port = 9090`. - `retry_join` is passed to the `-retry-join` option for the Consul agent. This tells the agent the location of your Consul server so that it can join the Consul cluster. The `mesh-task` module will create a new version of your task definition with the necessary sidecar containers added so you can delete your existing `aws_ecs_task_definition` resource. Your `aws_ecs_service` resource can remain unchanged except for the `task_definition` input which should reference the new module's output of the task definition's ARN: ```hcl resource "aws_ecs_service" "my_task" { ... task_definition = module.my_task.task_definition_arn } ``` -> **NOTE:** If your tasks run in a public subnet, they must have `assign_public_ip = true` in their [`network_configuration`](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ecs_service#network_configuration) block so that ECS can pull the Docker images. After running `terraform apply`, you should see your tasks registered in the Consul UI. ## Complete Installation Now that your task(s) are migrated to the `mesh-task` module, see the [Install Guide](/docs/ecs/get-started/install) to install Consul on ECS.