Skip to content

Commit 8fa767a

Browse files
authored
feat: add admission control to BackendTrafficPolicy (#8872)
1 parent bef5ed1 commit 8fa767a

26 files changed

Lines changed: 2677 additions & 4 deletions

api/v1alpha1/admission_control.go

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
// Copyright Envoy Gateway Authors
2+
// SPDX-License-Identifier: Apache-2.0
3+
// The full text of the Apache license is available in the LICENSE file at
4+
// the root of the repo.
5+
6+
package v1alpha1
7+
8+
import (
9+
gwapiv1 "sigs.k8s.io/gateway-api/apis/v1"
10+
)
11+
12+
// AdmissionControl configures health-based load shedding for upstream backends.
13+
//
14+
// Envoy tracks recent upstream responses over a sliding sampling window. When the
15+
// observed success rate drops below the configured threshold, Envoy
16+
// probabilistically rejects new requests before forwarding them upstream. This can
17+
// reduce pressure on degraded backends and give them time to recover.
18+
//
19+
// All fields are optional. When omitted, Envoy's admission control defaults are used.
20+
//
21+
// +kubebuilder:validation:XValidation:rule="!has(self.minSuccessRate) || (self.minSuccessRate >= 1 && self.minSuccessRate <= 100)",message="minSuccessRate must be between 1 and 100"
22+
// +kubebuilder:validation:XValidation:rule="!has(self.maxRejectionPercent) || (self.maxRejectionPercent >= 0 && self.maxRejectionPercent <= 100)",message="maxRejectionPercent must be between 0 and 100"
23+
// +kubebuilder:validation:XValidation:rule="!has(self.samplingWindow) || duration(self.samplingWindow) >= duration('1s')",message="samplingWindow must be at least 1s"
24+
type AdmissionControl struct {
25+
// SamplingWindow defines the time window over which request success rates are calculated.
26+
// Must be at least 1s; Envoy truncates the window to whole seconds and uses it as the
27+
// denominator in RPS calculations, so sub-second values would produce a zero denominator.
28+
// Defaults to 30s if not specified.
29+
//
30+
// +optional
31+
SamplingWindow *gwapiv1.Duration `json:"samplingWindow,omitempty"`
32+
33+
// MinSuccessRate is the lowest request success rate, as a percentage in the
34+
// range [1, 100], at which the filter will not reject requests. Defaults to 95 if
35+
// not specified. Envoy rejects values below 1%, so values lower than 1 are not allowed.
36+
//
37+
// +optional
38+
// +kubebuilder:validation:Minimum=1
39+
// +kubebuilder:validation:Maximum=100
40+
MinSuccessRate *uint32 `json:"minSuccessRate,omitempty"`
41+
42+
// RejectionAggression controls how steeply the rejection probability rises
43+
// as the observed success rate falls below MinSuccessRate. A value of 1
44+
// produces a linear curve; higher values reject more aggressively for a
45+
// given drop in success rate. Must be greater than 0; values below 1 are
46+
// clamped to 1. Defaults to 1.
47+
//
48+
// +optional
49+
// +kubebuilder:validation:Minimum=1
50+
RejectionAggression *uint32 `json:"rejectionAggression,omitempty"`
51+
52+
// MinRequestRate defines the minimum requests per second below which requests will
53+
// pass through the filter without rejection. Defaults to 0 if not specified.
54+
//
55+
// +optional
56+
// +kubebuilder:validation:Minimum=0
57+
MinRequestRate *uint32 `json:"minRequestRate,omitempty"`
58+
59+
// MaxRejectionPercent represents the upper limit of the rejection probability,
60+
// expressed as a percentage in the range [0, 100]. Defaults to 80 if not specified.
61+
//
62+
// +optional
63+
// +kubebuilder:validation:Minimum=0
64+
// +kubebuilder:validation:Maximum=100
65+
MaxRejectionPercent *uint32 `json:"maxRejectionPercent,omitempty"`
66+
67+
// SuccessCriteria defines what constitutes a successful request for both HTTP and gRPC.
68+
//
69+
// +optional
70+
SuccessCriteria *AdmissionControlSuccessCriteria `json:"successCriteria,omitempty"`
71+
}
72+
73+
// AdmissionControlSuccessCriteria defines the criteria for determining successful requests.
74+
type AdmissionControlSuccessCriteria struct {
75+
// HTTP defines success criteria for HTTP requests.
76+
//
77+
// +optional
78+
HTTP *HTTPSuccessCriteria `json:"http,omitempty"`
79+
80+
// GRPC defines success criteria for gRPC requests.
81+
//
82+
// +optional
83+
GRPC *GRPCSuccessCriteria `json:"grpc,omitempty"`
84+
}
85+
86+
// HTTPSuccessCriteria defines success criteria for HTTP requests.
87+
type HTTPSuccessCriteria struct {
88+
// StatusCodes defines HTTP status codes that are considered successful.
89+
//
90+
// +optional
91+
StatusCodes []HTTPStatus `json:"statusCodes,omitempty"`
92+
}
93+
94+
// GRPCSuccessCode defines gRPC status codes as defined in
95+
// https://github.com/grpc/grpc/blob/master/doc/statuscodes.md#status-codes-and-their-use-in-grpc.
96+
// +kubebuilder:validation:Enum=Ok;Cancelled;Unknown;InvalidArgument;DeadlineExceeded;NotFound;AlreadyExists;PermissionDenied;ResourceExhausted;FailedPrecondition;Aborted;OutOfRange;Unimplemented;Internal;Unavailable;DataLoss;Unauthenticated
97+
type GRPCSuccessCode string
98+
99+
const (
100+
GRPCSuccessCodeOk GRPCSuccessCode = "Ok"
101+
GRPCSuccessCodeCancelled GRPCSuccessCode = "Cancelled"
102+
GRPCSuccessCodeUnknown GRPCSuccessCode = "Unknown"
103+
GRPCSuccessCodeInvalidArgument GRPCSuccessCode = "InvalidArgument"
104+
GRPCSuccessCodeDeadlineExceeded GRPCSuccessCode = "DeadlineExceeded"
105+
GRPCSuccessCodeNotFound GRPCSuccessCode = "NotFound"
106+
GRPCSuccessCodeAlreadyExists GRPCSuccessCode = "AlreadyExists"
107+
GRPCSuccessCodePermissionDenied GRPCSuccessCode = "PermissionDenied"
108+
GRPCSuccessCodeResourceExhausted GRPCSuccessCode = "ResourceExhausted"
109+
GRPCSuccessCodeFailedPrecondition GRPCSuccessCode = "FailedPrecondition"
110+
GRPCSuccessCodeAborted GRPCSuccessCode = "Aborted"
111+
GRPCSuccessCodeOutOfRange GRPCSuccessCode = "OutOfRange"
112+
GRPCSuccessCodeUnimplemented GRPCSuccessCode = "Unimplemented"
113+
GRPCSuccessCodeInternal GRPCSuccessCode = "Internal"
114+
GRPCSuccessCodeUnavailable GRPCSuccessCode = "Unavailable"
115+
GRPCSuccessCodeDataLoss GRPCSuccessCode = "DataLoss"
116+
GRPCSuccessCodeUnauthenticated GRPCSuccessCode = "Unauthenticated"
117+
)
118+
119+
// GRPCSuccessCriteria defines success criteria for gRPC requests.
120+
type GRPCSuccessCriteria struct {
121+
// StatusCodes defines gRPC status codes that are considered successful.
122+
// Status codes are defined in https://github.com/grpc/grpc/blob/master/doc/statuscodes.md#status-codes-and-their-use-in-grpc.
123+
//
124+
// +optional
125+
StatusCodes []GRPCSuccessCode `json:"statusCodes,omitempty"`
126+
}

api/v1alpha1/backendtrafficpolicy_types.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ type BackendTrafficPolicy struct {
4545
// +kubebuilder:validation:XValidation:rule="has(self.targetRefs) ? self.targetRefs.all(ref, ref.kind in ['Gateway', 'HTTPRoute', 'GRPCRoute', 'UDPRoute', 'TCPRoute', 'TLSRoute']) : true ", message="this policy can only have a targetRefs[*].kind of Gateway/HTTPRoute/GRPCRoute/TCPRoute/UDPRoute/TLSRoute"
4646
// +kubebuilder:validation:XValidation:rule="!has(self.compression) || !has(self.compressor)", message="either compression or compressor can be set, not both"
4747
// +kubebuilder:validation:XValidation:rule="!has(self.requestBuffer) || !has(self.httpUpgrade) || self.httpUpgrade.size() == 0", message="requestBuffer cannot be used together with httpUpgrade"
48+
// +kubebuilder:validation:XValidation:rule="!has(self.admissionControl) || ((!has(self.targetRef) || self.targetRef.kind in ['Gateway', 'HTTPRoute', 'GRPCRoute']) && (!has(self.targetRefs) || self.targetRefs.all(ref, ref.kind in ['Gateway', 'HTTPRoute', 'GRPCRoute'])) && (!has(self.targetSelectors) || self.targetSelectors.all(sel, sel.kind in ['Gateway', 'HTTPRoute', 'GRPCRoute'])))", message="admissionControl can only be used with HTTPRoute, GRPCRoute, or Gateway targets"
4849
type BackendTrafficPolicySpec struct {
4950
PolicyTargetReferences `json:",inline"`
5051
ClusterSettings `json:",inline"`
@@ -74,6 +75,12 @@ type BackendTrafficPolicySpec struct {
7475
// +optional
7576
FaultInjection *FaultInjection `json:"faultInjection,omitempty"`
7677

78+
// AdmissionControl defines the admission control policy to be applied. This configuration
79+
// probabilistically rejects requests based on the success rate of previous requests in a
80+
// configurable sliding time window.
81+
// +optional
82+
AdmissionControl *AdmissionControl `json:"admissionControl,omitempty"`
83+
7784
// UseClientProtocol configures Envoy to prefer sending requests to backends using
7885
// the same HTTP protocol that the incoming request used. Defaults to false, which means
7986
// that Envoy will use the protocol indicated by the attached BackendRef.

api/v1alpha1/zz_generated.deepcopy.go

Lines changed: 115 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)