Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
971c3f1
Add support for ClientSideWeightedRoundRobin load balancer policy in …
Nov 2, 2025
a9d01f0
Adds / Updates test cases for client wrr
Nov 2, 2025
63e8b2f
Fix: gen-check ci, coverage-check
Nov 3, 2025
522534b
Remove `enableOOBLoadReport` and `oobReportingPeriod` fields from gat…
Nov 3, 2025
4512f9d
Remove `enableOOBLoadReport` and `oobReportingPeriod` fields from Cli…
Nov 3, 2025
dd5d285
Update: Change `ErrorUtilizationPenalty` type from float to integer a…
Nov 16, 2025
1101c1d
Merge branch 'main' into client-wrr
Nov 26, 2025
14d1d59
Merge branch 'main' into client-wrr
jukie Nov 27, 2025
8bce886
Update: Refactor `ErrorUtilizationPenalty` to use integer type with p…
Dec 7, 2025
0d65b01
Merge remote-tracking branch 'upstream/main' into client-wrr
Dec 7, 2025
a479e67
Refactor: Replace `ptr.To(metav1.Duration)` with `ir.MetaV1DurationPt…
Dec 7, 2025
777a1c1
Update: Add support for SlowStart configuration for ClientSideWeighte…
Dec 7, 2025
b88903c
Merge remote-tracking branch 'upstream/main' into client-wrr
Jan 20, 2026
234cffa
Update: Replace `ClientSideWeightedRoundRobin` load balancer type wit…
Jan 21, 2026
d012b11
Merge branch 'main' into client-wrr
Jan 21, 2026
44bfe7b
Update: Replace `ClientSideWeightedRoundRobin` references with `Backe…
Jan 21, 2026
7edc401
Merge branch 'main' into client-wrr
Jan 21, 2026
84a0942
Merge branch 'main' into client-wrr
Jan 21, 2026
afb690d
Update: Replace `lb-backend-bu` references with `lb-backend-utilizati…
Jan 21, 2026
3785264
Remove: Delete obsolete BackendUtilization OOB and penalty load balan…
Jan 21, 2026
6321ec4
Merge branch 'main' into client-wrr
jukie Jan 21, 2026
05016c4
Merge branch 'main' into client-wrr
Jan 28, 2026
7d7528f
Update: Add detailed documentation and configuration examples for Bac…
Jan 29, 2026
870c52c
Merge branch 'main' into client-wrr
Jan 29, 2026
1fa3ff3
Merge remote-tracking branch 'upstream/main' into client-wrr
Feb 1, 2026
c3e06cb
Update: Rename `ErrorUtilizationPenalty` to `ErrorUtilizationPenaltyP…
altaiezior Feb 2, 2026
9c9dc20
Update: Add support for `removeResponseHeaders` in `BackendUtilizatio…
altaiezior Feb 2, 2026
77a5c4b
Merge branch 'main' into client-wrr
altaiezior Feb 4, 2026
ac1d840
Update: Replace `removeResponseHeaders` with `keepResponseHeaders` ac…
altaiezior Feb 4, 2026
aa37fcb
Merge branch 'main' into client-wrr
arkodg Feb 8, 2026
53f1473
Refactor: Reorganize import order in `cluster_test.go` for consistency.
altaiezior Feb 9, 2026
b4f8e13
Merge remote-tracking branch 'upstream/main' into client-wrr
altaiezior Mar 20, 2026
abe5a04
Update: Fix formatting and alignment in `load_balancing.go` and `load…
altaiezior Mar 20, 2026
3b8a0d0
Update: Add validation to disallow ZoneAware routing for BackendUtili…
altaiezior Mar 20, 2026
e1bb5e6
Update: Add error handling for invalid duration values in `BackendUti…
altaiezior Mar 22, 2026
15b56ff
Refactor: Simplify nil check and assignment logic in `BackendUtilizat…
altaiezior Mar 22, 2026
0a1d0fe
Update: Add support for BackendUtilization load balancing policy in B…
altaiezior Mar 22, 2026
4ac8625
Merge remote-tracking branch 'upstream/main' into client-wrr-temp
altaiezior Mar 22, 2026
b570798
Merge branch 'main' into client-wrr
jukie Mar 23, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 53 additions & 4 deletions api/v1alpha1/loadbalancer_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,17 @@ import gwapiv1 "sigs.k8s.io/gateway-api/apis/v1"
// +union
//
// +kubebuilder:validation:XValidation:rule="self.type == 'ConsistentHash' ? has(self.consistentHash) : !has(self.consistentHash)",message="If LoadBalancer type is consistentHash, consistentHash field needs to be set."
// +kubebuilder:validation:XValidation:rule="self.type in ['Random', 'ConsistentHash'] ? !has(self.slowStart) : true ",message="Currently SlowStart is only supported for RoundRobin and LeastRequest load balancers."
// +kubebuilder:validation:XValidation:rule="self.type == 'ConsistentHash' ? !has(self.zoneAware) : true ",message="Currently ZoneAware is only supported for LeastRequest, Random, and RoundRobin load balancers."
// +kubebuilder:validation:XValidation:rule="self.type == 'ClientSideWeightedRoundRobin' ? has(self.clientSideWeightedRoundRobin) : !has(self.clientSideWeightedRoundRobin)",message="If LoadBalancer type is ClientSideWeightedRoundRobin, clientSideWeightedRoundRobin field needs to be set."
// +kubebuilder:validation:XValidation:rule="self.type in ['Random', 'ConsistentHash', 'ClientSideWeightedRoundRobin'] ? !has(self.slowStart) : true ",message="Currently SlowStart is only supported for RoundRobin and LeastRequest load balancers."
// +kubebuilder:validation:XValidation:rule="self.type in ['ConsistentHash', 'ClientSideWeightedRoundRobin'] ? !has(self.zoneAware) : true ",message="Currently ZoneAware is only supported for LeastRequest, Random, and RoundRobin load balancers."
type LoadBalancer struct {
// Type decides the type of Load Balancer policy.
// Valid LoadBalancerType values are
// "ConsistentHash",
// "LeastRequest",
// "Random",
// "RoundRobin".
// "RoundRobin",
// "ClientSideWeightedRoundRobin".
//
// +unionDiscriminator
Type LoadBalancerType `json:"type"`
Expand All @@ -29,6 +31,12 @@ type LoadBalancer struct {
// +optional
ConsistentHash *ConsistentHash `json:"consistentHash,omitempty"`

// ClientSideWeightedRoundRobin defines the configuration when the load balancer type is
// set to ClientSideWeightedRoundRobin.
//
// +optional
ClientSideWeightedRoundRobin *ClientSideWeightedRoundRobin `json:"clientSideWeightedRoundRobin,omitempty"`

// EndpointOverride defines the configuration for endpoint override.
// When specified, the load balancer will attempt to route requests to endpoints
// based on the override information extracted from request headers or metadata.
Expand All @@ -51,7 +59,7 @@ type LoadBalancer struct {
}

// LoadBalancerType specifies the types of LoadBalancer.
// +kubebuilder:validation:Enum=ConsistentHash;LeastRequest;Random;RoundRobin
// +kubebuilder:validation:Enum=ConsistentHash;LeastRequest;Random;RoundRobin;ClientSideWeightedRoundRobin
type LoadBalancerType string

const (
Expand All @@ -63,6 +71,8 @@ const (
RandomLoadBalancerType LoadBalancerType = "Random"
// RoundRobinLoadBalancerType load balancer policy.
RoundRobinLoadBalancerType LoadBalancerType = "RoundRobin"
// ClientSideWeightedRoundRobinLoadBalancerType load balancer policy.
ClientSideWeightedRoundRobinLoadBalancerType LoadBalancerType = "ClientSideWeightedRoundRobin"
)

// ConsistentHash defines the configuration related to the consistent hash
Expand Down Expand Up @@ -134,6 +144,45 @@ type Cookie struct {
Attributes map[string]string `json:"attributes,omitempty"`
}

// ClientSideWeightedRoundRobin defines configuration for Envoy's Client-Side Weighted Round Robin policy.
// See Envoy proto: envoy.extensions.load_balancing_policies.client_side_weighted_round_robin.v3.ClientSideWeightedRoundRobin
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tbh https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/load_balancing_policies/client_side_weighted_round_robin/v3/client_side_weighted_round_robin.proto is not descriptive enough, and doesnt mention how this needs to be instrumented in the upstream, are there other links than can be used

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah the docs aren't great... for example out-of-band reporting isn't supported at all yet reading the docs would indicate otherwise.

We could contribute some docs changes upstream but agreed that including a reference to how endpoint-load-metrics and endpoint-load-metrics-bin are instrumented would be useful here.

Copy link
Contributor Author

@altaiezior altaiezior Dec 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@arkodg what changes would you suggest me to add here?

This is a bit more elaborative document https://docs.cloud.google.com/load-balancing/docs/https/applb-custom-metrics although this can also be confusing and gcp specific.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do any docs exist that explain how a backend / server should be enhanced to send the appropriate trailors in the response ?
looking for a more end user facing doc for the feature ( which is described in https://www.youtube.com/watch?v=lfv_Oj1BLn0)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a google doc I will have to find it though but nothing stated officially as far I am aware of

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should consider adding one if it doesnt exist
cc @AndresGuedez

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ack, this is good feedback on the docs gaps.

I'll work with @efimki on this.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks @AndresGuedez ! Happy to be the beta tester

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is specific to google but some of their descriptions on ORCA/custom metrics may be helpful for the EG API fields - https://docs.cloud.google.com/load-balancing/docs/https/applb-custom-metrics#configure-custom-metrics

That's not an explicit ask to make changes but give this a read.

// Note: SlowStart is not supported for this policy in Envoy Gateway at this time.
type ClientSideWeightedRoundRobin struct {
// A given endpoint must report load metrics continuously for at least this long before the endpoint weight will be used.
// Default is 10s.
// +optional
BlackoutPeriod *gwapiv1.Duration `json:"blackoutPeriod,omitempty"`

// If a given endpoint has not reported load metrics in this long, stop using the reported weight. Defaults to 3m.
// +optional
WeightExpirationPeriod *gwapiv1.Duration `json:"weightExpirationPeriod,omitempty"`

// How often endpoint weights are recalculated. Values less than 100ms are capped at 100ms. Default 1s.
// +optional
WeightUpdatePeriod *gwapiv1.Duration `json:"weightUpdatePeriod,omitempty"`

// ErrorUtilizationPenalty adjusts endpoint weights based on the error rate (eps/qps).
// This is expressed as a percentage-based integer where 100 represents 1.0, 150 represents 1.5, etc.
//
// For example:
// - 100 => 1.0x
// - 120 => 1.2x
// - 200 => 2.0x
//
// Note: In the internal IR/XDS configuration this value is converted back to a
// floating point multiplier (value / 100.0).
//
// Must be non-negative.
// +kubebuilder:validation:Minimum=0
// +optional
ErrorUtilizationPenalty *uint32 `json:"errorUtilizationPenalty,omitempty"`

// Metric names used to compute utilization if application_utilization is not set.
// For map fields in ORCA proto, use the form "<map_field>.<key>", e.g., "named_metrics.foo".
// +optional
MetricNamesForComputingUtilization []string `json:"metricNamesForComputingUtilization,omitempty"`
}

// ConsistentHashType defines the type of input to hash on.
// +kubebuilder:validation:Enum=SourceIP;Header;Headers;Cookie
type ConsistentHashType string
Expand Down
45 changes: 45 additions & 0 deletions api/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -678,6 +678,53 @@ spec:
LoadBalancer policy to apply when routing traffic from the gateway to
the backend endpoints. Defaults to `LeastRequest`.
properties:
clientSideWeightedRoundRobin:
description: |-
ClientSideWeightedRoundRobin defines the configuration when the load balancer type is
set to ClientSideWeightedRoundRobin.
properties:
blackoutPeriod:
description: |-
A given endpoint must report load metrics continuously for at least this long before the endpoint weight will be used.
Default is 10s.
pattern: ^([0-9]{1,5}(h|m|s|ms)){1,4}$
type: string
errorUtilizationPenalty:
description: |-
ErrorUtilizationPenalty adjusts endpoint weights based on the error rate (eps/qps).
This is expressed as a percentage-based integer where 100 represents 1.0, 150 represents 1.5, etc.

For example:
- 100 => 1.0x
- 120 => 1.2x
- 200 => 2.0x

Note: In the internal IR/XDS configuration this value is converted back to a
floating point multiplier (value / 100.0).

Must be non-negative.
format: int32
minimum: 0
type: integer
metricNamesForComputingUtilization:
description: |-
Metric names used to compute utilization if application_utilization is not set.
For map fields in ORCA proto, use the form "<map_field>.<key>", e.g., "named_metrics.foo".
items:
type: string
type: array
weightExpirationPeriod:
description: If a given endpoint has not reported load metrics
in this long, stop using the reported weight. Defaults to
3m.
pattern: ^([0-9]{1,5}(h|m|s|ms)){1,4}$
type: string
weightUpdatePeriod:
description: How often endpoint weights are recalculated.
Values less than 100ms are capped at 100ms. Default 1s.
pattern: ^([0-9]{1,5}(h|m|s|ms)){1,4}$
type: string
type: object
consistentHash:
description: |-
ConsistentHash defines the configuration when the load balancer type is
Expand Down Expand Up @@ -823,12 +870,14 @@ spec:
"ConsistentHash",
"LeastRequest",
"Random",
"RoundRobin".
"RoundRobin",
"ClientSideWeightedRoundRobin".
enum:
- ConsistentHash
- LeastRequest
- Random
- RoundRobin
- ClientSideWeightedRoundRobin
type: string
zoneAware:
description: ZoneAware defines the configuration related to the
Expand Down Expand Up @@ -874,14 +923,18 @@ spec:
field needs to be set.
rule: 'self.type == ''ConsistentHash'' ? has(self.consistentHash)
: !has(self.consistentHash)'
- message: If LoadBalancer type is ClientSideWeightedRoundRobin, clientSideWeightedRoundRobin
field needs to be set.
rule: 'self.type == ''ClientSideWeightedRoundRobin'' ? has(self.clientSideWeightedRoundRobin)
: !has(self.clientSideWeightedRoundRobin)'
- message: Currently SlowStart is only supported for RoundRobin and
LeastRequest load balancers.
rule: 'self.type in [''Random'', ''ConsistentHash''] ? !has(self.slowStart)
: true '
rule: 'self.type in [''Random'', ''ConsistentHash'', ''ClientSideWeightedRoundRobin'']
? !has(self.slowStart) : true '
- message: Currently ZoneAware is only supported for LeastRequest,
Random, and RoundRobin load balancers.
rule: 'self.type == ''ConsistentHash'' ? !has(self.zoneAware) :
true '
rule: 'self.type in [''ConsistentHash'', ''ClientSideWeightedRoundRobin'']
? !has(self.zoneAware) : true '
mergeType:
description: |-
MergeType determines how this configuration is merged with existing BackendTrafficPolicy
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -736,6 +736,54 @@ spec:
LoadBalancer policy to apply when routing traffic from the gateway to
the backend endpoints. Defaults to `LeastRequest`.
properties:
clientSideWeightedRoundRobin:
description: |-
ClientSideWeightedRoundRobin defines the configuration when the load balancer type is
set to ClientSideWeightedRoundRobin.
properties:
blackoutPeriod:
description: |-
A given endpoint must report load metrics continuously for at least this long before the endpoint weight will be used.
Default is 10s.
pattern: ^([0-9]{1,5}(h|m|s|ms)){1,4}$
type: string
errorUtilizationPenalty:
description: |-
ErrorUtilizationPenalty adjusts endpoint weights based on the error rate (eps/qps).
This is expressed as a percentage-based integer where 100 represents 1.0, 150 represents 1.5, etc.

For example:
- 100 => 1.0x
- 120 => 1.2x
- 200 => 2.0x

Note: In the internal IR/XDS configuration this value is converted back to a
floating point multiplier (value / 100.0).

Must be non-negative.
format: int32
minimum: 0
type: integer
metricNamesForComputingUtilization:
description: |-
Metric names used to compute utilization if application_utilization is not set.
For map fields in ORCA proto, use the form "<map_field>.<key>", e.g., "named_metrics.foo".
items:
type: string
type: array
weightExpirationPeriod:
description: If a given endpoint has not reported
load metrics in this long, stop using the reported
weight. Defaults to 3m.
pattern: ^([0-9]{1,5}(h|m|s|ms)){1,4}$
type: string
weightUpdatePeriod:
description: How often endpoint weights are recalculated.
Values less than 100ms are capped at 100ms. Default
1s.
pattern: ^([0-9]{1,5}(h|m|s|ms)){1,4}$
type: string
type: object
consistentHash:
description: |-
ConsistentHash defines the configuration when the load balancer type is
Expand Down Expand Up @@ -886,12 +934,14 @@ spec:
"ConsistentHash",
"LeastRequest",
"Random",
"RoundRobin".
"RoundRobin",
"ClientSideWeightedRoundRobin".
enum:
- ConsistentHash
- LeastRequest
- Random
- RoundRobin
- ClientSideWeightedRoundRobin
type: string
zoneAware:
description: ZoneAware defines the configuration related
Expand Down Expand Up @@ -939,14 +989,18 @@ spec:
field needs to be set.
rule: 'self.type == ''ConsistentHash'' ? has(self.consistentHash)
: !has(self.consistentHash)'
- message: If LoadBalancer type is ClientSideWeightedRoundRobin,
clientSideWeightedRoundRobin field needs to be set.
rule: 'self.type == ''ClientSideWeightedRoundRobin'' ?
has(self.clientSideWeightedRoundRobin) : !has(self.clientSideWeightedRoundRobin)'
- message: Currently SlowStart is only supported for RoundRobin
and LeastRequest load balancers.
rule: 'self.type in [''Random'', ''ConsistentHash''] ?
!has(self.slowStart) : true '
rule: 'self.type in [''Random'', ''ConsistentHash'', ''ClientSideWeightedRoundRobin'']
? !has(self.slowStart) : true '
- message: Currently ZoneAware is only supported for LeastRequest,
Random, and RoundRobin load balancers.
rule: 'self.type == ''ConsistentHash'' ? !has(self.zoneAware)
: true '
rule: 'self.type in [''ConsistentHash'', ''ClientSideWeightedRoundRobin'']
? !has(self.zoneAware) : true '
proxyProtocol:
description: ProxyProtocol enables the Proxy Protocol when
communicating with the backend.
Expand Down
Loading
Loading