Skip to main content

Hashicorp Consul Refresher - Service Mesh

Wan Chai, Hongkong

Consul Connect

Consul Connect provides service-to-service connection authorization and encryption using mutual Transport Layer Security (TLS). Applications can use Sidecar Proxies in a service mesh configuration to establish TLS connections for inbound and outbound connections without being aware of Connect at all.

The first step to use Connect is to enable Connect for your Consul cluster. By default, Connect is disabled. Enabling Connect requires changing the configuration of only your Consul servers (not client agents). To enable Connect, add the following to a new or existing server configuration file. In an existing cluster, this configuration change requires a Consul server restart:

sudo nano /etc/consul.d/consul.hcl

Add the following lines to the end of the file and service consul restart:

connect {
  enabled = true
}

Application Security

Connect enables secure deployment best-practices with automatic service-to-service encryption, and identity-based authorization. Connect uses the registered service identity (rather than IP addresses) to enforce access control with intentions.

Observability

One of the key benefits of Consul Connect is the uniform and consistent view it can provide of all the services on your network, irrespective of their different programming languages and frameworks. When you configure Consul Connect to use sidecar proxies, those proxies "see" all service-to-service traffic and can collect data about it.

Sidecar Service Registration

To make Connect aware of proxies you will need to register them in a Service Definition, just like you would register any other service with Consul. To reduce the amount of boilerplate needed for a sidecar proxy, application service definitions may define an inline sidecar service block.

Connect proxies are typically deployed as Sidecars that run on the same node as the single service instance that they handle traffic for:

{
  "service": {
    "name": "web",
    "port": 8080,
    "connect": { "sidecar_service": {} }
  }
}

This will register the web service as normal, but will also register another Proxy Service with defaults values used. The above expands out to be equivalent to the following explicit service definitions:

{
  "service": {
    "name": "web",
    "port": 8080,
  }
}
{
  "name": "web-sidecar-proxy",
  "port": 20000,
  "kind": "connect-proxy",
  "checks": [
    {
      "Name": "Connect Sidecar Listening",
      "TCP": "127.0.0.1:20000",
      "Interval": "10s"
    },
    {
      "name": "Connect Sidecar Aliasing web",
      "alias_service": "web"
    }
  ],
  "proxy": {
    "destination_service_name": "web",
    "destination_service_id": "web",
    "local_service_address": "127.0.0.1",
    "local_service_port": 8080,
  }
}

Intentions

Intentions define access control for services via Connect and are used to control which services may establish connections or make requests. Intentions can be managed via the API, CLI, or UI. Intentions are managed primarily via service-intentions config entries or the UI. Some simpler tasks can also be achieved with the older API or CLI.

A basic service-intentions config entry representing two simple intentions looks like:

Kind = "service-intentions"
Name = "db"
Sources = [
  {
    Name   = "web"
    Action = "deny"
  },
  {
    Name   = "api"
    Action = "allow"
  }
]

This config entry defines two intentions with a common destination of db. The first intention above is a deny intention with a source of web. This says that connections from web to db are not allowed and the connection will be rejected. The second intention is an allow intention with a source of api. This says that connections from api to db are allowed and connections will be accepted.

Wildcard Intentions

An intention source or destination may also be the special wildcard value *. This matches any value and is used as a catch-all. This example says that the web service cannot connect to any service:

Kind = "service-intentions"
Name = "*"
Sources = [
  {
    Name   = "web"
    Action = "deny"
  }
]

And this example says that no service can connect to the db service:

Kind = "service-intentions"
Name = "db"
Sources = [
  {
    Name   = "*"
    Action = "deny"
  }
]

Intentions are matched in an implicit order based on specificity, preferring deny over allow. Specificity is determined by whether a value is an exact specified value or is the wildcard value *.

Load Balancing Services with Envoy

Consul 1.9.0 introduces the ability to change the load balancing policy used by the Envoy data plane proxy by specifying the desired algorithm with Consul configuration entries.

WIP