GEP-3171: Percentage-based Request Mirroring¶
- Issue: #3171
- Status: Experimental
(See status definitions here.)
TLDR¶
Enhance the existing Request Mirroring feature by allowing users to specify a percentage of requests they'd like mirrored.
Goals¶
Successfully implement the feature.
Introduction¶
Request Mirroring is a feature that allows a user to mirror requests going to some backend A along to some other specified backend B. Right now Request Mirroring is an all or nothing feature – either 100% of request are mirrored, or 0% are. Percentage-based Request Mirroring will allow users to specify a percentage of requests they'd like mirrored as opposed to every single request.
This feature is already supported by Envoy, so adding it for the Gateway API would enable better integration between the two products. There's also an existing user desire for this feature on the HAProxy side and NGINX side. Since Request Mirroring is already supported by the Gateway API, Percentage-based Request Mirroring would a clear improvement on this pre-existing feature.
Existing Support in Implementations¶
Implementation | Support |
---|---|
Envoy | config.route.v3.RouteAction.RequestMirrorPolicy |
HAProxy | HAProxy SPOP |
NGINX | ngx_http_mirror_module |
gCloud | RequestMirrorPolicy |
API¶
This GEP proposes the following API changes:
- Add utility type
Fraction
to v1/shared_types.go:
type Fraction struct {
// +optional
// +kubebuilder:default=100
// +kubebuilder:validation:Minimum=0
Numerator int32 `json:"numerator"`
// +optional
// +kubebuilder:default=100
// +kubebuilder:validation:Minimum=1
Denominator int32 `json:"denominator"`
}
- Update the
HTTPRequestMirrorFilter
struct to include aPercent
field of typeint32
, and aFraction
field of typeFraction
:
// HTTPRequestMirrorFilter defines configuration for the RequestMirror filter.
type HTTPRequestMirrorFilter struct {
// BackendRef references a resource where mirrored requests are sent.
//
// Mirrored requests must be sent only to a single destination endpoint
// within this BackendRef, irrespective of how many endpoints are present
// within this BackendRef.
//
// If the referent cannot be found, this BackendRef is invalid and must be
// dropped from the Gateway. The controller must ensure the "ResolvedRefs"
// condition on the Route status is set to `status: False` and not configure
// this backend in the underlying implementation.
//
// If there is a cross-namespace reference to an *existing* object
// that is not allowed by a ReferenceGrant, the controller must ensure the
// "ResolvedRefs" condition on the Route is set to `status: False`,
// with the "RefNotPermitted" reason and not configure this backend in the
// underlying implementation.
//
// In either error case, the Message of the `ResolvedRefs` Condition
// should be used to provide more detail about the problem.
//
// Support: Extended for Kubernetes Service
//
// Support: Implementation-specific for any other resource
BackendRef BackendObjectReference `json:"backendRef"`
// Percent represents the percentage of requests that should be
// mirrored to BackendRef. Its minimum value is 0 (indicating 0% of
// requests) and its maximum value is 100 (indicating 100% of requests).
//
// If both Percent and Fraction are specified, Fraction will take
// priority. If Percent is unspecified, it will have a default value of
// 100. If Fraction is unspecified, it will have a default value of
// 100/100. This means that if neither field is specified, 100% of
// requests will be mirrored.
//
// +optional
// +kubebuilder:default=100
// +kubebuilder:validation:Minimum=0
// +kubebuilder:validation:Maximum=100
Percent int32 `json:"percent,omitempty"`
// Fraction represents the fraction of requests that should be
// mirrored to BackendRef.
//
// If both Percent and Fraction are specified, Fraction will take
// priority. If Percent is unspecified, it will have a default value of
// 100. If Fraction is unspecified, it will have a default value of
// 100/100. This means that if neither field is specified, 100% of
// requests will be mirrored.
//
// +optional
Fraction Fraction `json:"fraction,omitempty"`
}
Example¶
An example with Percent:
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: http-filter-mirror
labels:
gateway: mirror-gateway
spec:
parentRefs:
- name: mirror-gateway
hostnames:
- mirror.example
rules:
- backendRefs:
- name: foo-v1
port: 8080
filters:
- type: RequestMirror
requestMirror:
backendRef:
name: foo-v2
port: 8080
percent: 42
foo-v1
to be mirrored to foo-v2
.
An example with Fraction:
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: http-filter-mirror
labels:
gateway: mirror-gateway
spec:
parentRefs:
- name: mirror-gateway
hostnames:
- mirror.example
rules:
- backendRefs:
- name: foo-v1
port: 8080
filters:
- type: RequestMirror
requestMirror:
backendRef:
name: foo-v2
port: 8080
fraction:
numerator: 5
denominator: 1000
foo-v1
to be mirrored to foo-v2
.