Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding GEP 3171: Percentage-based Request Mirroring #3178

Merged
merged 12 commits into from
Jul 29, 2024
174 changes: 174 additions & 0 deletions geps/gep-3171/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
# GEP-3171: Percentage-based Request Mirroring

* Issue: [#3171](https://github.com/kubernetes-sigs/gateway-api/issues/3171)
* Status: **Provisional**
jakebennert marked this conversation as resolved.
Show resolved Hide resolved

(See status definitions [here](/geps/overview/#gep-states).)

## TLDR

Enhance the existing [Request Mirroring](https://gateway-api.sigs.k8s.io/guides/http-request-mirroring/) feature by allowing users to specify a percentage of requests they'd like mirrored.

## Goals

Successfully implement the feature.

## Introduction

[Request Mirroring](https://gateway-api.sigs.k8s.io/guides/http-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](https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/route/v3/route_components.proto#envoy-v3-api-msg-config-route-v3-routeaction-requestmirrorpolicy), 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](https://www.haproxy.com/blog/haproxy-traffic-mirroring-for-real-world-testing) and [NGINX side](https://alex.dzyoba.com/blog/nginx-mirror/). Since Request Mirroring is already supported by the Gateway API, Percentage-based Request Mirroring would a clear improvement on this pre-existing feature.

jakebennert marked this conversation as resolved.
Show resolved Hide resolved
## Existing Support in Implementations

| Implementation | Support |
|----------------|------------|
| Envoy | [config.route.v3.RouteAction.RequestMirrorPolicy](config.route.v3.RouteAction.RequestMirrorPolicy) |
| HAProxy | [HAProxy SPOP](https://github.com/haproxytech/spoa-mirror) |
| NGINX | [ngx_http_mirror_module](https://nginx.org/en/docs/http/ngx_http_mirror_module.html) |
| gCloud | [RequestMirrorPolicy](https://cloud.google.com/python/docs/reference/compute/latest/google.cloud.compute_v1.types.RequestMirrorPolicy) |

## API

This GEP proposes the following API changes:

* Add utility type `Fraction` to [v1/shared_types.go](https://github.com/kubernetes-sigs/gateway-api/blob/cb5bf1541fa70f0692aebde8c64bba434cf331b6/apis/v1/shared_types.go):


```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 a `Percent` field of type `int32`, and a `Fraction` field of type `Fraction`:


```go
// 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"`
}
```
robscott marked this conversation as resolved.
Show resolved Hide resolved

## 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
```
This would result in 42% of requests going to `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
```
This would result in 0.5% of requests going to `foo-v1` to be mirrored to `foo-v2`.
11 changes: 11 additions & 0 deletions geps/gep-3171/metadata.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
apiVersion: internal.gateway.networking.k8s.io/v1alpha2
kind: GEPDetails
number: 3171
name: Percentage-based Request Mirroring
status: Provisional
authors:
- jakebennert
references:
- https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io%2fv1.HTTPRequestMirrorFilter
featureNames:
- Percentage-based Request Mirroring