11 KiB
layout | page_title | sidebar_current | description |
---|---|---|---|
docs | Connect - Envoy Integration | docs-connect-proxies-envoy | Consul Connect has first-class support for configuring Envoy proxy. |
Envoy Integration
Consul Connect has first class support for using Envoy as a proxy. Consul configures Envoy by optionally exposing a gRPC service on the local agent that serves Envoy's xDS configuration API.
Currently Consul only supports TCP proxying between services, however HTTP and gRPC features are planned for the near future along with first class ways to configure them in Consul.
As an interim solution, custom Envoy configuration can be specified in proxy service definition allowing more powerful features of Envoy to be used.
Supported Versions
Consul's Envoy support was added in version 1.3.0. It has been tested against Envoy 1.7.1 and 1.8.0.
Getting Started
To get started with Envoy and see a working example you can follow the Using Envoy with Connect guide.
Limitations
The following list limitations of the Envoy integration as released in 1.3.0. All of these are planned to be lifted in the near future.
- Default Envoy configuration only supports Layer 4 (TCP) proxying. More advanced listener configuration is possible but experimental and requires deep Envoy knowledge. First class workflows for configuring Layer 7 features across the cluster are planned for the near future.
- There is currently no way to override the configuration of upstream clusters which makes it impossible to configure Envoy features like circuit breakers, load balancing policy, custom protocol settings etc. This will be fixed in a near-future release first with an "escape hatch" similar to the one for listeners below, then later with first-class support.
- The configuration delivered to Envoy is suitable for a sidecar proxy currently. Later we plan to support more flexibility to be able to configure Envoy as an edge router or gateway and similar.
- There is currently no way to disable the public listener and have a "client only" sidecar for services that don't expose Connect-enabled service but want to consume others. This will be fixed in a near-future release.
- Once authorized, a persistent TCP connection will not be closed if the intentions change to deny access. This is currently a limitation of how TCP proxy and network authz filter work in Envoy. All new connections will be denied though and destination services can limit exposure by closing inbound connections periodically or by a rolling restart of the destination service as an emergency measure.
Bootstrap Configuration
Envoy requires an initial bootstrap configuration that directs it to the local agent for further configuration discovery.
To assist in generating this, Consul 1.3.0 adds a consul connect envoy
command. The command can either output the
bootstrap configuration directly or can generate it and then exec
the Envoy
binary as a convenience wrapper.
Some Envoy configuration options like metrics and tracing sinks can only be specified via the bootstrap config currently and so a custom bootstrap must be used. In order to work with Connect it's necessary to start with the following basic template and add additional configuration as needed.
admin:
# access_log_path and address are required by Envoy, Consul doesn't care what
# they are set to though and never accesses the admin API.
node:
# cluter is required by Envoy but Consul doesn't use it
cluster: "<cluster_name"
# id must be the ID (not name if they differ) of the proxy service
# registration in Consul
id: "<proxy_service_id>"
static_resources:
clusters:
# local_agent is the "cluster" used to make further discovery requests for
# config and should point to the gRPC port of the local Consul agent instance.
- name: local_agent
connect_timeout: 1s
type: STATIC
# tls_context is needed if and only if Consul agent TLS is configured
tls_context:
common_tls_context:
validation_context:
trusted_ca:
filename: "<path to CA cert file Consul is using>"
http2_protocol_options: {}
hosts:
- socket_address:
address: "<agent's local IP address, usually 127.0.0.1>"
port_value: "<agent's grpc port, default 8502>"
dynamic_resources:
lds_config:
ads: {}
cds_config:
ads: {}
ads_config:
api_type: GRPC
grpc_services:
initial_metadata:
- key: "x-consul-token"
token: "<Consul ACL token with service:write on the target service>"
envoy_grpc:
cluster_name: local_agent
This configures a "cluster" pointing to the local Consul agent and sets that as the target for discovering all types of dynamic resources.
~> Security Note: The bootstrap configuration must contain the Consul ACL token authorizing the proxy to identify as the target service. As such it should be treated as a secret value and handled with care - an attacker with access to one is able to obtain Connect TLS certificates for the target service and so access anything that service is authorized to connect to.
Advanced Listener Configuration
Consul 1.3.0 includes initial Envoy support which includes automatic Layer 4 (TCP) proxying over mTLS, and authorization. Near future versions of Consul will bring Layer 7 features like HTTP-path-based routing, retries, tracing and more.
-> Advanced Topic! This section covers an optional way of taking almost complete control of Envoy's listener configuration which is provided as a way to experiment with advanced integrations ahead of full layer 7 feature support. While we don't plan to remove the ability to do this in the future, it should be considered experimental and requires in-depth knowledge of Envoy's configuration format.
For advanced users there is an "escape hatch" available in 1.3.0. The
proxy.config
map in the proxy service
definition may contain a
special key called envoy_public_listener_json
. If this is set, it's value must
be a string containing the serialized proto3 JSON encoding of a complete envoy
listener
config.
Each upstream listener may also be customized in the same way by adding a
envoy_listener_json
key to the config
map of the upstream
definition.
The JSON supplied may describe a protobuf types.Any
message with @type
set
to type.googleapis.com/envoy.api.v2.Listener
, or it may be the direct encoding
of the listener with no @type
field.
Once parsed, it is passed to Envoy in place of the listener config that Consul would typically configure. The only modifications Consul will make to the config provided are noted below.
Public Listener Configuration
For the proxy.config.envoy_public_listener_json
, every FilterChain
added to
the listener will have it's TlsContext
overwritten with the Connect TLS
certificates. This means there is no way to override Connect TLS settings or the
requirement for all inbound clients to present valid Connect certificates.
Also, every FilterChain
will have the envoy.ext_authz
filter prepended to
the filters array to ensure that all incoming connections must be authorized
explicitly by the Consul agent based on their presented client certificate.
To work properly with Consul Connect, the public listener should bind to the
same address in the service definition so it is discoverable. It may also use
the special cluster name local_app
to forward requests to a single local
instance if the proxy was configured as a
sidecar.
Example
The following example shows a public listener being configured with an http connection manager. As specified this behaves exactly like the default TCP proxy filter however it provides metrics on HTTP request volume and response codes.
If additional config outside of the listener is needed (for example the
top-level tracing
configuration to send traces to a collecting service), those
currently need to be added to a custom bootstrap. You may generate the default
connect bootstrap with the consul connect envoy -bootstrap
command and then add the required additional
resources.
service {
kind = "connect-proxy"
name = "web-http-aware-proxy"
port = 8080
proxy {
destination_service_name = "web"
destination_service_id = "web"
config {
envoy_public_listener_json = <<EOL
{
"@type": "type.googleapis.com/envoy.api.v2.Listener",
"name": "public_listener:0.0.0.0:18080",
"address": {
"socketAddress": {
"address": "0.0.0.0",
"portValue": 8080
}
},
"filterChains": [
{
"filters": [
{
"name": "envoy.http_connection_manager",
"config": {
"stat_prefix": "public_listener",
"route_config": {
"name": "local_route",
"virtual_hosts": [
{
"name": "backend",
"domains": ["*"],
"routes": [
{
"match": {
"prefix": "/"
},
"route": {
"cluster": "local_app"
}
}
]
}
]
},
"http_filters": [
{
"name": "envoy.router",
"config": {}
}
]
}
}
]
}
]
}
EOL
}
}
}
Upstream Listener Configuration
For the upstream listeners proxy.upstreams[].config.envoy_listener_json
, no
modification is performed. The Clusters
served via the xDS API all have the
correct client certificates and verification contexts configured so outbound
traffic should be authenticated.
Each upstream may separately choose to define a custom listener config. If multiple upstreams define them care must be taken to ensure they all listen on separate ports.
Currently there is no way to disable a listener for an upstream, or modify how upstream service discovery clusters are delivered. Richer support for features like this is planned for the near future.