From 4414cb395c06cb17b48c4b6823c10956aa6ebdc3 Mon Sep 17 00:00:00 2001 From: Paul Glass Date: Tue, 18 Jan 2022 14:52:40 -0600 Subject: [PATCH] docs: Manual installation of Consul on ECS --- .../content/docs/ecs/install-no-terraform.mdx | 492 ++++++++++++++++++ website/content/docs/ecs/install.mdx | 97 ++-- website/content/docs/ecs/requirements.mdx | 12 +- website/data/docs-nav-data.json | 6 +- 4 files changed, 565 insertions(+), 42 deletions(-) create mode 100644 website/content/docs/ecs/install-no-terraform.mdx diff --git a/website/content/docs/ecs/install-no-terraform.mdx b/website/content/docs/ecs/install-no-terraform.mdx new file mode 100644 index 0000000000..5f6378eafb --- /dev/null +++ b/website/content/docs/ecs/install-no-terraform.mdx @@ -0,0 +1,492 @@ +--- +layout: docs +page_title: Manual Installation - AWS ECS +description: >- + Manually Install Consul Service Mesh on AWS ECS (Elastic Container Service). +--- + +# Manual Installation + +While the [Consul ECS Terraform module](/docs/ecs/install) is the easiest way to use Consul on ECS, +this page will describe how to directly create the ECS task definition using the [`consul-ecs` Docker image](https://gallery.ecr.aws/hashicorp/consul-ecs) +for use without Terraform. + +## Pre-requisites + +* This page assumes you are familiar with AWS ECS. See [What is Amazon Elastic Container Service](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/Welcome.html) for more details. +* This page does not show how to create all necessary AWS resources, such as a VPC or the ECS Cluster. + For complete runnable examples, see the links in the [Getting Started](/docs/ecs#getting-started) section. + +# Task Definition + +You must define a Task Definition which includes the following containers: + +* Your application container +* An Envoy sidecar-proxy container +* A Consul Agent container +* The `consul-ecs-mesh-init` container for service mesh setup +* Optionally, a `consul-ecs-health-sync` container to sync ECS health checks into Consul + +## Top-level fields + +In your task definition, you'll need to define these important top-level fields: + +```json +{ + "family": "my-example-client-app", + "networkMode": "awsvpc", + "volumes": [ + { + "name": "consul_data", + }, + { + "name": "consul_binary", + } + ], + "containerDefinitions": [...] +} +``` + +| Field name | Type | Description | +| ------------- | ------ | --------------------------------------------------------------------------------------------------- | +| `family` | string | The task family name. This is used as the Consul service name, by default. | +| `networkMode` | string | Must be `awsvpc`, which is the only network mode supported by Consul on ECS. | +| `volumes` | list | These are volumes used to share information between containers, which is important for setup steps. | +| `containerDefinitions` | list | The list of containers to run in this task (see below). | + +## Application container + +First, include your application container in the `containerDefinitions` list +in the task definition: + +```json +{ + "containerDefinitions": [ + { + "name": "example-client-app", + "image": "docker.io/org/my_task:v0.0.1", + "essential": true, + "dependsOn": [ + { + "containerName": "consul-ecs-mesh-init", + "condition": "SUCCESS" + }, + { + "containerName": "sidecar-proxy", + "condition": "HEALTHY" + } + ] + } + ] +} +``` + +| Field name | Type | Description | +| ----------- | ------- | ------------------------------------------------------------------------------------------------------------------------ | +| `name` | string | The name of your application container. | +| `image` | string | The container image used to run your application. | +| `essential` | boolean | Set this to `true` ensures your application container ties into the health of the task. All tasks must have at least one essential container. | +| `dependsOn` | list | Container dependendencies are used to ensure the service mesh is ready before your application starts. | + +See the [ECS Task Definition](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_definition_parameters.html) documentation for a complete reference. + +## `sidecar-proxy` container + +The sidecar proxy container runs [Envoy proxy](/docs/connect/proxies/envoy) for Consul Connect. + +```json +{ + "containerDefinitions": [ + { + "name": "example-client-app", + "image": "docker.io/org/my_task:v0.0.1", + ... + }, + { + "name": "sidecar-proxy", + "image": "envoyproxy/envoy-alpine:", + "essential": false, + "dependsOn": [ + { + "containerName": "consul-ecs-mesh-init", + "condition": "SUCCESS" + } + ], + "healthCheck": { + "retries": 3, + "command": ["nc", "-z", "127.0.0.1", "20000"], + "timeout": 5, + "interval": 30 + }, + "mountPoints": [ + { + "readOnly": true, + "containerPath": "/consul", + "sourceVolume": "consul_data" + } + ], + "ulimits": [ + { + "name": "nofile", + "softLimit": 1048576, + "hardLimit": 1048576 + } + ], + "command": ["envoy", "--config-path", "/consul/envoy-bootstrap.json"], + "entryPoint": ["/consul/consul-ecs", "envoy-entrypoint"], + } + ] +} +``` + +| Field name | Type | Description | +| ----------- | ------- | ------------------------------------------------------------------------------------------------------------------ | +| `name` | string | The name of the container, which should always be `sidecar-proxy`. | +| `image` | string | The container image for Envoy. We recommend using `envoyproxy/envoy-alpine`. | +| `dependsOn` | list | Envoy must start after `consul-ecs-mesh-init`, which creates the bootstrap configuration file for Envoy. | +| `healthCheck` | list | A health check should be definied for Envoy's primary listener port. | +| `mountPoints` | list | The mounts the `/consul` data volume which contains the Envoy configuration file. | +| `ulimits` | list | Set the file descriptor limit, `nofile`, to a sufficiently high value so that Envoy does not fail to open sockets. | +| `entrypoint` | list | A custom entrypoint binary is used to help facilitate graceful shutdown. | +| `command` | list | The startup command. This passes the bootstrap configuration to Envoy. | + +-> **NOTE**: Envoy and Consul must be compatible versions. See the [supported versions of Envoy](https://www.consul.io/docs/connect/proxies/envoy#supported-versions) for each Consul release. + + +## `consul-client` container + +Each task must include a Consul agent container in order for the task to join your Consul cluster. + +```json +{ + "containerDefinitions": [ + { + "name": "example-client-app", + "image": "docker.io/org/my_task:v0.0.1", + ... + }, + { + "name": "sidecar-proxy", + "image": "envoyproxy/envoy-alpine:", + ... + } + { + "name": "consul-client" + "image": "public.ecr.aws/hashicorp/consul:", + "mountPoints": [ + { + "readOnly": false, + "containerPath": "/consul", + "sourceVolume": "consul_data" + }, + { + "containerPath": "/bin/consul-inject", + "sourceVolume": "consul_binary" + } + ], + "entryPoint": ["/bin/sh", "-ec"], + "command": [ + "cp /bin/consul /bin/consul-inject/consul\n\nECS_IPV4=$(curl -s $ECS_CONTAINER_METADATA_URI_V4 | jq -r '.Networks[0].IPv4Addresses[0]')\n\n\ncat << EOF > /consul/agent-defaults.hcl\naddresses = {\n dns = \"127.0.0.1\"\n grpc = \"127.0.0.1\"\n http = \"127.0.0.1\"\n}\nadvertise_addr = \"$ECS_IPV4\"\nadvertise_reconnect_timeout = \"15m\"\nclient_addr = \"0.0.0.0\"\ndatacenter = \"dc1\"\nenable_central_service_config = true\nleave_on_terminate = true\nports {\n grpc = 8502\n}\nretry_join = [\n \"",\n]\ntelemetry {\n disable_compat_1.9 = true\n}\n\nEOF\n\ncat << EOF > /consul/agent-extra.hcl\naddresses = {\n dns = \"0.0.0.0\"\n}\nlog_level = \"debug\"\n\nEOF\n\nexec consul agent \\\n -data-dir /consul/data \\\n -config-file /consul/agent-defaults.hcl \\\n -config-file /consul/agent-extra.hcl\n" + ] + } + ] +} +``` + +| Field name | Type | Description | +| ----------- | ------- | ------------------------------------------------------------------------------------------------------------------------ | +| `name` | string | The name of the Consul agent container, which should always be `consul-client`. | +| `image` | string | The container image for Consul. Use our public AWS registry, `public.ecr.aws/hashicorp/consul`, to avoid rate limits. | +| `mountPoints` | list | The mounts the `/consul` data volume which contains the Envoy configuration file. | +| `ulimits` | list | Set the file descriptor limit, `nofile`, to a sufficiently high value so that Envoy does not fail to open sockets. | +| `entrypoint` | list | A custom entrypoint binary is used to run Envoy, in order to facilitate graceful shutdown. | +| `command` | list | The startup command. See below for details. + +The following is the recommended `command` script for the Consul agent. +This is the same as the above `command` field, but is unescaped and has comments added. + +```shell +# Copy the consul binary to a shared volume for mesh-init to use to generate Envoy configuration. +cp /bin/consul /bin/consul-inject/consul + +# At runtime, determine the IP address assigned to this ECS Task. +ECS_IPV4=$(curl -s $ECS_CONTAINER_METADATA_URI_V4 | jq -r '.Networks[0].IPv4Addresses[0]') + +# Define the Consul agent configuration file. +cat << EOF > /consul/agent-defaults.hcl +addresses = { + dns = "127.0.0.1" + grpc = "127.0.0.1" + http = "127.0.0.1" +} +advertise_addr = "$ECS_IPV4" +advertise_reconnect_timeout = "15m" +client_addr = "0.0.0.0" +datacenter = "dc1" +enable_central_service_config = true +leave_on_terminate = true +ports { + grpc = 8502 +} +retry_join = [""] +telemetry { + disable_compat_1.9 = true +} + +EOF + +# Start the consul agent. +exec consul agent \ + -data-dir /consul/data \ + -config-file /consul/agent-defaults.hcl +``` + +You can tailor the configuration above for your use case, but it's important to set the following fields as show: + +| Field name | Type | Description | +| -------------------- | ------- | ------------------------------------------------------------------------------------------------------------ | +| `addresses.*` | strings | Set the DNS, GRPC, and HTTP addresses to `127.0.0.1` to ensure these are not accessible outside of the task. | +| `advertise_addr` | string | This must be set to the task IP address so that other Consul agents know how to reach this agent. | +| `client_addr` | string | This must bind to an interface reacable by other Consul agents. | +| `leave_on_terminate` | boolean | This ensures this Consul agent will leave the cluster gracefully before exiting. | +| `retry_join` | string | This must be set to your Consul server location(s) so this agent can join the Consul cluster. | + +-> **NOTE**: It is important to use `exec` to start the Consul agent, so that the Consul agent runs as PID 1. This ensures +the Consul agent directly receives signals from ECS, which is important for graceful shutdown of the Consul agent. + +## `mesh-init` container + +The mesh-init container runs at task startup to setup this instance for Consul service mesh. +It will register this service and proxy with Consul and write Envoy bootstrap configuration +to a shared volume. + +```json +{ + "containerDefinitions": [ + { + "name": "example-client-app", + "image": "docker.io/org/my_task:v0.0.1", + ... + }, + { + "name": "sidecar-proxy", + "image": "envoyproxy/envoy-alpine:", + ... + }, + { + "name": "consul-client" + "image": "public.ecr.aws/hashicorp/consul:", + ... + }, + { + "name": "consul-ecs-mesh-init", + "image": "public.ecr.aws/hashicorp/consul-ecs:", + "command": ["mesh-init"], + "essential": false, + "environment": [ + { + "name": "CONSUL_ECS_CONFIG_JSON", + "value": "{\"bootstrapDir\":\"/consul\",\"healthSyncContainers\":[],\"proxy\":{\"upstreams\":[{\"destinationName\":\"example-server-app\",\"localBindPort\":1234}]},\"service\":{\"checks\":[],\"meta\":{},\"name\":\"example-client-app\",\"port\":9090,\"tags\":[]}}" + } + ], + "mountPoints": [ + { + "readOnly": false, + "containerPath": "/consul", + "sourceVolume": "consul_data" + }, + { + "readOnly": true, + "containerPath": "/bin/consul-inject", + "sourceVolume": "consul_binary" + } + ] + } + ] +} +``` + +| Field name | Type | Description | +| ----------- | ------- | ---------------------------------------------------------------------------------------------------------------------------- | +| `name` | string | The container name should be `consul-ecs-mesh-init`. | +| `image` | string | The `consul-ecs` image. Use our public AWS registry, `public.ecr.aws/hashicorp/consul-ecs`, to avoid rate limits. | +| `mountPoints` | list | The mounts two volumes so that mesh-init can invoke the `consul` binary to write bootstrap Envoy configuration. | +| `command` | list | Set the `["mesh-init"]` so that the container runs the `consul-ecs mesh-init` command. | +| `environment` | list | This must include the `CONSUL_ECS_CONFIG_JSON` variable. See below for details. | + +Additional configuration is passed to the `consul-ecs mesh-init` command in JSON format using the `CONSUL_ECS_CONFIG_JSON` environment variable. +Here is the sample config from above, expanded to be readable: + +```json +{ + "bootstrapDir": "/consul", + "healthSyncContainers": [], + "proxy": { + "upstreams": [ + { + "destinationName": "example-server-app", + "localBindPort": 1234 + } + ] + }, + "service": { + "checks": [], + "meta": {}, + "name": "example-client-app", + "port": 9090, + "tags": [] + } +} +``` + +| Field name | Type | Description | +| ----------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------ | +| `bootstrapDir` | string | This is the path of a shared volume the is mounted to other containers, where `mesh-init` will write out Envoy configuration. | +| `proxy.upstreams` | list | The upstream services that your application calls over the service mesh, if any. | +| `service.name` | string | The name used to register this service into the Consul service catalog. | +| `service.port` | number | The port your application listens on. Set to `0` if your application does not listen on any port. | +| `service.checks` | list | Consul [checks](/docs/discovery/checks) to include, to have Consul run health checks against your application. | + +See the [`consul-ecs JSON Schema`](https://github.com/hashicorp/consul-ecs/blob/main/config/schema.json) for a complete reference of fields. + +## `consul-ecs-health-sync` container + +Optionally, Consul ECS can sync health checks for this task into Consul checks. +This allows you to configure a health check for your application in one place, and +see a consistent health status in both ECS and Consul. + +First, you'll need to add an ECS health check command to the container definition for your application. +This configures a health check command that runs `curl localhost:9090/health` to check the application health: + +```json +{ + "containerDefinitions": [ + { + "name": "example-client-app", + "image": "docker.io/org/my_task:v0.0.1", + "healthCheck": { + "retries": 3, + "command": ["CMD-SHELL", "curl localhost:9090/health"], + "timeout": 5, + "interval": 30 + }, + ... + }, + ... + ] +} +``` + +See the [ECS health check documentation](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_definition_parameters.html#container_definition_healthcheck) for details on defining ECS health checks. + +Next, you must tell Consul ECS which containers will have their health status synced into Consul. To do this, +set the `healthSyncContainers` field of the `CONSUL_ECS_CONFIG_JSON` variable to include your application container name. + +Here is the expanded configuration: + +```json +{ + "bootstrapDir": "/consul", + "healthSyncContainers": ["example-client-app"], + "proxy": { + "upstreams": [ + { + "destinationName": "example-server-app", + "localBindPort": 1234 + } + ] + }, + "service": { + "checks": [], + "meta": {}, + "name": "example-client-app", + "port": 9090, + "tags": [] + } +} +``` + +Then, update the task definition so that the `consul-ecs-mesh-init` container uses new configuration. +You should compact and escape the JSON configuration above, and copy the result into the `CONSUL_ECS_CONFIG_JSON` +environment variable: + +```json +{ + "containerDefinitions": [ + { + "name": "consul-ecs-mesh-init", + "image": "public.ecr.aws/hashicorp/consul-ecs:", + "environment": [ + { + "name": "CONSUL_ECS_CONFIG_JSON", + "value": "{\"bootstrapDir\":\"/consul\",\"healthSyncContainers\":[\"example-client-app\"],\"proxy\":{\"upstreams\":[{\"destinationName\":\"example-server-app\",\"localBindPort\":1234}]},\"service\":{\"checks\":[],\"meta\":{},\"name\":\"example-client-app\",\"port\":9090,\"tags\":[]}}" + } + ], + ... + }, + ... + ] +} +``` + +Finally, include the `consul-ecs-health-sync` container in the `containerDefinitions` list. +Be sure to pass the same value as above for the `CONSUL_ECS_CONFIG_JSON` environment +variable: + +```json +{ + "containerDefinitions": [ + { + "name": "example-client-app", + "image": "docker.io/org/my_task:v0.0.1", + ... + }, + { + "name": "sidecar-proxy", + "image": "envoyproxy/envoy-alpine:", + ... + }, + { + "name": "consul-client" + "image": "public.ecr.aws/hashicorp/consul:", + ... + }, + { + "name": "consul-ecs-mesh-init", + "image": "public.ecr.aws/hashicorp/consul-ecs:", + ... + }, + { + "name": "consul-ecs-health-sync", + "image": "public.ecr.aws/hashicorp/consul-ecs:", + "command": ["health-sync"], + "essential": false, + "dependsOn": [ + { + "containerName": "consul-ecs-mesh-init", + "condition": "SUCCESS" + } + ], + "environment": [ + { + "name": "CONSUL_ECS_CONFIG_JSON", + "value": "{\"bootstrapDir\":\"/consul\",\"healthSyncContainers\":[\"example-client-app\"],\"proxy\":{\"upstreams\":[{\"destinationName\":\"example-server-app\",\"localBindPort\":1234}]},\"service\":{\"checks\":[],\"meta\":{},\"name\":\"example-client-app\",\"port\":9090,\"tags\":[]}}" + } + ] + } + ] +} +``` + +| Field name | Type | Description | +| ------------- | ------ | ----------------------------------------------------------------------------------------------------------------- | +| `name` | string | The container name which should be `consul-ecs-health-sync`. | +| `image` | string | The `consul-ecs` image. Use our public AWS registry, `public.ecr.aws/hashicorp/consul-ecs`, to avoid rate limits. | +| `command` | list | Set to `["health-sync"]` to run the `consul-ecs health-sync` command. | +| `dependsOn` | list | The `health-sync` container should not start until `mesh-init` has finished service and proxy registration. | +| `environment` | list | Set the `CONSUL_ECS_CONFIG_JSON` variable to pass configuration to the `consul-ecs health-sync command. | + +# Next Steps + +* Create the task definition using the [AWS Console](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ecs-taskdefinition.html) or the [AWS CLI](https://docs.aws.amazon.com/cli/latest/reference/ecs/register-task-definition.html), or another method of your choice. +* Create an [ECS Service](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs_services.html) to start tasks using the task definition. diff --git a/website/content/docs/ecs/install.mdx b/website/content/docs/ecs/install.mdx index d98fb15bdf..3554043cd9 100644 --- a/website/content/docs/ecs/install.mdx +++ b/website/content/docs/ecs/install.mdx @@ -1,28 +1,30 @@ --- layout: docs -page_title: Installation - AWS ECS +page_title: Installation with Terraform - AWS ECS description: >- - Install Consul Service Mesh on AWS ECS (Elastic Container Service). + Install Consul Service Mesh on AWS ECS with Terraform (Elastic Container Service). --- -# Installation +# Installation with Terraform -Installing Consul on ECS is a multi-part process: +This will describe how to use the [`mesh-task` module](https://registry.terraform.io/modules/hashicorp/consul-ecs/aws/latest/submodules/mesh-task) Terraform module to launch your application in AWS ECS as part of Consul service mesh. -1. [**Task Module:**](#task-module) Define the [`mesh-task` Terraform module](https://registry.terraform.io/modules/hashicorp/consul-ecs/aws/latest/submodules/mesh-task) - to create a task definition with the necessary sidecar containers for your application to join the service mesh. -1. [**Routing:**](#routing) With your tasks as part of the mesh, you must specify their upstream - services and change the URLs the tasks are using so that they're making requests through the service mesh. -1. [**Bind Address:**](#bind-address) Now that all communication is flowing through the service mesh, - you should change the address your application is listening on to `127.0.0.1` - so that it only receives requests through the sidecar proxy. +## Pre-requisites --> **NOTE:** This page assumes you're familiar with ECS. See [What is Amazon Elastic Container Service](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/Welcome.html) for more details. +* This pages assumes you are familiar with Terraform. If you are new to Terraform, see the [Terraform documentation](https://www.terraform.io/docs) to + learn about infrastructure as code and how to get started with Terraform. +* This page assumes you are familiar with AWS ECS. See [What is Amazon Elastic Container Service](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/Welcome.html) for more details. +* This page does not show how to create all necessary AWS resources, such as a VPC or the ECS Cluster. + For complete runnable examples, see the links in the [Getting Started](/docs/ecs#getting-started) section. -## Task Module +## Using the Mesh Task 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): +To run an application in ECS with Consul service mesh, you must create an ECS task definition which includes your application container(s) +and additional sidecar containers, such as the Consul agent container and the Envoy sidecar proxy container. + +The [`mesh-task` module](https://registry.terraform.io/modules/hashicorp/consul-ecs/aws/latest/submodules/mesh-task) will automatically include the necessary sidecar containers. + +Here is an example Terraform configuration file which defines a task definition with an application container called `example-client-app`. ```hcl module "my_task" { @@ -53,35 +55,52 @@ module "my_task" { } ``` -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), +All possible inputs are documented in 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: -- `family` is used as the [task definition family](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_definition_parameters.html#family) - but it's also used as the name of the service that gets 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). - This is where you include application containers. -- `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`](/docs/agent/options#_retry_join) option for the Consul agent. This tells - the agent the location of your Consul servers so that it can join the Consul cluster. - --> **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. +| Input Variable | Type | Description | +| ----------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `source` and `version` | string | This specifies the source location and version of the `mesh-task` module. | +| `family` | string | The [ECS task definition family](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_definition_parameters.html#family). The family is also used as the Consul service name, by default. | +| `container_definitions` | list | This is the list of [container definitions](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_definition_parameters.html#container_definitions) for the task definition. This is where you include your application containers. | +| `port` | number | The port that your application listens on, if any. If your application does not listen on a port, set `outbound_only = true`. | +| `retry_join` | list | The is the [`retry_join`](/docs/agent/options#_retry_join) option for the Consul agent, which specifies the locations of your Consul servers. | ## ECS Service +[ECS services](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs_services.html) are one of the most common +ways to start tasks using a task definition.. + To define an ECS Service, reference the mesh-task module's `task_definition_arn` output value in your `aws_ecs_service` resource: ```hcl resource "aws_ecs_service" "my_task" { - ... + name = "my_task_service" task_definition = module.my_task.task_definition_arn + launch_type = "FARGATE" + propagate_tags = "TASK_DEFINITION" + ... } ``` -After running `terraform apply`, you should see your tasks registered in -the Consul UI. +This is a partial configuration to highlight some important fields. +See the [`aws_ecs_service`](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ecs_service) documentation for a complete reference. + +| Input Variable | Type | Description | +| ----------------- | ------- | ------------------------------------------------------------------------------------------------------------------- | +| `name` | string | The name of the ECS service. This is required by AWS but is not used by Consul service mesh. | +| `task_definition` | string | The task definition used to start tasks. Set this to the task definition ARN returned by the `mesh-task` module. | +| `launch_type` | string | The launch type. Consul on ECS supports the `FARGATE` and `EC2` launch types. | +| `propagate_tags` | string | This must be set to `TASK_DEFINITION` so that tags added by `mesh-task` to the task definition are copied to tasks. | + +After defining the Terraform configuration for both the `mesh-task` and ECS service, +run `terraform apply` to create the ECS task definition and service resources. The ECS +service will soon start your application in a task. The task will automatically +register itself into the Consul service catalog. + +-> **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. ## Routing @@ -94,25 +113,23 @@ needs to call. You then must modify your application to make requests to the sid proxy on that port. For example, if your application `web` makes calls to another application called `backend`, then you would first configure the `mesh-task` module's upstream(s): -`backend`. ```hcl module "web" { family = "web" upstreams = [ { - destination_name = "backend" - local_bind_port = 8080 + destinationName = "backend" + localBindPort = 8080 } ] } ``` -- Set the `destination_name` to the name of the upstream service (in this case `backend`) -- Set `local_bind_port` to an unused port. This is the port that the sidecar proxy - will listen on. Any requests to this port will be forwarded over to the `destination_name`. - This does not have to be the port that `backend` is listening on because the service mesh - will handle routing the request to the right port. +| Input Variable | Type | Description | +| ----------------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `destinationName` | string | The name of the upstream service, as it is registered in the Consul service catalog. | +| `localBindPort` | number | Requests to this port will be forwarded by the proxy to the upstream service. This must be an unused port, but does not need to match the upstream service port. | If you have multiple upstream services they each need to be listed here. @@ -127,8 +144,8 @@ module "web" { family = "web" upstreams = [ { - destination_name = "backend" - local_bind_port = 8080 + destinationName = "backend" + localBindPort = 8080 } ] container_definitions = [ diff --git a/website/content/docs/ecs/requirements.mdx b/website/content/docs/ecs/requirements.mdx index 1c4d0488df..c7d0b7407d 100644 --- a/website/content/docs/ecs/requirements.mdx +++ b/website/content/docs/ecs/requirements.mdx @@ -9,8 +9,18 @@ description: >- The following requirements must be met in order to install Consul on ECS: -1. **Terraform:** The tasks that you want to add to the service mesh must first be modeled in Terraform. 1. **Launch Type:** Fargate and EC2 launch types are supported. 1. **Subnets:** ECS Tasks can run in private or public subnets. Tasks must have [network access](https://aws.amazon.com/premiumsupport/knowledge-center/ecs-pull-container-api-error-ecr/) to Amazon ECR or other public container registries to pull images. 1. **Consul Servers:** You can use your own Consul servers running on virtual machines or use [HashiCorp Cloud Platform Consul](https://www.hashicorp.com/cloud-platform) to host the servers for you. For development purposes or testing, you may use the `dev-server` [Terraform module](https://github.com/hashicorp/terraform-aws-consul-ecs/tree/main) that runs the Consul server as an ECS task. The `dev-server` does not support persistent storage. 1. **ACL Controller:** If you are running a secure Consul installation with ACLs enabled, configure the ACL controller. +1. **Sidecar containers:** Consul on ECS requires two sidecar containers to run in each ECS task: a + Consul agent container and a sidecar proxy container. These additional sidecar containers must + be included in the ECS task definition. The Consul ECS Terraform modules will include these + sidecar containers for you. Or if you do not use Terraform, you can construct the task + definition yourself by following our documentation. +1. **Routing:** With your application running in tasks as part of the mesh, you must specify the + upstream services that your application calls. You will also need to change the URLs your + application uses to ensure the application is making requests through the service mesh. +1. **Bind Address:** Once all communication is flowing through the service mesh, you should change + the address your application is listening on to `127.0.0.1` so that it only receives requests + through the sidecar proxy. diff --git a/website/data/docs-nav-data.json b/website/data/docs-nav-data.json index 028a950e01..fdbacd0e94 100644 --- a/website/data/docs-nav-data.json +++ b/website/data/docs-nav-data.json @@ -612,7 +612,7 @@ "path": "ecs/requirements" }, { - "title": "Installation", + "title": "Installation with Terraform", "path": "ecs/install" }, { @@ -630,6 +630,10 @@ { "title": "Consul Enterprise", "path": "ecs/enterprise" + }, + { + "title": "Manual Installation", + "path": "ecs/install-no-terraform" } ] },