June 20-22 Announcing HashiConf Europe full schedule: keynotes, sessions, labs & more Register Now
  • Overview
    • Consul on Kubernetes
    • Control access with Consul API Gateway
    • Discover Services with Consul
    • Enforce Zero Trust Networking with Consul
    • Load Balancing with Consul
    • Manage Traffic with Consul
    • Multi-Platform Service Mesh with Consul
    • Network Infrastructure Automation with Consul
    • Observability with Consul
  • Enterprise
  • Tutorials
  • Docs
  • API
  • CLI
  • Community
GitHub
Download
Try HCP Consul
    • v1.12.x (latest)
    • v1.11.x
    • v1.10.x
    • v1.9.x
    • v1.8.x
    • Overview
      • Overview
      • What is a Service Mesh?
      • Overview
      • Chef, Puppet, etc.
      • Nagios
      • SkyDNS
      • SmartStack
      • Serf
      • Eureka
      • Istio
      • Envoy and Other Proxies
      • Custom Solutions
    • Overview
    • Manual Bootstrap
    • Consul Agent
    • Glossary
    • Required Ports
    • Bootstrapping a Datacenter
    • Cloud Auto-join
    • Server Performance
    • Kubernetes
  • API
  • Commands (CLI)
    • Register Services - Service Definitions
    • Find Services - DNS Interface
    • Monitor Services - Check Definitions
    • Overview
    • How Service Mesh Works
    • Configuration
      • Overview
      • Ingress Gateway
      • Mesh
      • Exported Services
      • Proxy Defaults
      • Service Defaults
      • Service Intentions
      • Service Resolver
      • Service Router
      • Service Splitter
      • Terminating Gateway
      • Overview
      • Envoy
      • Built-in Proxy
      • Proxy Integration
      • Managed (Deprecated)
      • Overview
      • Proxy Service Registration
      • Sidecar Service Registration
    • Service-to-service permissions - Intentions
    • Service-to-service permissions - Intentions (Legacy Mode)
    • Transparent Proxy
      • Overview
      • UI Visualization
      • Overview
      • Discovery Chain
    • Connectivity Tasks
    • Distributed Tracing
      • Overview
        • WAN Federation
        • Enabling Service-to-service Traffic Across Datacenters
        • Enabling Service-to-service Traffic Across Admin Partitions
      • Ingress Gateways
      • Terminating Gateways
    • Nomad
    • Kubernetes
      • Overview
      • Go Integration
      • Overview
      • Built-In CA
      • Vault
      • ACM Private CA
    • Develop and Debug
    • Security
    • Overview
    • Installation
    • Technical Specifications
    • Common Errors
    • Upgrades
    • Overview
    • Architecture
      • Installing Consul on Kubernetes
      • Installing Consul K8s CLI
        • Minikube
        • Kind
        • AKS (Azure)
        • EKS (AWS)
        • GKE (Google Cloud)
        • Red Hat OpenShift
        • Self Hosted Kubernetes
        • Consul Clients Outside Kubernetes
        • Consul Servers Outside Kubernetes
        • Single Consul Datacenter in Multiple Kubernetes Clusters
        • Consul Enterprise
        • Overview
        • Federation Between Kubernetes Clusters
        • Federation Between VMs and Kubernetes
        • Overview
        • Systems Integration
          • Overview
          • Bootstrap Token
          • Enterprise License
          • Gossip Encryption Key
          • Partition Token
          • Replication Token
          • Server TLS
          • Service Mesh Certificates
          • Snapshot Agent Config
        • WAN Federation
      • Compatibility Matrix
      • Overview
      • Transparent Proxy
      • Ingress Gateways
      • Terminating Gateways
      • Ingress Controllers
      • Configuring a Connect CA Provider
      • Health Checks
        • Metrics
    • Service Sync
      • Overview
      • Upgrade An Existing Cluster to CRDs
    • Annotations and Labels
    • Consul DNS
      • Upgrading Consul on Kubernetes
      • Upgrading Consul K8s CLI
      • Uninstall
      • Certificate Rotation
      • Gossip Encryption Key Rotation
      • Configure TLS on an Existing Cluster
      • Common Error Messages
      • FAQ
    • Helm Chart Configuration
    • Consul K8s CLI Reference
    • Overview
    • Requirements
    • Task Resource Usage
      • Installation
      • Secure Configuration
      • Migrate Existing Tasks
      • Installation
      • Secure Configuration
      • ACL Controller
    • Architecture
    • Consul Enterprise
    • Configuration Reference
    • Overview
      • Installation
      • Requirements
      • Configure
      • Run Consul-Terraform-Sync
    • Architecture
      • Overview
      • Status
      • Tasks
      • Overview
      • task
    • Configuration
    • Tasks
    • Terraform Modules
      • Overview
      • License
      • Terraform Cloud Driver
      • Overview
      • Terraform
      • Terraform Cloud
    • Compatibility
    • Consul KV
    • Sessions
    • Watches
    • Overview
      • General
      • CLI Reference
      • Configuration Reference
    • Configuration Entries
    • Telemetry
    • Sentinel
    • RPC
    • Overview
      • ACL System Overview
      • Tokens
      • Policies
      • Roles
      • Rules Reference
      • Legacy Mode
      • Token Migration
      • ACLs in Federated Datacenters
        • Overview
        • Kubernetes
        • JWT
        • OIDC
        • AWS IAM
    • Encryption
      • Overview
      • Core
      • Network Infrastructure Automation
    • Overview
    • Admin Partitions
    • Audit Logging
    • Automated Backups
    • Automated Upgrades
    • Enhanced Read Scalability
    • Single sign-on - OIDC
    • Redundancy Zones
    • Advanced Federation
    • Network Segments
    • Namespaces
    • NIA with TFE
    • Sentinel
      • Overview
      • FAQ
    • Overview
    • Improving Consul Resilience
    • Anti-Entropy
    • Consensus Protocol
    • Gossip Protocol
    • Jepsen Testing
    • Network Coordinates
    • Consul Integration Program
    • NIA Integration Program
    • Vault Integration
    • Proxy Integration
  • Consul Tools
    • Overview
    • Compatibility Promise
    • Specific Version Details
      • Overview
      • General Process
      • Upgrading to 1.2.4
      • Upgrading to 1.6.9
      • Upgrading to 1.8.13
      • Upgrading to 1.10.0
    • Common Error Messages
    • FAQ
    • Overview
      • v1.11.x
      • v1.10.x
      • v1.9.x
      • v0.1.x
      • v0.2.x
      • v0.4.x
      • v0.3.x
      • v0.2.x
      • v0.5.x
      • v0.6.0-beta
    • Overview
    • ACL
  • Guides
Type '/' to Search

»Installation with Terraform

This topic describes how to use the mesh-task Terraform module to launch your application in AWS ECS as part of Consul service mesh. If you do not use Terraform, see the Manual Installation page to install Consul on ECS without Terraform.

This topic does not include instructions for creating all AWS resources necessary to install Consul, such as a VPC or the ECS cluster. Refer to the linked guides in the Getting Started section for complete, runnable examples.

»Overview

This topic describes the following procedure:

  1. Create Terraform configuration files for the necessary components:

    • ECS task definition: Use the mesh-task module to create an ECS task definition for Consul on ECS
    • ECS service: Use the aws_ecs_service resource to create an ECS service that schedules service mesh tasks to run on ECS
  2. Run Terraform to deploy the resources in AWS

»Prerequisites

  • You should have some familiarity with using Terraform. Refer to the Terraform documentation to learn about infrastructure as code and how to get started with Terraform.
  • You should also be familiar with AWS ECS before following these instructions. See What is Amazon Elastic Container Service for details.

»Using the Mesh Task Module

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 will automatically include the necessary sidecar containers.

The following example shows a Terraform configuration file that creates a task definition with an application container called example-client-app in a file called mesh-task.tf:

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>"]
  consul_datacenter = "<name of your Consul datacenter>"
}
mesh-task.tf
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>"]
  consul_datacenter = "<name of your Consul datacenter>"
}

The following fields are required. Refer to the module reference documentation for a complete reference.

Input VariableTypeDescription
sourcestringMust be set to the source location of the mesh-task module, hashicorp/consul-ecs/aws//modules/mesh-task.
versionstringMust be set to the version of the mesh-task module.
familystringThe ECS task definition family. The family is also used as the Consul service name by default.
container_definitionslistThis is the list of container definitions for the task definition. This is where you include your application containers.
essentialbooleanMust be true to ensure the health of your application container affects the health status of the task.
portintegerThe port that your application listens on, if any. If your application does not listen on a port, set outbound_only = true.
retry_joinlistThe is the retry_join option for the Consul agent, which specifies the locations of your Consul servers.
consul_datacenterstringThe name of your Consul datacenter.

»Running Terraform

You will need to run Terraform to create the task definition.

Save the Terraform configuration for the task definition to a file, such as mesh-task.tf. You should place this file in a directory alongside other Terraform configuration files for your project.

The mesh-task module requires the AWS Terraform provider. The following example shows how to include and configure the AWS provider in a file called provider.tf. Refer to the AWS Terraform provider documentation for complete configuration details.

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "<latest version>"
    }
  }
}

provider "aws" {
  region = "<AWS region>"
  ...
}
provider.tf
terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "<latest version>"
    }
  }
}

provider "aws" {
  region = "<AWS region>"
  ...
}

Additional AWS resources for your project can be included in additional Terraform configuration files in the same directory. The following example shows a basic project directory:

$ ls
mesh-task.tf
provider.tf
...
$ ls
mesh-task.tf
provider.tf
...

Terraform should be run in your project directory as follows.

  • Run terraform init first to download dependencies, such as Terraform providers
  • Run terraform apply to have Terraform create AWS resources, such as the task definition from the mesh-task module.

Terraform automatically reads all files in the current directory that have a .tf file extension. Refer to the Terraform documentation for more information and Terraform best practices.

»ECS Service

ECS services 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. The following example shows how to include the service in the mesh-task.tf file.

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

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"
  ...
}
mesh-task.tf
module "my_task" {
  source  = "hashicorp/consul-ecs/aws//modules/mesh-task"
  ...
}

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"
  ...
}

This is a partial configuration to highlight some important fields. See the aws_ecs_service documentation for a complete reference.

Input VariableTypeDescription
namestringThe name of the ECS service. This is required by AWS but is not used by Consul service mesh.
task_definitionstringThe task definition used to start tasks. Set this to the task definition ARN returned by the mesh-task module.
launch_typestringThe launch type. Consul on ECS supports the FARGATE and EC2 launch types.
propagate_tagsstringThis must be set to TASK_DEFINITION so that tags added by mesh-task to the task definition are copied to tasks.

After including the ECS service in your Terraform configuration, run terraform apply from your project directory to create the ECS service resource. The ECS service will soon start your application in a task. The task will automatically register itself into the Consul service catalog during startup.

NOTE: If your tasks run in a public subnet, they must have assign_public_ip = true in their network_configuration block so that ECS can pull the Docker images.

»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):

module "web" {
  family = "web"
  upstreams = [
    {
      destinationName = "backend"
      localBindPort = 8080
    }
  ]
}
module "web" {
  family = "web"
  upstreams = [
    {
      destinationName = "backend"
      localBindPort = 8080
    }
  ]
}
Input VariableTypeDescription
destinationNamestringThe name of the upstream service, as it is registered in the Consul service catalog.
localBindPortintegerRequests 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.

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:

module "web" {
  family = "web"
  upstreams = [
    {
      destinationName = "backend"
      localBindPort = 8080
    }
  ]
  container_definitions = [
    {
      name        = "web"
      environment = [
        {
          name  = "BACKEND_URL"
          value = "http://localhost:8080"
        }
      ]
      ...
    }
  ]
  ...
}
module "web" {
  family = "web"
  upstreams = [
    {
      destinationName = "backend"
      localBindPort = 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:

s := &http.Server{
    Addr:           "127.0.0.1:8080",
  ...
}
log.Fatal(s.ListenAndServe())
s := &http.Server{
    Addr:           "127.0.0.1:8080",
  ...
}
log.Fatal(s.ListenAndServe())

In Django you'd use:

python manage.py runserver "127.0.0.1:8080"
python manage.py runserver "127.0.0.1:8080"

»Next Steps

  • Follow the Secure Configuration to get production-ready.
  • Now that your applications are running in the service mesh, read about other Service Mesh features.
  • View the Architecture documentation to understand what's going on under the hood.
github logoEdit this page
IntroGuidesDocsCommunityPrivacySecurityBrandConsent Manager