consul

Announcing Tech Preview of Consul Service Mesh for Amazon ECS

AWS users may now select Consul as their service mesh for ECS deployments.

Consul on ECS is now in Beta.

Today we are pleased to announce that HashiCorp Consul service mesh is available to deploy on Amazon Elastic Container Service (ECS) as a tech preview. This integration enables users to select Consul as their service mesh for ECS deployments.

The tech preview of this integration lets users deploy a non-production version of Consul for testing on the Fargate launch type for ECS. As we approach general availability, we will enable more secure, production-ready deployments for self-managed Consul clusters on AWS and HashiCorp Cloud Platform (HCP) Consul clusters.

In this blog, we’ll explore how this integration was built and provide steps for users who wish to try it for themselves.

»A Quick Overview of ECS

Amazon Elastic Container Service (ECS) is a fully managed container orchestration service provided by Amazon Web Services. ECS is a popular choice for organizations that have built a large portion of their infrastructure in AWS and rely on it for other services. In fact, according to AWS’s 2020 Container Security Survey, 56% of respondents are using ECS on EC2 or Fargate to manage their container deployments.

Amazon Elastic Kubernetes Service (EKS) continues to be a growing service for AWS, but this survey reinforces the notion that customers frequently opt for multiple kinds of orchestration services. Our goal with Consul is to enable a true multi-platform service mesh that supports all runtimes. Adding ECS to the list of supported runtime platforms brings us closer to achieving this goal.

»How it Works

Let’s walk through the steps of how to use Consul service mesh on ECS. To provide a simple and consistent user experience, users can deploy Consul service mesh on Amazon ECS using HashiCorp Terraform. There are two official Terraform modules used to deploy Consul on ECS: mesh-task and dev-server.

The dev-server module deploys a development/testing-only Consul server task onto ECS Fargate:

Consul server task

The image above represents a basic Consul server task. Future releases will support deploying a production-ready Consul server.

The mesh-task module is used to deploy application tasks into the service mesh. In addition to the application containers, the mesh-task module adds additional containers to the task. Here's a diagram of what an application task deployed with the mesh-task module looks like:

Application task deployed with the mesh-task module

The additional containers added to the task are the Consul client container and the sidecar proxy container. The Consul client container communicates with the Consul server and acts as part of the control plane for the service mesh. The sidecar proxy container runs Envoy and proxies all traffic into and out of the task.

The mesh-task module is designed to make it easy to convert existing task definitions into service mesh tasks. For example, given an existing Terraform task definition:

resource "aws_ecs_task_definition" "web" {
  family                = "web"
  container_definitions = jsonencode(
    [{
      name             = "web"
      image            = "docker.io/org/web:v0.0.1"
      essential        = true
      portMappings = [
        {
          containerPort = 9090
        }
      ]
    }]
  )
}
resource "aws_ecs_task_definition" "web" {  family                = "web"  container_definitions = jsonencode(    [{      name             = "web"      image            = "docker.io/org/web:v0.0.1"      essential        = true      portMappings = [        {          containerPort = 9090        }      ]    }]  )}

All that’s required to add that task to the service mesh is to copy the family and container_definitions inputs into a new instantiation of the mesh-task module:

module "web" {
  source  = "hashicorp/consul/aws-ecs//modules/mesh-task"

  family                = "web"
  container_definitions = [
    {
      name             = "web"
      image            = "docker.io/org/web:v0.0.1"
      essential        = true
      portMappings = [
        {
          containerPort = 9090
        }
      ]
    }
  ]
}
module "web" {  source  = "hashicorp/consul/aws-ecs//modules/mesh-task"   family                = "web"  container_definitions = [    {      name             = "web"      image            = "docker.io/org/web:v0.0.1"      essential        = true      portMappings = [        {          containerPort = 9090        }      ]    }  ]}

Under the hood, the module will automatically add in the additional containers.

Now that you understand how the dev-server and mesh-task modules work, let’s look at how you can combine them into a full service mesh architecture.

»Web and API Example

In this example, we want to deploy two services: web and api, and a Consul server. An example Terraform file that creates a Consul server and the two services tasks would look like this:

module "consul_server" {
  source  = "hashicorp/consul-ecs/aws//modules/dev-server"
  ...
}

module "web" {
  source  = "hashicorp/consul-ecs/aws//modules/mesh-task"
  ...
}

module "api" {
  source  = "hashicorp/consul-ecs/aws//modules/mesh-task"
  ...
}
module "consul_server" {  source  = "hashicorp/consul-ecs/aws//modules/dev-server"  ...} module "web" {  source  = "hashicorp/consul-ecs/aws//modules/mesh-task"  ...} module "api" {  source  = "hashicorp/consul-ecs/aws//modules/mesh-task"  ...}

This Terraform configuration would create a Consul server task and two application tasks in the service mesh. The diagram below illustrates this:

Consul server task and two application tasks in the service mesh.

If we wanted web to be able to call api, we would define an upstream in its Terraform configuration:

module "web" {
  source  = "hashicorp/consul/aws-ecs//modules/mesh-task"

  family                = "web"
  container_definitions = ...

  # Define api as an upstream.
  upstreams = [
    {
      destination_name = "api"
      local_bind_port  = 8080
    }
  ]
}
module "web" {  source  = "hashicorp/consul/aws-ecs//modules/mesh-task"   family                = "web"  container_definitions = ...   # Define api as an upstream.  upstreams = [    {      destination_name = "api"      local_bind_port  = 8080    }  ]}

This configuration instructs Consul to configure web’s Envoy proxy to bind to port 8080 on the web task. If web then makes a request to http://localhost:8080, the request will be routed through the service mesh and over to the api task.

»Service Mesh Features

Running Consul on ECS lets you take advantage of many exciting service mesh features:

  • Zero trust networking: Requests between tasks are fully encrypted with mTLS. This prevents potential attackers from sniffing plain-text traffic. In addition, because requests flow through sidecar proxies, Consul can block requests from unauthorized services.
  • Observability: Sidecar proxies can be configured to emit consistent request metrics between all your services. This means you can build dashboards and create automated alerts without reconfiguring and re-coding all your services.
  • Reliability: Consul’s configuration entries can be used to configure the behavior of proxies to retry failed requests, timeout after a certain period of time, and circuit break services that are not responding. These controls can increase the reliability of your microservices infrastructure without requiring changes to the underlying services.

»Conclusion

This exciting evolution in Consul service mesh further expands HashiCorp’s ability to support any application on any runtime. As we move Consul service mesh for Amazon ECS towards general availability we plan to further enhance this offering, so we greatly appreciate any feedback tech preview users can share along the way.

For more information about Consul on ECS, please visit our documentation, and for more information about Consul service mesh, please visit the Consul project home page.

Sign up for the latest HashiCorp news