mirror of https://github.com/hashicorp/consul
agent/xds: Update mesh gateway to use service router timeout (#7444)
* website/connect/proxy/envoy: specify timeout precedence for services behind mesh gatewaypull/7464/head
parent
5c7b3762e3
commit
bef693df9c
|
@ -159,20 +159,28 @@ func (s *Server) clustersFromSnapshotMeshGateway(cfgSnap *proxycfg.ConfigSnapsho
|
||||||
// generate the per-service clusters
|
// generate the per-service clusters
|
||||||
for svc, _ := range cfgSnap.MeshGateway.ServiceGroups {
|
for svc, _ := range cfgSnap.MeshGateway.ServiceGroups {
|
||||||
clusterName := connect.ServiceSNI(svc.ID, "", svc.NamespaceOrDefault(), cfgSnap.Datacenter, cfgSnap.Roots.TrustDomain)
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
clusters = append(clusters, cluster)
|
clusters = append(clusters, cluster)
|
||||||
|
|
||||||
// if there is a service-resolver for this service then also setup subset clusters for it
|
// 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
|
// 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)
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
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) {
|
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)
|
cfg, err := ParseMeshGatewayConfig(cfgSnap.Proxy.Config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Don't hard fail on a config typo, just warn. The parse func returns
|
// 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)
|
s.Logger.Warn("failed to parse mesh gateway config", "error", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if connectTimeout <= 0 {
|
||||||
|
connectTimeout = time.Duration(cfg.ConnectTimeoutMs) * time.Millisecond
|
||||||
|
}
|
||||||
|
|
||||||
return &envoy.Cluster{
|
return &envoy.Cluster{
|
||||||
Name: clusterName,
|
Name: clusterName,
|
||||||
ConnectTimeout: time.Duration(cfg.ConnectTimeoutMs) * time.Millisecond,
|
ConnectTimeout: connectTimeout,
|
||||||
ClusterDiscoveryType: &envoy.Cluster_Type{Type: envoy.Cluster_EDS},
|
ClusterDiscoveryType: &envoy.Cluster_Type{Type: envoy.Cluster_EDS},
|
||||||
EdsClusterConfig: &envoy.Cluster_EdsClusterConfig{
|
EdsClusterConfig: &envoy.Cluster_EdsClusterConfig{
|
||||||
EdsConfig: &envoycore.ConfigSource{
|
EdsConfig: &envoycore.ConfigSource{
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"sort"
|
"sort"
|
||||||
"testing"
|
"testing"
|
||||||
"text/template"
|
"text/template"
|
||||||
|
"time"
|
||||||
|
|
||||||
envoy "github.com/envoyproxy/go-control-plane/envoy/api/v2"
|
envoy "github.com/envoyproxy/go-control-plane/envoy/api/v2"
|
||||||
"github.com/hashicorp/consul/agent/proxycfg"
|
"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 {
|
for _, tt := range tests {
|
||||||
|
|
|
@ -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"
|
||||||
|
}
|
|
@ -288,8 +288,11 @@ entry](/docs/agent/config_entries.html#proxy-defaults-proxy-defaults) to act as
|
||||||
defaults that are inherited by all services.
|
defaults that are inherited by all services.
|
||||||
|
|
||||||
- `connect_timeout_ms` - The number of milliseconds to allow when making upstream
|
- `connect_timeout_ms` - The number of milliseconds to allow when making upstream
|
||||||
connections before timing out. Defaults to 5000
|
connections before timing out. Defaults to 5000 (5 seconds). If the upstream
|
||||||
(5 seconds).
|
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
|
- `envoy_mesh_gateway_bind_tagged_addresses` - Indicates that the mesh gateway
|
||||||
services tagged addresses should be bound to listeners in addition to the
|
services tagged addresses should be bound to listeners in addition to the
|
||||||
|
|
Loading…
Reference in New Issue