mirror of https://github.com/hashicorp/consul
187 lines
6.6 KiB
Markdown
187 lines
6.6 KiB
Markdown
---
|
|
layout: docs
|
|
page_title: Installation - AWS ECS
|
|
description: >-
|
|
Install Consul Service Mesh on AWS ECS (Elastic Container Service).
|
|
---
|
|
|
|
# Installation
|
|
|
|
Installing Consul on ECS is a multi-part process:
|
|
|
|
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.
|
|
|
|
-> **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.
|
|
|
|
## 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):
|
|
|
|
```hcl
|
|
module "my_task" {
|
|
source = "hashicorp/consul-ecs/aws//modules/mesh-task"
|
|
version = "<latest 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 = ["<address of the Consul server>"]
|
|
}
|
|
```
|
|
|
|
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:
|
|
|
|
- `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.
|
|
|
|
## ECS Service
|
|
|
|
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" {
|
|
...
|
|
task_definition = module.my_task.task_definition_arn
|
|
}
|
|
```
|
|
|
|
After running `terraform apply`, you should see your tasks registered in
|
|
the Consul UI.
|
|
|
|
## Routing
|
|
|
|
Now that your tasks are registered in the mesh, you're able to use the service
|
|
mesh to route between them.
|
|
|
|
In order to make calls through the service mesh, you must configure the sidecar
|
|
proxy to listen on a different port for each upstream service your application
|
|
needs to call. You then must modify your application to make requests to the sidecar
|
|
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
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
- 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.
|
|
|
|
If you have multiple upstream services they each need to be listed here.
|
|
|
|
Next, configure your application to make requests to `localhost:8080` when
|
|
it wants to call the `backend` service.
|
|
|
|
For example, if your service allows configuring the URL for `backend` via the
|
|
`BACKEND_URL` environment variable, you would set:
|
|
|
|
```hcl
|
|
module "web" {
|
|
family = "web"
|
|
upstreams = [
|
|
{
|
|
destination_name = "backend"
|
|
local_bind_port = 8080
|
|
}
|
|
]
|
|
container_definitions = [
|
|
{
|
|
name = "web"
|
|
environment = [
|
|
{
|
|
name = "BACKEND_URL"
|
|
value = "http://localhost:8080"
|
|
}
|
|
]
|
|
...
|
|
}
|
|
]
|
|
...
|
|
}
|
|
```
|
|
|
|
## Bind Address
|
|
|
|
To ensure that your application only receives traffic through the service mesh,
|
|
you must change the address that your application is listening on to only the loopback address
|
|
(also known as `localhost`, `lo`, and `127.0.0.1`)
|
|
so that only the sidecar proxy running in the same task can make requests to it.
|
|
|
|
If your application is listening on all interfaces, e.g. `0.0.0.0`, then other
|
|
applications can call it directly, bypassing its sidecar proxy.
|
|
|
|
Changing the listening address is specific to the language and framework you're
|
|
using in your application. Regardless of which language/framework you're using,
|
|
it's a good practice to make the address configurable via environment variable.
|
|
|
|
For example in Go, you would use:
|
|
|
|
```go
|
|
s := &http.Server{
|
|
Addr: "127.0.0.1:8080",
|
|
...
|
|
}
|
|
log.Fatal(s.ListenAndServe())
|
|
```
|
|
|
|
In Django you'd use:
|
|
|
|
```bash
|
|
python manage.py runserver "127.0.0.1:8080"
|
|
```
|
|
|
|
## Next Steps
|
|
|
|
- Configure a secure [Production Installation](/docs/ecs/get-started/production-installation).
|
|
- Now that your applications are running in the service mesh, read about
|
|
other [Service Mesh features](/docs/connect).
|
|
- View the [Architecture](/docs/ecs/architecture) documentation to understand
|
|
what's going on under the hood.
|