feat(ingress-gateway): support outlier detection of upstream service for ingress gateway (#15614)
* feat(ingress-gateway): support outlier detection of upstream service for ingress gateway * changelog Co-authored-by: Eric Haberkorn <erichaberkorn@gmail.com>
This commit is contained in:
parent
50a5549f8a
commit
3e37a449c8
|
@ -0,0 +1,7 @@
|
|||
```release-note:feature
|
||||
config-entry(ingress-gateway): support outlier detection (passive health check) for upstream cluster
|
||||
```
|
||||
|
||||
```release-note:breaking-change
|
||||
ingress-gateway: upstream cluster will have empty outlier_detection if passive health check is unspecified
|
||||
```
|
|
@ -317,6 +317,14 @@ func (o *configSnapshotIngressGateway) DeepCopy() *configSnapshotIngressGateway
|
|||
cp.Listeners[k2] = cp_Listeners_v2
|
||||
}
|
||||
}
|
||||
if o.Defaults.PassiveHealthCheck != nil {
|
||||
cp.Defaults.PassiveHealthCheck = new(structs.PassiveHealthCheck)
|
||||
*cp.Defaults.PassiveHealthCheck = *o.Defaults.PassiveHealthCheck
|
||||
if o.Defaults.PassiveHealthCheck.EnforcingConsecutive5xx != nil {
|
||||
cp.Defaults.PassiveHealthCheck.EnforcingConsecutive5xx = new(uint32)
|
||||
*cp.Defaults.PassiveHealthCheck.EnforcingConsecutive5xx = *o.Defaults.PassiveHealthCheck.EnforcingConsecutive5xx
|
||||
}
|
||||
}
|
||||
return &cp
|
||||
}
|
||||
|
||||
|
|
|
@ -43,6 +43,10 @@ type IngressServiceConfig struct {
|
|||
MaxConnections uint32
|
||||
MaxPendingRequests uint32
|
||||
MaxConcurrentRequests uint32
|
||||
|
||||
// PassiveHealthCheck configuration determines how upstream proxy instances will
|
||||
// be monitored for removal from the load balancing pool.
|
||||
PassiveHealthCheck *PassiveHealthCheck `json:",omitempty" alias:"passive_health_check"`
|
||||
}
|
||||
|
||||
type IngressListener struct {
|
||||
|
@ -103,6 +107,10 @@ type IngressService struct {
|
|||
MaxPendingRequests uint32 `json:",omitempty" alias:"max_pending_requests"`
|
||||
MaxConcurrentRequests uint32 `json:",omitempty" alias:"max_concurrent_requests"`
|
||||
|
||||
// PassiveHealthCheck configuration determines how upstream proxy instances will
|
||||
// be monitored for removal from the load balancing pool.
|
||||
PassiveHealthCheck *PassiveHealthCheck `json:",omitempty" alias:"passive_health_check"`
|
||||
|
||||
Meta map[string]string `json:",omitempty"`
|
||||
acl.EnterpriseMeta `hcl:",squash" mapstructure:",squash"`
|
||||
}
|
||||
|
|
|
@ -325,6 +325,14 @@ func (o *IngressListener) DeepCopy() *IngressListener {
|
|||
if o.Services[i2].ResponseHeaders != nil {
|
||||
cp.Services[i2].ResponseHeaders = o.Services[i2].ResponseHeaders.DeepCopy()
|
||||
}
|
||||
if o.Services[i2].PassiveHealthCheck != nil {
|
||||
cp.Services[i2].PassiveHealthCheck = new(PassiveHealthCheck)
|
||||
*cp.Services[i2].PassiveHealthCheck = *o.Services[i2].PassiveHealthCheck
|
||||
if o.Services[i2].PassiveHealthCheck.EnforcingConsecutive5xx != nil {
|
||||
cp.Services[i2].PassiveHealthCheck.EnforcingConsecutive5xx = new(uint32)
|
||||
*cp.Services[i2].PassiveHealthCheck.EnforcingConsecutive5xx = *o.Services[i2].PassiveHealthCheck.EnforcingConsecutive5xx
|
||||
}
|
||||
}
|
||||
if o.Services[i2].Meta != nil {
|
||||
cp.Services[i2].Meta = make(map[string]string, len(o.Services[i2].Meta))
|
||||
for k4, v4 := range o.Services[i2].Meta {
|
||||
|
|
|
@ -849,6 +849,20 @@ func (s *ResourceGenerator) configIngressUpstreamCluster(c *envoy_cluster_v3.Clu
|
|||
if threshold != nil {
|
||||
c.CircuitBreakers.Thresholds = []*envoy_cluster_v3.CircuitBreakers_Thresholds{threshold}
|
||||
}
|
||||
|
||||
// Configure the outlier detector for upstream service
|
||||
var override *structs.PassiveHealthCheck
|
||||
if svc != nil {
|
||||
override = svc.PassiveHealthCheck
|
||||
}
|
||||
outlierDetection := ToOutlierDetection(cfgSnap.IngressGateway.Defaults.PassiveHealthCheck, override, false)
|
||||
|
||||
// Specail handling for failover peering service, which has set MaxEjectionPercent
|
||||
if c.OutlierDetection != nil && c.OutlierDetection.MaxEjectionPercent != nil {
|
||||
outlierDetection.MaxEjectionPercent = &wrappers.UInt32Value{Value: c.OutlierDetection.MaxEjectionPercent.Value}
|
||||
}
|
||||
|
||||
c.OutlierDetection = outlierDetection
|
||||
}
|
||||
|
||||
func (s *ResourceGenerator) makeAppCluster(cfgSnap *proxycfg.ConfigSnapshot, name, pathProtocol string, port int) (*envoy_cluster_v3.Cluster, error) {
|
||||
|
@ -949,7 +963,7 @@ func (s *ResourceGenerator) makeUpstreamClusterForPeerService(
|
|||
|
||||
clusterName := generatePeeredClusterName(uid, tbs)
|
||||
|
||||
outlierDetection := ToOutlierDetection(upstreamConfig.PassiveHealthCheck)
|
||||
outlierDetection := ToOutlierDetection(upstreamConfig.PassiveHealthCheck, nil, true)
|
||||
// We can't rely on health checks for services on cluster peers because they
|
||||
// don't take into account service resolvers, splitters and routers. Setting
|
||||
// MaxEjectionPercent too 100% gives outlier detection the power to eject the
|
||||
|
@ -1084,7 +1098,7 @@ func (s *ResourceGenerator) makeUpstreamClusterForPreparedQuery(upstream structs
|
|||
CircuitBreakers: &envoy_cluster_v3.CircuitBreakers{
|
||||
Thresholds: makeThresholdsIfNeeded(cfg.Limits),
|
||||
},
|
||||
OutlierDetection: ToOutlierDetection(cfg.PassiveHealthCheck),
|
||||
OutlierDetection: ToOutlierDetection(cfg.PassiveHealthCheck, nil, true),
|
||||
}
|
||||
if cfg.Protocol == "http2" || cfg.Protocol == "grpc" {
|
||||
if err := s.setHttp2ProtocolOptions(c); err != nil {
|
||||
|
@ -1327,7 +1341,7 @@ func (s *ResourceGenerator) makeUpstreamClustersForDiscoveryChain(
|
|||
CircuitBreakers: &envoy_cluster_v3.CircuitBreakers{
|
||||
Thresholds: makeThresholdsIfNeeded(upstreamConfig.Limits),
|
||||
},
|
||||
OutlierDetection: ToOutlierDetection(upstreamConfig.PassiveHealthCheck),
|
||||
OutlierDetection: ToOutlierDetection(upstreamConfig.PassiveHealthCheck, nil, true),
|
||||
}
|
||||
|
||||
var lb *structs.LoadBalancer
|
||||
|
|
|
@ -549,6 +549,65 @@ func TestClustersFromSnapshot(t *testing.T) {
|
|||
}, nil)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ingress-with-service-passive-health-check",
|
||||
create: func(t testinf.T) *proxycfg.ConfigSnapshot {
|
||||
return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp",
|
||||
"simple", nil,
|
||||
func(entry *structs.IngressGatewayConfigEntry) {
|
||||
entry.Listeners[0].Services[0].MaxConnections = 4096
|
||||
entry.Listeners[0].Services[0].PassiveHealthCheck = &structs.PassiveHealthCheck{
|
||||
Interval: 5000000000,
|
||||
MaxFailures: 10,
|
||||
}
|
||||
}, nil)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ingress-with-defaults-passive-health-check",
|
||||
create: func(t testinf.T) *proxycfg.ConfigSnapshot {
|
||||
return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp",
|
||||
"simple", nil,
|
||||
func(entry *structs.IngressGatewayConfigEntry) {
|
||||
enforcingConsecutive5xx := uint32(80)
|
||||
entry.Defaults = &structs.IngressServiceConfig{
|
||||
MaxConnections: 2048,
|
||||
MaxPendingRequests: 512,
|
||||
MaxConcurrentRequests: 4096,
|
||||
PassiveHealthCheck: &structs.PassiveHealthCheck{
|
||||
Interval: 5000000000,
|
||||
MaxFailures: 10,
|
||||
EnforcingConsecutive5xx: &enforcingConsecutive5xx,
|
||||
},
|
||||
}
|
||||
}, nil)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ingress-with-overwrite-defaults-passive-health-check",
|
||||
create: func(t testinf.T) *proxycfg.ConfigSnapshot {
|
||||
return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp",
|
||||
"simple", nil,
|
||||
func(entry *structs.IngressGatewayConfigEntry) {
|
||||
defaultEnforcingConsecutive5xx := uint32(80)
|
||||
entry.Defaults = &structs.IngressServiceConfig{
|
||||
MaxConnections: 2048,
|
||||
MaxPendingRequests: 512,
|
||||
PassiveHealthCheck: &structs.PassiveHealthCheck{
|
||||
Interval: 5000000000,
|
||||
EnforcingConsecutive5xx: &defaultEnforcingConsecutive5xx,
|
||||
},
|
||||
}
|
||||
enforcingConsecutive5xx := uint32(50)
|
||||
entry.Listeners[0].Services[0].MaxConnections = 4096
|
||||
entry.Listeners[0].Services[0].MaxPendingRequests = 2048
|
||||
entry.Listeners[0].Services[0].PassiveHealthCheck = &structs.PassiveHealthCheck{
|
||||
Interval: 8000000000,
|
||||
EnforcingConsecutive5xx: &enforcingConsecutive5xx,
|
||||
}
|
||||
}, nil)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ingress-with-chain-external-sni",
|
||||
create: func(t testinf.T) *proxycfg.ConfigSnapshot {
|
||||
|
|
|
@ -175,24 +175,53 @@ func ParseGatewayConfig(m map[string]interface{}) (GatewayConfig, error) {
|
|||
return cfg, err
|
||||
}
|
||||
|
||||
// Return an envoy.OutlierDetection populated by the values from this struct.
|
||||
// Return an envoy.OutlierDetection populated by the values from structs.PassiveHealthChec.
|
||||
// If all values are zero a default empty OutlierDetection will be returned to
|
||||
// enable outlier detection with default values.
|
||||
func ToOutlierDetection(p *structs.PassiveHealthCheck) *envoy_cluster_v3.OutlierDetection {
|
||||
// - If override is not nil, it will overwrite the values from p, e.g., ingress gateway defaults
|
||||
// - allowZero is added to handle the legacy case where connect-proxy and mesh gateway can set 0
|
||||
// for EnforcingConsecutive5xx. Due to the definition of proto of PassiveHealthCheck, ingress
|
||||
// gateway's EnforcingConsecutive5xx must be > 0.
|
||||
func ToOutlierDetection(p *structs.PassiveHealthCheck, override *structs.PassiveHealthCheck, allowZero bool) *envoy_cluster_v3.OutlierDetection {
|
||||
od := &envoy_cluster_v3.OutlierDetection{}
|
||||
if p == nil {
|
||||
if p != nil {
|
||||
|
||||
if p.Interval != 0 {
|
||||
od.Interval = durationpb.New(p.Interval)
|
||||
}
|
||||
if p.MaxFailures != 0 {
|
||||
od.Consecutive_5Xx = &wrappers.UInt32Value{Value: p.MaxFailures}
|
||||
}
|
||||
|
||||
if p.EnforcingConsecutive5xx != nil {
|
||||
// NOTE: EnforcingConsecutive5xx must be great than 0 for ingress-gateway
|
||||
if *p.EnforcingConsecutive5xx != 0 {
|
||||
od.EnforcingConsecutive_5Xx = &wrappers.UInt32Value{Value: *p.EnforcingConsecutive5xx}
|
||||
} else if allowZero {
|
||||
od.EnforcingConsecutive_5Xx = &wrappers.UInt32Value{Value: *p.EnforcingConsecutive5xx}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if override == nil {
|
||||
return od
|
||||
}
|
||||
|
||||
if p.Interval != 0 {
|
||||
od.Interval = durationpb.New(p.Interval)
|
||||
// override the default outlier detection value
|
||||
if override.Interval != 0 {
|
||||
od.Interval = durationpb.New(override.Interval)
|
||||
}
|
||||
if p.MaxFailures != 0 {
|
||||
od.Consecutive_5Xx = &wrappers.UInt32Value{Value: p.MaxFailures}
|
||||
if override.MaxFailures != 0 {
|
||||
od.Consecutive_5Xx = &wrappers.UInt32Value{Value: override.MaxFailures}
|
||||
}
|
||||
|
||||
if p.EnforcingConsecutive5xx != nil {
|
||||
od.EnforcingConsecutive_5Xx = &wrappers.UInt32Value{Value: *p.EnforcingConsecutive5xx}
|
||||
if override.EnforcingConsecutive5xx != nil {
|
||||
// NOTE: EnforcingConsecutive5xx must be great than 0 for ingress-gateway
|
||||
if *override.EnforcingConsecutive5xx != 0 {
|
||||
od.EnforcingConsecutive_5Xx = &wrappers.UInt32Value{Value: *override.EnforcingConsecutive5xx}
|
||||
} else if allowZero {
|
||||
od.EnforcingConsecutive_5Xx = &wrappers.UInt32Value{Value: *override.EnforcingConsecutive5xx}
|
||||
}
|
||||
}
|
||||
|
||||
return od
|
||||
|
|
|
@ -16,6 +16,9 @@
|
|||
}
|
||||
},
|
||||
"connectTimeout": "33s",
|
||||
"outlierDetection": {
|
||||
|
||||
},
|
||||
"lbPolicy": "CLUSTER_PROVIDED"
|
||||
},
|
||||
{
|
||||
|
|
|
@ -16,6 +16,9 @@
|
|||
}
|
||||
},
|
||||
"connectTimeout": "33s",
|
||||
"outlierDetection": {
|
||||
|
||||
},
|
||||
"lbPolicy": "CLUSTER_PROVIDED"
|
||||
},
|
||||
{
|
||||
|
|
73
agent/xds/testdata/clusters/ingress-with-defaults-passive-health-check.latest.golden
vendored
Normal file
73
agent/xds/testdata/clusters/ingress-with-defaults-passive-health-check.latest.golden
vendored
Normal file
|
@ -0,0 +1,73 @@
|
|||
{
|
||||
"versionInfo": "00000001",
|
||||
"resources": [
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster",
|
||||
"name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"altStatName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"type": "EDS",
|
||||
"edsClusterConfig": {
|
||||
"edsConfig": {
|
||||
"ads": {
|
||||
|
||||
},
|
||||
"resourceApiVersion": "V3"
|
||||
}
|
||||
},
|
||||
"connectTimeout": "33s",
|
||||
"circuitBreakers": {
|
||||
"thresholds": [
|
||||
{
|
||||
"maxConnections": 2048,
|
||||
"maxPendingRequests": 512,
|
||||
"maxRequests": 4096
|
||||
}
|
||||
]
|
||||
},
|
||||
"outlierDetection": {
|
||||
"consecutive5xx": 10,
|
||||
"interval": "5s",
|
||||
"enforcingConsecutive5xx": 80
|
||||
},
|
||||
"commonLbConfig": {
|
||||
"healthyPanicThreshold": {
|
||||
|
||||
}
|
||||
},
|
||||
"transportSocket": {
|
||||
"name": "tls",
|
||||
"typedConfig": {
|
||||
"@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext",
|
||||
"commonTlsContext": {
|
||||
"tlsParams": {
|
||||
|
||||
},
|
||||
"tlsCertificates": [
|
||||
{
|
||||
"certificateChain": {
|
||||
"inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n"
|
||||
},
|
||||
"privateKey": {
|
||||
"inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n"
|
||||
}
|
||||
}
|
||||
],
|
||||
"validationContext": {
|
||||
"trustedCa": {
|
||||
"inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n"
|
||||
},
|
||||
"matchSubjectAltNames": [
|
||||
{
|
||||
"exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster",
|
||||
"nonce": "00000001"
|
||||
}
|
71
agent/xds/testdata/clusters/ingress-with-overwrite-defaults-passive-health-check.latest.golden
vendored
Normal file
71
agent/xds/testdata/clusters/ingress-with-overwrite-defaults-passive-health-check.latest.golden
vendored
Normal file
|
@ -0,0 +1,71 @@
|
|||
{
|
||||
"versionInfo": "00000001",
|
||||
"resources": [
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster",
|
||||
"name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"altStatName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"type": "EDS",
|
||||
"edsClusterConfig": {
|
||||
"edsConfig": {
|
||||
"ads": {
|
||||
|
||||
},
|
||||
"resourceApiVersion": "V3"
|
||||
}
|
||||
},
|
||||
"connectTimeout": "33s",
|
||||
"circuitBreakers": {
|
||||
"thresholds": [
|
||||
{
|
||||
"maxConnections": 4096,
|
||||
"maxPendingRequests": 2048
|
||||
}
|
||||
]
|
||||
},
|
||||
"outlierDetection": {
|
||||
"interval": "8s",
|
||||
"enforcingConsecutive5xx": 50
|
||||
},
|
||||
"commonLbConfig": {
|
||||
"healthyPanicThreshold": {
|
||||
|
||||
}
|
||||
},
|
||||
"transportSocket": {
|
||||
"name": "tls",
|
||||
"typedConfig": {
|
||||
"@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext",
|
||||
"commonTlsContext": {
|
||||
"tlsParams": {
|
||||
|
||||
},
|
||||
"tlsCertificates": [
|
||||
{
|
||||
"certificateChain": {
|
||||
"inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n"
|
||||
},
|
||||
"privateKey": {
|
||||
"inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n"
|
||||
}
|
||||
}
|
||||
],
|
||||
"validationContext": {
|
||||
"trustedCa": {
|
||||
"inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n"
|
||||
},
|
||||
"matchSubjectAltNames": [
|
||||
{
|
||||
"exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster",
|
||||
"nonce": "00000001"
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
{
|
||||
"versionInfo": "00000001",
|
||||
"resources": [
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster",
|
||||
"name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"altStatName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"type": "EDS",
|
||||
"edsClusterConfig": {
|
||||
"edsConfig": {
|
||||
"ads": {
|
||||
|
||||
},
|
||||
"resourceApiVersion": "V3"
|
||||
}
|
||||
},
|
||||
"connectTimeout": "33s",
|
||||
"circuitBreakers": {
|
||||
"thresholds": [
|
||||
{
|
||||
"maxConnections": 4096,
|
||||
"maxPendingRequests": 2048
|
||||
}
|
||||
]
|
||||
},
|
||||
"outlierDetection": {
|
||||
"interval": "8s",
|
||||
"enforcingConsecutive5xx": 50
|
||||
},
|
||||
"commonLbConfig": {
|
||||
"healthyPanicThreshold": {
|
||||
|
||||
}
|
||||
},
|
||||
"transportSocket": {
|
||||
"name": "tls",
|
||||
"typedConfig": {
|
||||
"@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext",
|
||||
"commonTlsContext": {
|
||||
"tlsParams": {
|
||||
|
||||
},
|
||||
"tlsCertificates": [
|
||||
{
|
||||
"certificateChain": {
|
||||
"inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n"
|
||||
},
|
||||
"privateKey": {
|
||||
"inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n"
|
||||
}
|
||||
}
|
||||
],
|
||||
"validationContext": {
|
||||
"trustedCa": {
|
||||
"inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n"
|
||||
},
|
||||
"matchSubjectAltNames": [
|
||||
{
|
||||
"exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster",
|
||||
"nonce": "00000001"
|
||||
}
|
70
agent/xds/testdata/clusters/ingress-with-service-passive-health-check.latest.golden
vendored
Normal file
70
agent/xds/testdata/clusters/ingress-with-service-passive-health-check.latest.golden
vendored
Normal file
|
@ -0,0 +1,70 @@
|
|||
{
|
||||
"versionInfo": "00000001",
|
||||
"resources": [
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster",
|
||||
"name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"altStatName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"type": "EDS",
|
||||
"edsClusterConfig": {
|
||||
"edsConfig": {
|
||||
"ads": {
|
||||
|
||||
},
|
||||
"resourceApiVersion": "V3"
|
||||
}
|
||||
},
|
||||
"connectTimeout": "33s",
|
||||
"circuitBreakers": {
|
||||
"thresholds": [
|
||||
{
|
||||
"maxConnections": 4096
|
||||
}
|
||||
]
|
||||
},
|
||||
"outlierDetection": {
|
||||
"consecutive5xx": 10,
|
||||
"interval": "5s"
|
||||
},
|
||||
"commonLbConfig": {
|
||||
"healthyPanicThreshold": {
|
||||
|
||||
}
|
||||
},
|
||||
"transportSocket": {
|
||||
"name": "tls",
|
||||
"typedConfig": {
|
||||
"@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext",
|
||||
"commonTlsContext": {
|
||||
"tlsParams": {
|
||||
|
||||
},
|
||||
"tlsCertificates": [
|
||||
{
|
||||
"certificateChain": {
|
||||
"inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n"
|
||||
},
|
||||
"privateKey": {
|
||||
"inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n"
|
||||
}
|
||||
}
|
||||
],
|
||||
"validationContext": {
|
||||
"trustedCa": {
|
||||
"inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n"
|
||||
},
|
||||
"matchSubjectAltNames": [
|
||||
{
|
||||
"exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster",
|
||||
"nonce": "00000001"
|
||||
}
|
|
@ -17,6 +17,9 @@
|
|||
}
|
||||
},
|
||||
"connectTimeout": "33s",
|
||||
"outlierDetection": {
|
||||
|
||||
},
|
||||
"lbPolicy": "CLUSTER_PROVIDED"
|
||||
},
|
||||
{
|
||||
|
|
|
@ -17,6 +17,9 @@
|
|||
}
|
||||
},
|
||||
"connectTimeout": "33s",
|
||||
"outlierDetection": {
|
||||
|
||||
},
|
||||
"lbPolicy": "CLUSTER_PROVIDED"
|
||||
},
|
||||
{
|
||||
|
|
|
@ -17,6 +17,9 @@
|
|||
}
|
||||
},
|
||||
"connectTimeout": "33s",
|
||||
"outlierDetection": {
|
||||
|
||||
},
|
||||
"lbPolicy": "CLUSTER_PROVIDED"
|
||||
},
|
||||
{
|
||||
|
|
|
@ -17,6 +17,9 @@
|
|||
}
|
||||
},
|
||||
"connectTimeout": "33s",
|
||||
"outlierDetection": {
|
||||
|
||||
},
|
||||
"lbPolicy": "CLUSTER_PROVIDED"
|
||||
},
|
||||
{
|
||||
|
|
|
@ -16,6 +16,9 @@
|
|||
}
|
||||
},
|
||||
"connectTimeout": "33s",
|
||||
"outlierDetection": {
|
||||
|
||||
},
|
||||
"lbPolicy": "CLUSTER_PROVIDED"
|
||||
},
|
||||
{
|
||||
|
|
|
@ -16,6 +16,9 @@
|
|||
}
|
||||
},
|
||||
"connectTimeout": "33s",
|
||||
"outlierDetection": {
|
||||
|
||||
},
|
||||
"lbPolicy": "CLUSTER_PROVIDED"
|
||||
},
|
||||
{
|
||||
|
|
|
@ -16,6 +16,9 @@
|
|||
}
|
||||
},
|
||||
"connectTimeout": "33s",
|
||||
"outlierDetection": {
|
||||
|
||||
},
|
||||
"lbPolicy": "CLUSTER_PROVIDED"
|
||||
},
|
||||
{
|
||||
|
|
|
@ -16,6 +16,9 @@
|
|||
}
|
||||
},
|
||||
"connectTimeout": "33s",
|
||||
"outlierDetection": {
|
||||
|
||||
},
|
||||
"lbPolicy": "CLUSTER_PROVIDED"
|
||||
},
|
||||
{
|
||||
|
|
|
@ -44,6 +44,10 @@ type IngressServiceConfig struct {
|
|||
MaxConnections *uint32
|
||||
MaxPendingRequests *uint32
|
||||
MaxConcurrentRequests *uint32
|
||||
|
||||
// PassiveHealthCheck configuration determines how upstream proxy instances will
|
||||
// be monitored for removal from the load balancing pool.
|
||||
PassiveHealthCheck *PassiveHealthCheck `json:",omitempty" alias:"passive_health_check"`
|
||||
}
|
||||
|
||||
type GatewayTLSConfig struct {
|
||||
|
@ -137,6 +141,10 @@ type IngressService struct {
|
|||
MaxConnections *uint32 `json:",omitempty" alias:"max_connections"`
|
||||
MaxPendingRequests *uint32 `json:",omitempty" alias:"max_pending_requests"`
|
||||
MaxConcurrentRequests *uint32 `json:",omitempty" alias:"max_concurrent_requests"`
|
||||
|
||||
// PassiveHealthCheck configuration determines how upstream proxy instances will
|
||||
// be monitored for removal from the load balancing pool.
|
||||
PassiveHealthCheck *PassiveHealthCheck `json:",omitempty" alias:"passive_health_check"`
|
||||
}
|
||||
|
||||
func (i *IngressGatewayConfigEntry) GetKind() string { return i.Kind }
|
||||
|
|
|
@ -2,6 +2,7 @@ package api
|
|||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
@ -32,6 +33,10 @@ func TestAPI_ConfigEntries_IngressGateway(t *testing.T) {
|
|||
Defaults: &IngressServiceConfig{
|
||||
MaxConnections: uint32Pointer(2048),
|
||||
MaxPendingRequests: uint32Pointer(4096),
|
||||
PassiveHealthCheck: &PassiveHealthCheck{
|
||||
MaxFailures: 20,
|
||||
Interval: 500000000,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -100,6 +105,9 @@ func TestAPI_ConfigEntries_IngressGateway(t *testing.T) {
|
|||
MaxConnections: uint32Pointer(5120),
|
||||
MaxPendingRequests: uint32Pointer(512),
|
||||
MaxConcurrentRequests: uint32Pointer(2048),
|
||||
PassiveHealthCheck: &PassiveHealthCheck{
|
||||
MaxFailures: 10,
|
||||
},
|
||||
},
|
||||
},
|
||||
TLS: &GatewayTLSConfig{
|
||||
|
@ -178,6 +186,10 @@ func TestAPI_ConfigEntries_IngressGateway(t *testing.T) {
|
|||
require.Equal(t, *ingress2.Defaults.MaxConnections, *readIngress.Defaults.MaxConnections)
|
||||
require.Equal(t, uint32(4096), *readIngress.Defaults.MaxPendingRequests)
|
||||
require.Equal(t, uint32(0), *readIngress.Defaults.MaxConcurrentRequests)
|
||||
require.Equal(t, uint32(20), readIngress.Defaults.PassiveHealthCheck.MaxFailures)
|
||||
require.Equal(t, time.Duration(500000000), readIngress.Defaults.PassiveHealthCheck.Interval)
|
||||
require.Nil(t, readIngress.Defaults.PassiveHealthCheck.EnforcingConsecutive5xx)
|
||||
|
||||
require.Len(t, readIngress.Listeners, 1)
|
||||
require.Len(t, readIngress.Listeners[0].Services, 1)
|
||||
// Set namespace and partition to blank so that OSS and ent can utilize the same tests
|
||||
|
|
|
@ -304,6 +304,11 @@ func IngressServiceToStructs(s *IngressService, t *structs.IngressService) {
|
|||
t.MaxConnections = s.MaxConnections
|
||||
t.MaxPendingRequests = s.MaxPendingRequests
|
||||
t.MaxConcurrentRequests = s.MaxConcurrentRequests
|
||||
if s.PassiveHealthCheck != nil {
|
||||
var x structs.PassiveHealthCheck
|
||||
PassiveHealthCheckToStructs(s.PassiveHealthCheck, &x)
|
||||
t.PassiveHealthCheck = &x
|
||||
}
|
||||
t.Meta = s.Meta
|
||||
t.EnterpriseMeta = enterpriseMetaToStructs(s.EnterpriseMeta)
|
||||
}
|
||||
|
@ -331,6 +336,11 @@ func IngressServiceFromStructs(t *structs.IngressService, s *IngressService) {
|
|||
s.MaxConnections = t.MaxConnections
|
||||
s.MaxPendingRequests = t.MaxPendingRequests
|
||||
s.MaxConcurrentRequests = t.MaxConcurrentRequests
|
||||
if t.PassiveHealthCheck != nil {
|
||||
var x PassiveHealthCheck
|
||||
PassiveHealthCheckFromStructs(t.PassiveHealthCheck, &x)
|
||||
s.PassiveHealthCheck = &x
|
||||
}
|
||||
s.Meta = t.Meta
|
||||
s.EnterpriseMeta = enterpriseMetaFromStructs(t.EnterpriseMeta)
|
||||
}
|
||||
|
@ -341,6 +351,11 @@ func IngressServiceConfigToStructs(s *IngressServiceConfig, t *structs.IngressSe
|
|||
t.MaxConnections = s.MaxConnections
|
||||
t.MaxPendingRequests = s.MaxPendingRequests
|
||||
t.MaxConcurrentRequests = s.MaxConcurrentRequests
|
||||
if s.PassiveHealthCheck != nil {
|
||||
var x structs.PassiveHealthCheck
|
||||
PassiveHealthCheckToStructs(s.PassiveHealthCheck, &x)
|
||||
t.PassiveHealthCheck = &x
|
||||
}
|
||||
}
|
||||
func IngressServiceConfigFromStructs(t *structs.IngressServiceConfig, s *IngressServiceConfig) {
|
||||
if s == nil {
|
||||
|
@ -349,6 +364,11 @@ func IngressServiceConfigFromStructs(t *structs.IngressServiceConfig, s *Ingress
|
|||
s.MaxConnections = t.MaxConnections
|
||||
s.MaxPendingRequests = t.MaxPendingRequests
|
||||
s.MaxConcurrentRequests = t.MaxConcurrentRequests
|
||||
if t.PassiveHealthCheck != nil {
|
||||
var x PassiveHealthCheck
|
||||
PassiveHealthCheckFromStructs(t.PassiveHealthCheck, &x)
|
||||
s.PassiveHealthCheck = &x
|
||||
}
|
||||
}
|
||||
func IntentionHTTPHeaderPermissionToStructs(s *IntentionHTTPHeaderPermission, t *structs.IntentionHTTPHeaderPermission) {
|
||||
if s == nil {
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -242,6 +242,7 @@ message IngressServiceConfig {
|
|||
uint32 MaxConnections = 1;
|
||||
uint32 MaxPendingRequests = 2;
|
||||
uint32 MaxConcurrentRequests = 3;
|
||||
PassiveHealthCheck PassiveHealthCheck = 4;
|
||||
}
|
||||
|
||||
// mog annotation:
|
||||
|
@ -300,6 +301,7 @@ message IngressService {
|
|||
uint32 MaxConnections = 8;
|
||||
uint32 MaxPendingRequests = 9;
|
||||
uint32 MaxConcurrentRequests = 10;
|
||||
PassiveHealthCheck PassiveHealthCheck = 11;
|
||||
}
|
||||
|
||||
// mog annotation:
|
||||
|
|
|
@ -10,6 +10,9 @@ services {
|
|||
local_bind_port = 5000
|
||||
config {
|
||||
protocol = "http"
|
||||
passive_health_check {
|
||||
interval = "22s"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
|
|
|
@ -69,6 +69,15 @@ load helpers
|
|||
[ "$UPS" = "envoy.filters.http.router" ]
|
||||
}
|
||||
|
||||
@test "s1 proxy should have been configured with passive_health_check" {
|
||||
CLUSTER_CONFIG=$(get_envoy_cluster_config localhost:19000 1a47f6e1~s2.default.primary)
|
||||
echo $CLUSTER_CONFIG
|
||||
|
||||
[ "$(echo $CLUSTER_CONFIG | jq --raw-output '.outlier_detection.interval')" = "22s" ]
|
||||
[ "$(echo $CLUSTER_CONFIG | jq --raw-output '.outlier_detection.consecutive_5xx')" = null ]
|
||||
[ "$(echo $CLUSTER_CONFIG | jq --raw-output '.outlier_detection.enforcing_consecutive_5xx')" = null ]
|
||||
}
|
||||
|
||||
@test "s2 proxy should have been configured with http rbac filters" {
|
||||
HTTP_FILTERS=$(get_envoy_http_filters localhost:19001)
|
||||
PUB=$(echo "$HTTP_FILTERS" | grep -E "^public_listener:" | cut -f 2 -d ' ')
|
||||
|
|
|
@ -23,11 +23,11 @@ load helpers
|
|||
}
|
||||
|
||||
@test "ingress-gateway should have healthy endpoints for s1" {
|
||||
assert_upstream_has_endpoints_in_status 127.0.0.1:20000 s1 HEALTHY 1
|
||||
assert_upstream_has_endpoints_in_status 127.0.0.1:20000 s1 HEALTHY 1
|
||||
}
|
||||
|
||||
@test "ingress-gateway should have healthy endpoints for s2" {
|
||||
assert_upstream_has_endpoints_in_status 127.0.0.1:20000 s2 HEALTHY 1
|
||||
assert_upstream_has_endpoints_in_status 127.0.0.1:20000 s2 HEALTHY 1
|
||||
}
|
||||
|
||||
@test "ingress should be able to connect to s1 via configured path" {
|
||||
|
|
|
@ -17,6 +17,11 @@ Defaults {
|
|||
MaxConnections = 10
|
||||
MaxPendingRequests = 20
|
||||
MaxConcurrentRequests = 30
|
||||
|
||||
PassiveHealthCheck {
|
||||
MaxFailures = 10
|
||||
Interval = 5000000000
|
||||
}
|
||||
}
|
||||
listeners = [
|
||||
{
|
||||
|
@ -38,6 +43,9 @@ listeners = [
|
|||
MaxConnections = 100
|
||||
MaxPendingRequests = 200
|
||||
MaxConcurrentRequests = 300
|
||||
PassiveHealthCheck {
|
||||
MaxFailures = 15
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -55,6 +55,23 @@ load helpers
|
|||
[ "$MAX_REQS" = "30" ]
|
||||
}
|
||||
|
||||
@test "s2 proxy should have been configured with outlier detection in ingress gateway" {
|
||||
CLUSTER_THRESHOLD=$(get_envoy_cluster_config 127.0.0.1:20000 s2.default.primary | jq '.outlier_detection')
|
||||
echo $CLUSTER_THRESHOLD
|
||||
|
||||
INTERVAL=$(echo $CLUSTER_THRESHOLD | jq --raw-output '.interval')
|
||||
CONSECTIVE5xx=$(echo $CLUSTER_THRESHOLD | jq --raw-output '.consecutive_5xx')
|
||||
ENFORCING_CONSECTIVE5xx=$(echo $CLUSTER_THRESHOLD | jq --raw-output '.enforcing_consecutive_5xx')
|
||||
|
||||
echo "INTERVAL = $INTERVAL"
|
||||
echo "CONSECTIVE5xx = $CONSECTIVE5xx"
|
||||
echo "ENFORCING_CONSECTIVE5xx = $ENFORCING_CONSECTIVE5xx"
|
||||
|
||||
[ "$INTERVAL" = "5s" ]
|
||||
[ "$CONSECTIVE5xx" = "10" ]
|
||||
[ "$ENFORCING_CONSECTIVE5xx" = null ]
|
||||
}
|
||||
|
||||
@test "ingress should be able to connect to s1 using Host header" {
|
||||
assert_expected_fortio_name s1 s1.ingress.consul 9999
|
||||
}
|
||||
|
|
|
@ -9,6 +9,9 @@ Defaults {
|
|||
MaxConnections = 10
|
||||
MaxPendingRequests = 20
|
||||
MaxConcurrentRequests = 30
|
||||
PassiveHealthCheck {
|
||||
Interval = 5000000000
|
||||
}
|
||||
}
|
||||
listeners = [
|
||||
{
|
||||
|
|
|
@ -39,6 +39,23 @@ load helpers
|
|||
[ "$MAX_REQS" = "30" ]
|
||||
}
|
||||
|
||||
@test "s1 proxy should have been configured with outlier detection in ingress gateway" {
|
||||
CLUSTER_THRESHOLD=$(get_envoy_cluster_config 127.0.0.1:20000 s1.default.primary | jq '.outlier_detection')
|
||||
echo $CLUSTER_THRESHOLD
|
||||
|
||||
INTERVAL=$(echo $CLUSTER_THRESHOLD | jq --raw-output '.interval')
|
||||
CONSECTIVE5xx=$(echo $CLUSTER_THRESHOLD | jq --raw-output '.consecutive_5xx')
|
||||
ENFORCING_CONSECTIVE5xx=$(echo $CLUSTER_THRESHOLD | jq --raw-output '.enforcing_consecutive_5xx')
|
||||
|
||||
echo "INTERVAL = $INTERVAL"
|
||||
echo "CONSECTIVE5xx = $CONSECTIVE5xx"
|
||||
echo "ENFORCING_CONSECTIVE5xx = $ENFORCING_CONSECTIVE5xx"
|
||||
|
||||
[ "$INTERVAL" = "5s" ]
|
||||
[ "$CONSECTIVE5xx" = null ]
|
||||
[ "$ENFORCING_CONSECTIVE5xx" = null ]
|
||||
}
|
||||
|
||||
@test "ingress should be able to connect to s1 via configured port" {
|
||||
run retry_default curl -s -f -d hello localhost:9999
|
||||
[ "$status" -eq 0 ]
|
||||
|
|
|
@ -30,9 +30,9 @@ load helpers
|
|||
CLUSTER_THRESHOLD=$(get_envoy_cluster_config localhost:19000 s2.default.primary | jq '.circuit_breakers.thresholds[0]')
|
||||
echo $CLUSTER_THRESHOLD
|
||||
|
||||
MAX_CONNS=$(echo $CLUSTER_THRESHOLD | jq --raw-output '.max_connections')
|
||||
MAX_PENDING_REQS=$(echo $CLUSTER_THRESHOLD | jq --raw-output '.max_pending_requests')
|
||||
MAX_REQS=$(echo $CLUSTER_THRESHOLD | jq --raw-output '.max_requests')
|
||||
MAX_CONNS=$(echo $CLUSTER_THRESHOLD | jq --raw-output '.max_connections')
|
||||
MAX_PENDING_REQS=$(echo $CLUSTER_THRESHOLD | jq --raw-output '.max_pending_requests')
|
||||
MAX_REQS=$(echo $CLUSTER_THRESHOLD | jq --raw-output '.max_requests')
|
||||
|
||||
echo "MAX_CONNS = $MAX_CONNS"
|
||||
echo "MAX_PENDING_REQS = $MAX_PENDING_REQS"
|
||||
|
|
|
@ -1076,6 +1076,32 @@ You can specify the following parameters to configure ingress gateway configurat
|
|||
respected, a L7 protocol must be defined in the \`protocol\` field.
|
||||
If not specified, it uses the default value. For example, 1024 for Envoy proxy.`,
|
||||
},
|
||||
{
|
||||
name: 'PassiveHealthCheck',
|
||||
type: 'PassiveHealthCheck: <optional>',
|
||||
description:
|
||||
'Passive health checks remove hosts from the upstream cluster that are unreachable or that return errors.',
|
||||
children: [
|
||||
{
|
||||
name: 'interval',
|
||||
type: 'int: <optional>',
|
||||
description:
|
||||
"The time in nanosecond between checks. Each check will cause hosts which have exceeded `max_failures` to be removed from the load balancer, and any hosts which have passed their ejection time to be returned to the load balancer. If not specified, it uses the default value. For example, 10s for Envoy proxy.",
|
||||
},
|
||||
{
|
||||
name: 'max_failures',
|
||||
type: 'int: <optional>',
|
||||
description:
|
||||
'The number of consecutive failures that cause a host to be removed from the upstream cluster. If not specified, Consul uses the proxy\'s default value. For example, `5` for Envoy proxy.',
|
||||
},
|
||||
{
|
||||
name: 'enforcing_consecutive_5xx',
|
||||
type: 'int: <optional>',
|
||||
description:
|
||||
'A percentage representing the chance that a host will be actually ejected when the proxy detects an outlier status through consecutive errors in the 500 code range. If not specified, Consul uses the proxy\'s default value. For example, `100` for Envoy proxy.',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
|
@ -1208,6 +1234,25 @@ You can specify the following parameters to configure ingress gateway configurat
|
|||
type: 'int: 0',
|
||||
description: 'overrides for the [`Defaults` field](#available-fields)',
|
||||
},
|
||||
{
|
||||
name: 'PassiveHealthCheck',
|
||||
type: 'PassiveHealthCheck: <optional>',
|
||||
description: 'overrides for the [`Defaults` field](#available-fields)',
|
||||
children: [
|
||||
{
|
||||
name: 'interval',
|
||||
type: 'int: <optional>',
|
||||
},
|
||||
{
|
||||
name: 'max_failures',
|
||||
type: 'int: <optional>',
|
||||
},
|
||||
{
|
||||
name: 'enforcing_consecutive_5xx',
|
||||
type: 'int: <optional>',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
|
|
|
@ -393,17 +393,21 @@ definition](/docs/connect/registration/service-registration) or
|
|||
since HTTP/2 has many requests per connection. For this configuration to be
|
||||
respected, a L7 protocol must be defined in the `protocol` field.
|
||||
|
||||
- `passive_health_check` - Passive health checks are used to remove hosts from
|
||||
the upstream cluster which are unreachable or are returning errors.
|
||||
- `passive_health_check` - Passive health checks remove hosts from the upstream
|
||||
cluster that are unreachable or that return errors.
|
||||
|
||||
- `interval` - The time between checks. Each check will cause hosts which
|
||||
have exceeded `max_failures` to be removed from the load balancer, and
|
||||
any hosts which have passed their ejection time to be returned to the
|
||||
load balancer.
|
||||
- `max_failures` - The number of consecutive failures which cause a host to be
|
||||
removed from the load balancer.
|
||||
- `enforcing_consecutive_5xx` - The % chance that a host will be actually ejected
|
||||
when an outlier status is detected through consecutive 5xx.
|
||||
- `interval` - The time in nanosecond between checks. Each check will cause
|
||||
hosts which have exceeded `max_failures` to be removed from the load
|
||||
balancer, and any hosts which have passed their ejection time to be
|
||||
returned to the load balancer. If not specified, it uses the default value.
|
||||
For example, 10s for Envoy proxy.
|
||||
- `max_failures` - The number of consecutive failures that cause a host to be
|
||||
removed from the upstream cluster. If not specified, Consul uses the proxy's
|
||||
default value. For example, `5` for Envoy proxy.
|
||||
- `enforcing_consecutive_5xx` - A percentage representing the chance that a
|
||||
host will be actually ejected when the proxy detects an outlier status
|
||||
through consecutive errors in the 500 code range. If not specified, Consul
|
||||
uses the proxy's default value. For example, `100` for Envoy proxy.
|
||||
|
||||
- `balance_outbound_connections` - Specifies the strategy for balancing outbound connections
|
||||
across Envoy worker threads. Consul service mesh Envoy integration supports the
|
||||
|
|
Loading…
Reference in New Issue