8b05efcf88
This PR implements Nomad built-in support for running Consul Connect terminating gateways. Such a gateway can be used by services running inside the service mesh to access "legacy" services running outside the service mesh while still making use of Consul's service identity based networking and ACL policies. https://www.consul.io/docs/connect/gateways/terminating-gateway These gateways are declared as part of a task group level service definition within the connect stanza. service { connect { gateway { proxy { // envoy proxy configuration } terminating { // terminating-gateway configuration entry } } } } Currently Envoy is the only supported gateway implementation in Consul. The gateay task can be customized by configuring the connect.sidecar_task block. When the gateway.terminating field is set, Nomad will write/update the Configuration Entry into Consul on job submission. Because CEs are global in scope and there may be more than one Nomad cluster communicating with Consul, there is an assumption that any terminating gateway defined in Nomad for a particular service will be the same among Nomad clusters. Gateways require Consul 1.8.0+, checked by a node constraint. Closes #9445
451 lines
16 KiB
Plaintext
451 lines
16 KiB
Plaintext
---
|
|
layout: docs
|
|
page_title: gateway Stanza - Job Specification
|
|
sidebar_title: gateway
|
|
description: |-
|
|
The "gateway" stanza allows specifying options for configuring Consul Gateways
|
|
used in the Consul Connect integration
|
|
---
|
|
|
|
# `gateway` Stanza
|
|
|
|
<Placement groups={['job', 'group', 'service', 'connect', 'gateway']} />
|
|
|
|
The `gateway` stanza allows configuration of [Consul Connect Gateways](https://www.consul.io/docs/connect/gateways). Nomad will
|
|
automatically create the necessary Gateway [Configuration Entry](https://www.consul.io/docs/agent/config-entries)
|
|
as well as inject an Envoy proxy task into the Nomad job to serve as the Gateway.
|
|
|
|
The `gateway` configuration is valid within the context of a `connect` stanza.
|
|
Additional information about Gateway configurations can be found in Consul's
|
|
[Connect Gateways](https://www.consul.io/docs/connect/gateways) documentation.
|
|
|
|
~> **Note:** [Ingress Gateways](https://www.consul.io/docs/connect/gateways/ingress-gateway)
|
|
are generally intended for enabling access into a Consul service mesh from within the
|
|
same network. For public ingress products like [NGINX](https://learn.hashicorp.com/tutorials/nomad/load-balancing-nginx?in=nomad/load-balancing)
|
|
provide more suitable features.
|
|
|
|
```hcl
|
|
service {
|
|
connect {
|
|
gateway {
|
|
# ...
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
## `gateway` Parameters
|
|
|
|
Exactly one of `ingress` or `terminating` must be configured.
|
|
|
|
- `proxy` <code>([proxy]: nil)</code> - Configuration of the Envoy proxy that will
|
|
be injected into the task group.
|
|
- `ingress` <code>([ingress]: nil)</code> - Configuration Entry of type `ingress-gateway`
|
|
that will be associated with the service.
|
|
- `terminating` <code>([terminating]: nil)</code> - Configuration Entry of type `terminating-gateway`
|
|
that will be associated with the service.
|
|
|
|
### `proxy` Parameters
|
|
|
|
- `connect_timeout` `(string: "5s")` - The amount of time to allow when making upstream
|
|
connections before timing out. Defaults to 5 seconds. If the upstream service has
|
|
the configuration option <code>[connect_timeout_ms]</code> set for the `service-resolver`, that
|
|
timeout value will take precedence over this gateway proxy option.
|
|
- `envoy_gateway_bind_tagged_addresses` `(bool: false)` - Indicates that the gateway
|
|
services tagged addresses should be bound to listeners in addition to the default
|
|
listener address.
|
|
- `envoy_gateway_bind_addresses` <code>(map<string|[address]>: nil)</code> - A map of additional addresses to be bound.
|
|
The keys to this map are the same of the listeners to be created and the values are
|
|
a map with two keys - address and port, that combined make the address to bind the
|
|
listener to. These are bound in addition to the default address.
|
|
If `bridge` networking is in use, this map is automatically populated with additional
|
|
listeners enabling the Envoy proxy to work from inside the network namespace.
|
|
|
|
```
|
|
envoy_gateway_bind_addresses "<service>" {
|
|
address = "0.0.0.0"
|
|
port = <port>
|
|
}
|
|
```
|
|
|
|
- `envoy_gateway_no_default_bind` `(bool: false)` - Prevents binding to the default
|
|
address of the gateway service. This should be used with one of the other options
|
|
to configure the gateway's bind addresses. If `bridge` networking is in use, this
|
|
value will default to `true` since the Envoy proxy does not need to bind to the
|
|
service address from inside the network namespace.
|
|
- `envoy_dns_discovery_type` `(string: optional)` - Determintes how Envoy will
|
|
resolve hostnames. Defaults to `LOGICAL_DNS`. Must be one of `STRICT_DNS` or
|
|
`LOGICAL_DNS`. Details for each type are available in the [Envoy Documentation](https://www.envoyproxy.io/docs/envoy/v1.16.1/intro/arch_overview/upstream/service_discovery).
|
|
This option applies to terminating gateways that route to services addressed by a
|
|
hostname.
|
|
- `config` `(map: nil)` - Escape hatch for [Advanced Configuration] of Envoy.
|
|
|
|
#### `address` Parameters
|
|
|
|
- `address` `(string: required)` - The address to bind to when combined with `port`.
|
|
- `port` `(int: required)` - The port to listen to.
|
|
|
|
### `ingress` Parameters
|
|
|
|
- `tls` <code>([tls]: nil)</code> - TLS configuration for this gateway.
|
|
- `listener` <code>(array<[listener]> : required)</code> - One or more listeners that the
|
|
ingress gateway should setup, uniquely identified by their port number.
|
|
|
|
#### `tls` Parameters
|
|
|
|
- `enabled` `(bool: false)` - Set this configuration to enable TLS for every listener
|
|
on the gateway. If TLS is enabled, then each host defined in the `host` field will
|
|
be added as a DNSSAN to the gateway's x509 certificate.
|
|
|
|
#### `listener` Parameters
|
|
|
|
- `port` `(int: required)` - The port that the listener should receive traffic on.
|
|
- `protocol` `(string: "tcp")` - The protocol associated with the listener. Either
|
|
`tcp` or `http`.
|
|
|
|
~> **Note:** If using `http`, preconfiguring a [service-default] in Consul to
|
|
set the [Protocol](https://www.consul.io/docs/agent/config-entries/service-defaults#protocol)
|
|
of the service to `http` is recommended.
|
|
|
|
- `service` <code>(array<[service]>: required)</code> - One or more services to be
|
|
exposed via this listener. For `tcp` listeners, only a single service is allowed.
|
|
|
|
#### `service` Parameters
|
|
|
|
- `name` `(string: required)` - The name of the service that should be exposed through
|
|
this listener. This can be either a service registered in the catalog, or a
|
|
service defined by other config entries, or a service that is going to be configured
|
|
by Nomad. If the wildcard specifier `*` is provided, then ALL services will be
|
|
exposed through this listener. This is not supported for a listener with protocol `tcp`.
|
|
- `hosts` `(array<string>: nil)` - A list of hosts that specify what requests will
|
|
match this service. This cannot be used with a `tcp` listener, and cannot be
|
|
specified alongside a wildcard (`*`) service name. If not specified, the default
|
|
domain `<service-name>.ingress.*` will be used to match services. Requests _must_
|
|
send the correct host to be routed to the defined service.
|
|
|
|
The wildcard specifier `*` can be used by itself to match all traffic coming to
|
|
the ingress gateway, if TLS is not enabled. This allows a user to route all traffic
|
|
to a single service without specifying a host, allowing simpler tests and demos.
|
|
Otherwise, the wildcard specifier can be used as part of the host to match
|
|
multiple hosts, but only in the leftmost DNS label. This ensures that all defined
|
|
hosts are valid DNS records. For example, `*.example.com` is valid while `example.*`
|
|
and `*-suffix.example.com` are not.
|
|
|
|
~> **Note:** If a well-known port is not used, i.e. a port other than 80 (http) or 443 (https),
|
|
then the port must be appended to the host to correctly match traffic. This is
|
|
defined in the [HTTP/1.1 RFC](https://tools.ietf.org/html/rfc2616#section-14.23).
|
|
If TLS is enabled, then the host **without** the port must be added to the `hosts`
|
|
field as well. TLS verification only matches against the hostname of the incoming
|
|
connection, and does not take into account the port.
|
|
|
|
### `terminating` Parameters
|
|
|
|
- `service` <code>(array<[linked-service]>: required)</code> - One or more services to be
|
|
linked with the gateway. The gateway will proxy traffic to these services. These
|
|
linked services must be registered with Consul for the gateway to discover their
|
|
addresses. They must also be registered in the same Consul datacenter as the
|
|
terminating gateway.
|
|
|
|
#### `service` Parameters
|
|
|
|
- `name` `(string: required)` - The name of the service to link with the gateway.
|
|
If the wildcard specifier `*` is provided, then ALL services within the Consul
|
|
namespace wil lbe linked with the gateway.
|
|
|
|
- `ca_file` `(string: <optional>)` - A file path to a PEM-encoded certificate
|
|
authority. The file must be accessible by the gateway task. The certificate authority
|
|
is used to verify the authenticity of the service linked with the gateway. It
|
|
can be provided along with a `cert_file` and `key_file` for mutual TLS
|
|
authentication, or on its own for one-way TLS authentication. If none is provided
|
|
the gateway **will not** encrypt traffic to the destination.
|
|
- `cert_file` `(string: <optional>)` - A file path to a PEM-encoded certificate.
|
|
The file must be accessible by the gateway task. The certificate is provided to servers
|
|
to verify the gateway's authenticity. It must be provided if a `key_file` is provided.
|
|
- `key_file` `(string: <optional>)` - A file path to a PEM-encoded private key.
|
|
The file must be accessible by the gateway task. The key is used with the certificate
|
|
to verify the gateway's authenticity. It must be provided if a `cert_file` is provided.
|
|
- `sni` `(string: <optional>)` - An optional hostname or domain name to specify during
|
|
the TLS handshake.
|
|
|
|
### Gateway with host networking
|
|
|
|
Nomad supports running gateways using host networking. A static port must be allocated
|
|
for use by the [Envoy admin interface](https://www.envoyproxy.io/docs/envoy/latest/operations/admin)
|
|
and assigned to the proxy service definition.
|
|
|
|
!> **Warning:** There is no way to disable the Envoy admin interface, which will be
|
|
accessible to any workload running on the same Nomad client. The admin interface exposes
|
|
information about the proxy, including a Consul Service Identity token if Consul ACLs
|
|
are enabled.
|
|
|
|
### Specify Envoy image
|
|
|
|
The Docker image used for Connect gateway tasks defaults to the official [Envoy
|
|
Docker] image, `envoyproxy/envoy:v${NOMAD_envoy_version}`, where `${NOMAD_envoy_version}`
|
|
is resolved automatically by a query to Consul. The image to use can be configured
|
|
by setting `meta.connect.gateway_image` in the Nomad job. Custom images can still
|
|
make use of the envoy version interpolation, e.g.
|
|
|
|
```hcl
|
|
meta.connect.gateway_image = custom/envoy-${NOMAD_envoy_version}:latest
|
|
```
|
|
|
|
### Custom gateway task
|
|
|
|
The task created for the gateway can be configured manually using the
|
|
[`sidecar_task`][sidecar_task] stanza.
|
|
|
|
```
|
|
connect {
|
|
gateway {
|
|
# ...
|
|
}
|
|
|
|
sidecar_task {
|
|
# see /docs/job-specification/sidecar_task for more details
|
|
}
|
|
}
|
|
```
|
|
|
|
### Examples
|
|
|
|
#### ingress gateway
|
|
|
|
```hcl
|
|
job "ingress-demo" {
|
|
|
|
datacenters = ["dc1"]
|
|
|
|
# This group will have a task providing the ingress gateway automatically
|
|
# created by Nomad. The ingress gateway is based on the Envoy proxy being
|
|
# managed by the docker driver.
|
|
group "ingress-group" {
|
|
|
|
network {
|
|
mode = "bridge"
|
|
|
|
# This example will enable plain HTTP traffic to access the uuid-api connect
|
|
# native example service on port 8080.
|
|
port "inbound" {
|
|
static = 8080
|
|
to = 8080
|
|
}
|
|
}
|
|
|
|
service {
|
|
name = "my-ingress-service"
|
|
port = "8080"
|
|
|
|
connect {
|
|
gateway {
|
|
|
|
# Consul gateway [envoy] proxy options.
|
|
proxy {
|
|
# The following options are automatically set by Nomad if not
|
|
# explicitly configured when using bridge networking.
|
|
#
|
|
# envoy_gateway_no_default_bind = true
|
|
# envoy_gateway_bind_addresses "uuid-api" {
|
|
# address = "0.0.0.0"
|
|
# port = <associated listener.port>
|
|
# }
|
|
#
|
|
# Additional options are documented at
|
|
# https://www.nomadproject.io/docs/job-specification/gateway#proxy-parameters
|
|
}
|
|
|
|
# Consul Ingress Gateway Configuration Entry.
|
|
ingress {
|
|
# Nomad will automatically manage the Configuration Entry in Consul
|
|
# given the parameters in the ingress block.
|
|
#
|
|
# Additional options are documented at
|
|
# https://www.nomadproject.io/docs/job-specification/gateway#ingress-parameters
|
|
listener {
|
|
port = 8080
|
|
protocol = "tcp"
|
|
service {
|
|
name = "uuid-api"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
# The UUID generator from the connect-native demo is used as an example service.
|
|
# The ingress gateway above makes access to the service possible over normal HTTP.
|
|
# For example,
|
|
#
|
|
# $ curl $(dig +short @127.0.0.1 -p 8600 uuid-api.ingress.dc1.consul. ANY):8080
|
|
group "generator" {
|
|
network {
|
|
mode = "host"
|
|
port "api" {}
|
|
}
|
|
|
|
service {
|
|
name = "uuid-api"
|
|
port = "${NOMAD_PORT_api}"
|
|
|
|
connect {
|
|
native = true
|
|
}
|
|
}
|
|
|
|
task "generate" {
|
|
driver = "docker"
|
|
|
|
config {
|
|
image = "hashicorpnomad/uuid-api:v3"
|
|
network_mode = "host"
|
|
}
|
|
|
|
env {
|
|
BIND = "0.0.0.0"
|
|
PORT = "${NOMAD_PORT_api}"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
#### terminating gateway
|
|
|
|
```hcl
|
|
job "countdash-terminating" {
|
|
|
|
datacenters = ["dc1"]
|
|
|
|
# This group provides the service that exists outside of the Consul Connect
|
|
# service mesh. It is using host networking and listening to a statically
|
|
# allocated port.
|
|
group "api" {
|
|
network {
|
|
mode = "host"
|
|
port "port" {
|
|
static = "9001"
|
|
}
|
|
}
|
|
|
|
# This example will enable services in the service mesh to make requests
|
|
# to this service which is not in the service mesh by making requests
|
|
# through the terminating gateway.
|
|
service {
|
|
name = "count-api"
|
|
port = "port"
|
|
}
|
|
|
|
task "api" {
|
|
driver = "docker"
|
|
|
|
config {
|
|
image = "hashicorpnomad/counter-api:v3"
|
|
network_mode = "host"
|
|
}
|
|
}
|
|
}
|
|
|
|
group "gateway" {
|
|
network {
|
|
mode = "bridge"
|
|
}
|
|
|
|
service {
|
|
name = "api-gateway"
|
|
|
|
connect {
|
|
gateway {
|
|
# Consul gateway [envoy] proxy options.
|
|
proxy {
|
|
# The following options are automatically set by Nomad if not explicitly
|
|
# configured with using bridge networking.
|
|
#
|
|
# envoy_gateway_no_default_bind = true
|
|
# envoy_gateway_bind_addresses "default" {
|
|
# address = "0.0.0.0"
|
|
# port = <generated listener port>
|
|
# }
|
|
# Additional options are documented at
|
|
# https://www.nomadproject.io/docs/job-specification/gateway#proxy-parameters
|
|
}
|
|
|
|
# Consul Terminating Gateway Configuration Entry.
|
|
terminating {
|
|
# Nomad will automatically manage the Configuration Entry in Consul
|
|
# given the parameters in the terminating block.
|
|
#
|
|
# Additional options are documented at
|
|
# https://www.nomadproject.io/docs/job-specification/gateway#terminating-parameters
|
|
service {
|
|
name = "count-api"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
# The dashboard service is in the service mesh, making use of bridge network
|
|
# mode and connect.sidecar_service. When running, the dashboard should be
|
|
# available from a web browser at localhost:9002.
|
|
group "dashboard" {
|
|
network {
|
|
mode = "bridge"
|
|
|
|
port "http" {
|
|
static = 9002
|
|
to = 9002
|
|
}
|
|
}
|
|
|
|
service {
|
|
name = "count-dashboard"
|
|
port = "9002"
|
|
|
|
connect {
|
|
sidecar_service {
|
|
proxy {
|
|
upstreams {
|
|
# By configuring an upstream destination to the linked service of
|
|
# the terminating gateway, the dashboard is able to make requests
|
|
# through the gateway to the count-api service.
|
|
destination_name = "count-api"
|
|
local_bind_port = 8080
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
task "dashboard" {
|
|
driver = "docker"
|
|
|
|
env {
|
|
COUNTING_SERVICE_URL = "http://${NOMAD_UPSTREAM_ADDR_count_api}"
|
|
}
|
|
|
|
config {
|
|
image = "hashicorpnomad/counter-dashboard:v3"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
[address]: /docs/job-specification/gateway#address-parameters
|
|
[advanced configuration]: https://www.consul.io/docs/connect/proxies/envoy#advanced-configuration
|
|
[connect_timeout_ms]: https://www.consul.io/docs/agent/config-entries/service-resolver#connecttimeout
|
|
[envoy docker]: https://hub.docker.com/r/envoyproxy/envoy/tags
|
|
[ingress]: /docs/job-specification/gateway#ingress-parameters
|
|
[proxy]: /docs/job-specification/gateway#proxy-parameters
|
|
[linked-service]: /docs/job-specification/gateway#service-parameters-1
|
|
[listener]: /docs/job-specification/gateway#listener-parameters
|
|
[service]: /docs/job-specification/gateway#service-parameters
|
|
[service-default]: https://www.consul.io/docs/agent/config-entries/service-defaults
|
|
[sidecar_task]: /docs/job-specification/sidecar_task
|
|
[terminating]: /docs/job-specification/gateway#terminating-parameters
|
|
[tls]: /docs/job-specification/gateway#tls-parameters
|
|
|