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:
cskh 2022-12-13 11:51:37 -05:00 committed by GitHub
parent 50a5549f8a
commit 3e37a449c8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
36 changed files with 1124 additions and 496 deletions

7
.changelog/15614.txt Normal file
View File

@ -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
```

View File

@ -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
}

View File

@ -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"`
}

View File

@ -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 {

View File

@ -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

View File

@ -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 {

View File

@ -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

View File

@ -16,6 +16,9 @@
}
},
"connectTimeout": "33s",
"outlierDetection": {
},
"lbPolicy": "CLUSTER_PROVIDED"
},
{

View File

@ -16,6 +16,9 @@
}
},
"connectTimeout": "33s",
"outlierDetection": {
},
"lbPolicy": "CLUSTER_PROVIDED"
},
{

View 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"
}

View 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"
}

View 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"
}

View 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"
}

View File

@ -17,6 +17,9 @@
}
},
"connectTimeout": "33s",
"outlierDetection": {
},
"lbPolicy": "CLUSTER_PROVIDED"
},
{

View File

@ -17,6 +17,9 @@
}
},
"connectTimeout": "33s",
"outlierDetection": {
},
"lbPolicy": "CLUSTER_PROVIDED"
},
{

View File

@ -17,6 +17,9 @@
}
},
"connectTimeout": "33s",
"outlierDetection": {
},
"lbPolicy": "CLUSTER_PROVIDED"
},
{

View File

@ -17,6 +17,9 @@
}
},
"connectTimeout": "33s",
"outlierDetection": {
},
"lbPolicy": "CLUSTER_PROVIDED"
},
{

View File

@ -16,6 +16,9 @@
}
},
"connectTimeout": "33s",
"outlierDetection": {
},
"lbPolicy": "CLUSTER_PROVIDED"
},
{

View File

@ -16,6 +16,9 @@
}
},
"connectTimeout": "33s",
"outlierDetection": {
},
"lbPolicy": "CLUSTER_PROVIDED"
},
{

View File

@ -16,6 +16,9 @@
}
},
"connectTimeout": "33s",
"outlierDetection": {
},
"lbPolicy": "CLUSTER_PROVIDED"
},
{

View File

@ -16,6 +16,9 @@
}
},
"connectTimeout": "33s",
"outlierDetection": {
},
"lbPolicy": "CLUSTER_PROVIDED"
},
{

View File

@ -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 }

View File

@ -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

View File

@ -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

View File

@ -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:

View File

@ -10,6 +10,9 @@ services {
local_bind_port = 5000
config {
protocol = "http"
passive_health_check {
interval = "22s"
}
}
}
]

View File

@ -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 ' ')

View File

@ -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" {

View File

@ -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
}
}
]
}

View File

@ -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
}

View File

@ -9,6 +9,9 @@ Defaults {
MaxConnections = 10
MaxPendingRequests = 20
MaxConcurrentRequests = 30
PassiveHealthCheck {
Interval = 5000000000
}
}
listeners = [
{

View File

@ -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 ]

View File

@ -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"

View File

@ -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>',
},
],
},
],
},
{

View File

@ -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