agent/xds: Update mesh gateway to use service router timeout (#7444)

* website/connect/proxy/envoy: specify timeout precedence for services behind mesh gateway
This commit is contained in:
Kim Ngo 2020-03-17 14:50:14 -05:00 committed by GitHub
parent 5c7b3762e3
commit bef693df9c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 140 additions and 7 deletions

View File

@ -159,20 +159,28 @@ func (s *Server) clustersFromSnapshotMeshGateway(cfgSnap *proxycfg.ConfigSnapsho
// generate the per-service clusters
for svc, _ := range cfgSnap.MeshGateway.ServiceGroups {
clusterName := connect.ServiceSNI(svc.ID, "", svc.NamespaceOrDefault(), cfgSnap.Datacenter, cfgSnap.Roots.TrustDomain)
resolver, hasResolver := cfgSnap.MeshGateway.ServiceResolvers[svc]
cluster, err := s.makeMeshGatewayCluster(clusterName, cfgSnap)
// Create the cluster for default/unnamed services
var cluster *envoy.Cluster
var err error
if hasResolver {
cluster, err = s.makeMeshGatewayClusterWithConnectTimeout(clusterName, cfgSnap, resolver.ConnectTimeout)
} else {
cluster, err = s.makeMeshGatewayCluster(clusterName, cfgSnap)
}
if err != nil {
return nil, err
}
clusters = append(clusters, cluster)
// if there is a service-resolver for this service then also setup subset clusters for it
if resolver, ok := cfgSnap.MeshGateway.ServiceResolvers[svc]; ok {
if hasResolver {
// generate 1 cluster for each service subset
for subsetName, _ := range resolver.Subsets {
for subsetName := range resolver.Subsets {
clusterName := connect.ServiceSNI(svc.ID, subsetName, svc.NamespaceOrDefault(), cfgSnap.Datacenter, cfgSnap.Roots.TrustDomain)
cluster, err := s.makeMeshGatewayCluster(clusterName, cfgSnap)
cluster, err := s.makeMeshGatewayClusterWithConnectTimeout(clusterName, cfgSnap, resolver.ConnectTimeout)
if err != nil {
return nil, err
}
@ -464,6 +472,14 @@ func makeClusterFromUserConfig(configJSON string) (*envoy.Cluster, error) {
}
func (s *Server) makeMeshGatewayCluster(clusterName string, cfgSnap *proxycfg.ConfigSnapshot) (*envoy.Cluster, error) {
return s.makeMeshGatewayClusterWithConnectTimeout(clusterName, cfgSnap, 0)
}
// makeMeshGatewayClusterWithConnectTimeout initializes a mesh gateway cluster
// with the specified connect timeout. If the timeout is 0, the connect timeout
// defaults to use the mesh gateway timeout.
func (s *Server) makeMeshGatewayClusterWithConnectTimeout(clusterName string, cfgSnap *proxycfg.ConfigSnapshot,
connectTimeout time.Duration) (*envoy.Cluster, error) {
cfg, err := ParseMeshGatewayConfig(cfgSnap.Proxy.Config)
if err != nil {
// Don't hard fail on a config typo, just warn. The parse func returns
@ -471,9 +487,13 @@ func (s *Server) makeMeshGatewayCluster(clusterName string, cfgSnap *proxycfg.Co
s.Logger.Warn("failed to parse mesh gateway config", "error", err)
}
if connectTimeout <= 0 {
connectTimeout = time.Duration(cfg.ConnectTimeoutMs) * time.Millisecond
}
return &envoy.Cluster{
Name: clusterName,
ConnectTimeout: time.Duration(cfg.ConnectTimeoutMs) * time.Millisecond,
ConnectTimeout: connectTimeout,
ClusterDiscoveryType: &envoy.Cluster_Type{Type: envoy.Cluster_EDS},
EdsClusterConfig: &envoy.Cluster_EdsClusterConfig{
EdsConfig: &envoycore.ConfigSource{

View File

@ -6,6 +6,7 @@ import (
"sort"
"testing"
"text/template"
"time"
envoy "github.com/envoyproxy/go-control-plane/envoy/api/v2"
"github.com/hashicorp/consul/agent/proxycfg"
@ -316,6 +317,28 @@ func TestClustersFromSnapshot(t *testing.T) {
}
},
},
{
name: "mesh-gateway-service-timeouts",
create: proxycfg.TestConfigSnapshotMeshGateway,
setup: func(snap *proxycfg.ConfigSnapshot) {
snap.MeshGateway.ServiceResolvers = map[structs.ServiceID]*structs.ServiceResolverConfigEntry{
structs.NewServiceID("bar", nil): &structs.ServiceResolverConfigEntry{
Kind: structs.ServiceResolver,
Name: "bar",
ConnectTimeout: 10 * time.Second,
Subsets: map[string]structs.ServiceResolverSubset{
"v1": structs.ServiceResolverSubset{
Filter: "Service.Meta.Version == 1",
},
"v2": structs.ServiceResolverSubset{
Filter: "Service.Meta.Version == 2",
OnlyPassing: true,
},
},
},
}
},
},
}
for _, tt := range tests {

View File

@ -0,0 +1,87 @@
{
"versionInfo": "00000001",
"resources": [
{
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
"name": "bar.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
"type": "EDS",
"edsClusterConfig": {
"edsConfig": {
"ads": {
}
}
},
"connectTimeout": "10s",
"outlierDetection": {
}
},
{
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
"name": "dc2.internal.11111111-2222-3333-4444-555555555555.consul",
"type": "EDS",
"edsClusterConfig": {
"edsConfig": {
"ads": {
}
}
},
"connectTimeout": "5s",
"outlierDetection": {
}
},
{
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
"name": "foo.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
"type": "EDS",
"edsClusterConfig": {
"edsConfig": {
"ads": {
}
}
},
"connectTimeout": "5s",
"outlierDetection": {
}
},
{
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
"name": "v1.bar.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
"type": "EDS",
"edsClusterConfig": {
"edsConfig": {
"ads": {
}
}
},
"connectTimeout": "10s",
"outlierDetection": {
}
},
{
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
"name": "v2.bar.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
"type": "EDS",
"edsClusterConfig": {
"edsConfig": {
"ads": {
}
}
},
"connectTimeout": "10s",
"outlierDetection": {
}
}
],
"typeUrl": "type.googleapis.com/envoy.api.v2.Cluster",
"nonce": "00000001"
}

View File

@ -288,8 +288,11 @@ entry](/docs/agent/config_entries.html#proxy-defaults-proxy-defaults) to act as
defaults that are inherited by all services.
- `connect_timeout_ms` - The number of milliseconds to allow when making upstream
connections before timing out. Defaults to 5000
(5 seconds).
connections before timing out. Defaults to 5000 (5 seconds). If the upstream
service has the configuration option
[`connect_timeout_ms`](/docs/agent/config-entries/service-resolver.html#connecttimeout)
set for the `service-resolver`, that timeout value will take precedence over
this mesh gateway option.
- `envoy_mesh_gateway_bind_tagged_addresses` - Indicates that the mesh gateway
services tagged addresses should be bound to listeners in addition to the