consul/connect: Add support for Connect terminating gateways

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
This commit is contained in:
Seth Hoenig
2020-12-15 14:38:33 -06:00
parent 85129bb794
commit ceae8ad1cf
28 changed files with 2021 additions and 416 deletions

View File

@@ -110,13 +110,16 @@ func (envoyBootstrapHook) Name() string {
return envoyBootstrapHookName
}
func (_ *envoyBootstrapHook) extractNameAndKind(kind structs.TaskKind) (string, string, error) {
serviceKind := kind.Name()
serviceName := kind.Value()
func isConnectKind(kind string) bool {
kinds := []string{structs.ConnectProxyPrefix, structs.ConnectIngressPrefix, structs.ConnectTerminatingPrefix}
return helper.SliceStringContains(kinds, kind)
}
switch serviceKind {
case structs.ConnectProxyPrefix, structs.ConnectIngressPrefix:
default:
func (_ *envoyBootstrapHook) extractNameAndKind(kind structs.TaskKind) (string, string, error) {
serviceName := kind.Value()
serviceKind := kind.Name()
if !isConnectKind(serviceKind) {
return "", "", errors.New("envoy must be used as connect sidecar or gateway")
}
@@ -350,13 +353,15 @@ func (h *envoyBootstrapHook) newEnvoyBootstrapArgs(
proxyID string // gateway only
)
if service.Connect.HasSidecar() {
switch {
case service.Connect.HasSidecar():
sidecarForID = h.proxyServiceID(group, service)
}
if service.Connect.IsGateway() {
gateway = "ingress" // more types in the future
case service.Connect.IsIngress():
proxyID = h.proxyServiceID(group, service)
gateway = "ingress"
case service.Connect.IsTerminating():
proxyID = h.proxyServiceID(group, service)
gateway = "terminating"
}
h.logger.Debug("bootstrapping envoy",