docs: Manual installation of Consul on ECS
This commit is contained in:
parent
446355ff69
commit
5a98efcf56
|
@ -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:<VERSION>",
|
||||
"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:<ENVOY_VERSION>",
|
||||
...
|
||||
}
|
||||
{
|
||||
"name": "consul-client"
|
||||
"image": "public.ecr.aws/hashicorp/consul:<CONSUL_VERSION>",
|
||||
"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 \"<Consul server location>",\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 = ["<consul server location>"]
|
||||
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:<ENVOY_VERSION>",
|
||||
...
|
||||
},
|
||||
{
|
||||
"name": "consul-client"
|
||||
"image": "public.ecr.aws/hashicorp/consul:<CONSUL_VERSION>",
|
||||
...
|
||||
},
|
||||
{
|
||||
"name": "consul-ecs-mesh-init",
|
||||
"image": "public.ecr.aws/hashicorp/consul-ecs:<CONSUL_ECS_VERSION>",
|
||||
"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:<VERSION>",
|
||||
"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:<ENVOY_VERSION>",
|
||||
...
|
||||
},
|
||||
{
|
||||
"name": "consul-client"
|
||||
"image": "public.ecr.aws/hashicorp/consul:<CONSUL_VERSION>",
|
||||
...
|
||||
},
|
||||
{
|
||||
"name": "consul-ecs-mesh-init",
|
||||
"image": "public.ecr.aws/hashicorp/consul-ecs:<CONSUL_ECS_VERSION>",
|
||||
...
|
||||
},
|
||||
{
|
||||
"name": "consul-ecs-health-sync",
|
||||
"image": "public.ecr.aws/hashicorp/consul-ecs:<CONSUL_ECS_VERSION>",
|
||||
"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.
|
|
@ -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 = [
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
Loading…
Reference in New Issue