diff --git a/api/v1alpha1/loadbalancer_types.go b/api/v1alpha1/loadbalancer_types.go index 8e0dab5086..728a4c8f07 100644 --- a/api/v1alpha1/loadbalancer_types.go +++ b/api/v1alpha1/loadbalancer_types.go @@ -12,7 +12,8 @@ import gwapiv1 "sigs.k8s.io/gateway-api/apis/v1" // // +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 == 'ConsistentHash' && has(self.zoneAware) ? !has(self.zoneAware.preferLocal) : true",message="PreferLocal zone-aware routing is not supported for ConsistentHash load balancers. Use weightedZones instead." +// +kubebuilder:validation:XValidation:rule="has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) && has(self.zoneAware.weightedZones)) : true",message="ZoneAware PreferLocal and WeightedZones cannot be specified together." type LoadBalancer struct { // Type decides the type of Load Balancer policy. // Valid LoadBalancerType values are @@ -184,6 +185,14 @@ type ZoneAware struct { // // +optional PreferLocal *PreferLocalZone `json:"preferLocal,omitempty"` + + // WeightedZones configures weight-based traffic distribution across locality zones. + // Traffic is distributed proportionally based on the sum of all zone weights. + // + // +optional + // +listType=map + // +listMapKey=zone + WeightedZones []WeightedZoneConfig `json:"weightedZones,omitempty"` } // PreferLocalZone configures zone-aware routing to prefer sending traffic to the local locality zone. @@ -217,6 +226,20 @@ type ForceLocalZone struct { MinEndpointsInZoneThreshold *uint32 `json:"minEndpointsInZoneThreshold,omitempty"` } +// WeightedZoneConfig defines the weight for a specific locality zone. +type WeightedZoneConfig struct { + // Zone specifies the topology zone this weight applies to. + // The value should match the topology.kubernetes.io/zone label + // of the nodes where endpoints are running. + // Zones not listed in the configuration receive a default weight of 1. + Zone string `json:"zone"` + + // Weight defines the weight for this locality. + // Higher values receive more traffic. The actual traffic distribution + // is proportional to this value relative to other localities. + Weight uint32 `json:"weight"` +} + // EndpointOverride defines the configuration for endpoint override. // This allows endpoint picking to be implemented based on request headers or metadata. // It extracts selected override endpoints from the specified sources (request headers, metadata, etc.). diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index 8577b27ce1..3a5ce771a3 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -7705,6 +7705,21 @@ func (in *WasmEnv) DeepCopy() *WasmEnv { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *WeightedZoneConfig) DeepCopyInto(out *WeightedZoneConfig) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WeightedZoneConfig. +func (in *WeightedZoneConfig) DeepCopy() *WeightedZoneConfig { + if in == nil { + return nil + } + out := new(WeightedZoneConfig) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *XDSServer) DeepCopyInto(out *XDSServer) { *out = *in @@ -7843,6 +7858,11 @@ func (in *ZoneAware) DeepCopyInto(out *ZoneAware) { *out = new(PreferLocalZone) (*in).DeepCopyInto(*out) } + if in.WeightedZones != nil { + in, out := &in.WeightedZones, &out.WeightedZones + *out = make([]WeightedZoneConfig, len(*in)) + copy(*out, *in) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ZoneAware. diff --git a/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml b/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml index b1faba9c9a..56c666f9e8 100644 --- a/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml +++ b/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml @@ -931,6 +931,36 @@ spec: minimum: 0 type: integer type: object + weightedZones: + description: |- + WeightedZones configures weight-based traffic distribution across locality zones. + Traffic is distributed proportionally based on the sum of all zone weights. + items: + description: WeightedZoneConfig defines the weight for a + specific locality zone. + properties: + weight: + description: |- + Weight defines the weight for this locality. + Higher values receive more traffic. The actual traffic distribution + is proportional to this value relative to other localities. + format: int32 + type: integer + zone: + description: |- + Zone specifies the topology zone this weight applies to. + The value should match the topology.kubernetes.io/zone label + of the nodes where endpoints are running. + Zones not listed in the configuration receive a default weight of 1. + type: string + required: + - weight + - zone + type: object + type: array + x-kubernetes-list-map-keys: + - zone + x-kubernetes-list-type: map type: object required: - type @@ -944,10 +974,14 @@ spec: LeastRequest load balancers. rule: 'self.type in [''Random'', ''ConsistentHash''] ? !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 ' + - message: PreferLocal zone-aware routing is not supported for ConsistentHash + load balancers. Use weightedZones instead. + rule: 'self.type == ''ConsistentHash'' && has(self.zoneAware) ? + !has(self.zoneAware.preferLocal) : true' + - message: ZoneAware PreferLocal and WeightedZones cannot be specified + together. + rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) && + has(self.zoneAware.weightedZones)) : true' mergeType: description: |- MergeType determines how this configuration is merged with existing BackendTrafficPolicy diff --git a/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml b/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml index 996d26a91c..da2d4e856a 100644 --- a/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml +++ b/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml @@ -969,6 +969,36 @@ spec: minimum: 0 type: integer type: object + weightedZones: + description: |- + WeightedZones configures weight-based traffic distribution across locality zones. + Traffic is distributed proportionally based on the sum of all zone weights. + items: + description: WeightedZoneConfig defines the weight + for a specific locality zone. + properties: + weight: + description: |- + Weight defines the weight for this locality. + Higher values receive more traffic. The actual traffic distribution + is proportional to this value relative to other localities. + format: int32 + type: integer + zone: + description: |- + Zone specifies the topology zone this weight applies to. + The value should match the topology.kubernetes.io/zone label + of the nodes where endpoints are running. + Zones not listed in the configuration receive a default weight of 1. + type: string + required: + - weight + - zone + type: object + type: array + x-kubernetes-list-map-keys: + - zone + x-kubernetes-list-type: map type: object required: - type @@ -982,10 +1012,15 @@ spec: and LeastRequest load balancers. rule: 'self.type in [''Random'', ''ConsistentHash''] ? !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 ' + - message: PreferLocal zone-aware routing is not supported + for ConsistentHash load balancers. Use weightedZones + instead. + rule: 'self.type == ''ConsistentHash'' && has(self.zoneAware) + ? !has(self.zoneAware.preferLocal) : true' + - message: ZoneAware PreferLocal and WeightedZones cannot + be specified together. + rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) + && has(self.zoneAware.weightedZones)) : true' proxyProtocol: description: ProxyProtocol enables the Proxy Protocol when communicating with the backend. diff --git a/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_envoyproxies.yaml b/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_envoyproxies.yaml index 2931ebf19d..45aef65fee 100644 --- a/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_envoyproxies.yaml +++ b/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_envoyproxies.yaml @@ -12083,6 +12083,37 @@ spec: minimum: 0 type: integer type: object + weightedZones: + description: |- + WeightedZones configures weight-based traffic distribution across locality zones. + Traffic is distributed proportionally based on the sum of all zone weights. + items: + description: WeightedZoneConfig + defines the weight for a specific + locality zone. + properties: + weight: + description: |- + Weight defines the weight for this locality. + Higher values receive more traffic. The actual traffic distribution + is proportional to this value relative to other localities. + format: int32 + type: integer + zone: + description: |- + Zone specifies the topology zone this weight applies to. + The value should match the topology.kubernetes.io/zone label + of the nodes where endpoints are running. + Zones not listed in the configuration receive a default weight of 1. + type: string + required: + - weight + - zone + type: object + type: array + x-kubernetes-list-map-keys: + - zone + x-kubernetes-list-type: map type: object required: - type @@ -12097,11 +12128,18 @@ spec: load balancers. rule: 'self.type in [''Random'', ''ConsistentHash''] ? !has(self.slowStart) : true ' - - message: Currently ZoneAware is only - supported for LeastRequest, Random, - and RoundRobin load balancers. + - message: PreferLocal zone-aware routing + is not supported for ConsistentHash + load balancers. Use weightedZones + instead. rule: 'self.type == ''ConsistentHash'' - ? !has(self.zoneAware) : true ' + && has(self.zoneAware) ? !has(self.zoneAware.preferLocal) + : true' + - message: ZoneAware PreferLocal and WeightedZones + cannot be specified together. + rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) + && has(self.zoneAware.weightedZones)) + : true' proxyProtocol: description: ProxyProtocol enables the Proxy Protocol when communicating with @@ -13352,6 +13390,37 @@ spec: minimum: 0 type: integer type: object + weightedZones: + description: |- + WeightedZones configures weight-based traffic distribution across locality zones. + Traffic is distributed proportionally based on the sum of all zone weights. + items: + description: WeightedZoneConfig + defines the weight for a specific + locality zone. + properties: + weight: + description: |- + Weight defines the weight for this locality. + Higher values receive more traffic. The actual traffic distribution + is proportional to this value relative to other localities. + format: int32 + type: integer + zone: + description: |- + Zone specifies the topology zone this weight applies to. + The value should match the topology.kubernetes.io/zone label + of the nodes where endpoints are running. + Zones not listed in the configuration receive a default weight of 1. + type: string + required: + - weight + - zone + type: object + type: array + x-kubernetes-list-map-keys: + - zone + x-kubernetes-list-type: map type: object required: - type @@ -13366,11 +13435,18 @@ spec: load balancers. rule: 'self.type in [''Random'', ''ConsistentHash''] ? !has(self.slowStart) : true ' - - message: Currently ZoneAware is only - supported for LeastRequest, Random, - and RoundRobin load balancers. + - message: PreferLocal zone-aware routing + is not supported for ConsistentHash + load balancers. Use weightedZones + instead. rule: 'self.type == ''ConsistentHash'' - ? !has(self.zoneAware) : true ' + && has(self.zoneAware) ? !has(self.zoneAware.preferLocal) + : true' + - message: ZoneAware PreferLocal and WeightedZones + cannot be specified together. + rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) + && has(self.zoneAware.weightedZones)) + : true' proxyProtocol: description: ProxyProtocol enables the Proxy Protocol when communicating with @@ -14769,6 +14845,37 @@ spec: minimum: 0 type: integer type: object + weightedZones: + description: |- + WeightedZones configures weight-based traffic distribution across locality zones. + Traffic is distributed proportionally based on the sum of all zone weights. + items: + description: WeightedZoneConfig defines + the weight for a specific locality + zone. + properties: + weight: + description: |- + Weight defines the weight for this locality. + Higher values receive more traffic. The actual traffic distribution + is proportional to this value relative to other localities. + format: int32 + type: integer + zone: + description: |- + Zone specifies the topology zone this weight applies to. + The value should match the topology.kubernetes.io/zone label + of the nodes where endpoints are running. + Zones not listed in the configuration receive a default weight of 1. + type: string + required: + - weight + - zone + type: object + type: array + x-kubernetes-list-map-keys: + - zone + x-kubernetes-list-type: map type: object required: - type @@ -14782,11 +14889,17 @@ spec: for RoundRobin and LeastRequest load balancers. rule: 'self.type in [''Random'', ''ConsistentHash''] ? !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 ' + - message: PreferLocal zone-aware routing is + not supported for ConsistentHash load balancers. + Use weightedZones instead. + rule: 'self.type == ''ConsistentHash'' && + has(self.zoneAware) ? !has(self.zoneAware.preferLocal) + : true' + - message: ZoneAware PreferLocal and WeightedZones + cannot be specified together. + rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) + && has(self.zoneAware.weightedZones)) : + true' proxyProtocol: description: ProxyProtocol enables the Proxy Protocol when communicating with the backend. @@ -16106,6 +16219,36 @@ spec: minimum: 0 type: integer type: object + weightedZones: + description: |- + WeightedZones configures weight-based traffic distribution across locality zones. + Traffic is distributed proportionally based on the sum of all zone weights. + items: + description: WeightedZoneConfig defines + the weight for a specific locality zone. + properties: + weight: + description: |- + Weight defines the weight for this locality. + Higher values receive more traffic. The actual traffic distribution + is proportional to this value relative to other localities. + format: int32 + type: integer + zone: + description: |- + Zone specifies the topology zone this weight applies to. + The value should match the topology.kubernetes.io/zone label + of the nodes where endpoints are running. + Zones not listed in the configuration receive a default weight of 1. + type: string + required: + - weight + - zone + type: object + type: array + x-kubernetes-list-map-keys: + - zone + x-kubernetes-list-type: map type: object required: - type @@ -16119,10 +16262,15 @@ spec: RoundRobin and LeastRequest load balancers. rule: 'self.type in [''Random'', ''ConsistentHash''] ? !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 ' + - message: PreferLocal zone-aware routing is not supported + for ConsistentHash load balancers. Use weightedZones + instead. + rule: 'self.type == ''ConsistentHash'' && has(self.zoneAware) + ? !has(self.zoneAware.preferLocal) : true' + - message: ZoneAware PreferLocal and WeightedZones + cannot be specified together. + rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) + && has(self.zoneAware.weightedZones)) : true' proxyProtocol: description: ProxyProtocol enables the Proxy Protocol when communicating with the backend. diff --git a/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_securitypolicies.yaml b/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_securitypolicies.yaml index 3bfde648f7..fc4088dc2d 100644 --- a/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_securitypolicies.yaml +++ b/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_securitypolicies.yaml @@ -1593,6 +1593,36 @@ spec: minimum: 0 type: integer type: object + weightedZones: + description: |- + WeightedZones configures weight-based traffic distribution across locality zones. + Traffic is distributed proportionally based on the sum of all zone weights. + items: + description: WeightedZoneConfig defines the + weight for a specific locality zone. + properties: + weight: + description: |- + Weight defines the weight for this locality. + Higher values receive more traffic. The actual traffic distribution + is proportional to this value relative to other localities. + format: int32 + type: integer + zone: + description: |- + Zone specifies the topology zone this weight applies to. + The value should match the topology.kubernetes.io/zone label + of the nodes where endpoints are running. + Zones not listed in the configuration receive a default weight of 1. + type: string + required: + - weight + - zone + type: object + type: array + x-kubernetes-list-map-keys: + - zone + x-kubernetes-list-type: map type: object required: - type @@ -1606,10 +1636,15 @@ spec: and LeastRequest load balancers. rule: 'self.type in [''Random'', ''ConsistentHash''] ? !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 ' + - message: PreferLocal zone-aware routing is not supported + for ConsistentHash load balancers. Use weightedZones + instead. + rule: 'self.type == ''ConsistentHash'' && has(self.zoneAware) + ? !has(self.zoneAware.preferLocal) : true' + - message: ZoneAware PreferLocal and WeightedZones cannot + be specified together. + rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) + && has(self.zoneAware.weightedZones)) : true' proxyProtocol: description: ProxyProtocol enables the Proxy Protocol when communicating with the backend. @@ -2750,6 +2785,36 @@ spec: minimum: 0 type: integer type: object + weightedZones: + description: |- + WeightedZones configures weight-based traffic distribution across locality zones. + Traffic is distributed proportionally based on the sum of all zone weights. + items: + description: WeightedZoneConfig defines the + weight for a specific locality zone. + properties: + weight: + description: |- + Weight defines the weight for this locality. + Higher values receive more traffic. The actual traffic distribution + is proportional to this value relative to other localities. + format: int32 + type: integer + zone: + description: |- + Zone specifies the topology zone this weight applies to. + The value should match the topology.kubernetes.io/zone label + of the nodes where endpoints are running. + Zones not listed in the configuration receive a default weight of 1. + type: string + required: + - weight + - zone + type: object + type: array + x-kubernetes-list-map-keys: + - zone + x-kubernetes-list-type: map type: object required: - type @@ -2763,10 +2828,15 @@ spec: and LeastRequest load balancers. rule: 'self.type in [''Random'', ''ConsistentHash''] ? !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 ' + - message: PreferLocal zone-aware routing is not supported + for ConsistentHash load balancers. Use weightedZones + instead. + rule: 'self.type == ''ConsistentHash'' && has(self.zoneAware) + ? !has(self.zoneAware.preferLocal) : true' + - message: ZoneAware PreferLocal and WeightedZones cannot + be specified together. + rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) + && has(self.zoneAware.weightedZones)) : true' proxyProtocol: description: ProxyProtocol enables the Proxy Protocol when communicating with the backend. @@ -4122,6 +4192,36 @@ spec: minimum: 0 type: integer type: object + weightedZones: + description: |- + WeightedZones configures weight-based traffic distribution across locality zones. + Traffic is distributed proportionally based on the sum of all zone weights. + items: + description: WeightedZoneConfig defines + the weight for a specific locality zone. + properties: + weight: + description: |- + Weight defines the weight for this locality. + Higher values receive more traffic. The actual traffic distribution + is proportional to this value relative to other localities. + format: int32 + type: integer + zone: + description: |- + Zone specifies the topology zone this weight applies to. + The value should match the topology.kubernetes.io/zone label + of the nodes where endpoints are running. + Zones not listed in the configuration receive a default weight of 1. + type: string + required: + - weight + - zone + type: object + type: array + x-kubernetes-list-map-keys: + - zone + x-kubernetes-list-type: map type: object required: - type @@ -4135,11 +4235,15 @@ spec: for RoundRobin and LeastRequest load balancers. rule: 'self.type in [''Random'', ''ConsistentHash''] ? !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 ' + - message: PreferLocal zone-aware routing is not + supported for ConsistentHash load balancers. + Use weightedZones instead. + rule: 'self.type == ''ConsistentHash'' && has(self.zoneAware) + ? !has(self.zoneAware.preferLocal) : true' + - message: ZoneAware PreferLocal and WeightedZones + cannot be specified together. + rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) + && has(self.zoneAware.weightedZones)) : true' proxyProtocol: description: ProxyProtocol enables the Proxy Protocol when communicating with the backend. @@ -5544,6 +5648,36 @@ spec: minimum: 0 type: integer type: object + weightedZones: + description: |- + WeightedZones configures weight-based traffic distribution across locality zones. + Traffic is distributed proportionally based on the sum of all zone weights. + items: + description: WeightedZoneConfig defines the + weight for a specific locality zone. + properties: + weight: + description: |- + Weight defines the weight for this locality. + Higher values receive more traffic. The actual traffic distribution + is proportional to this value relative to other localities. + format: int32 + type: integer + zone: + description: |- + Zone specifies the topology zone this weight applies to. + The value should match the topology.kubernetes.io/zone label + of the nodes where endpoints are running. + Zones not listed in the configuration receive a default weight of 1. + type: string + required: + - weight + - zone + type: object + type: array + x-kubernetes-list-map-keys: + - zone + x-kubernetes-list-type: map type: object required: - type @@ -5557,10 +5691,15 @@ spec: and LeastRequest load balancers. rule: 'self.type in [''Random'', ''ConsistentHash''] ? !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 ' + - message: PreferLocal zone-aware routing is not supported + for ConsistentHash load balancers. Use weightedZones + instead. + rule: 'self.type == ''ConsistentHash'' && has(self.zoneAware) + ? !has(self.zoneAware.preferLocal) : true' + - message: ZoneAware PreferLocal and WeightedZones cannot + be specified together. + rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) + && has(self.zoneAware.weightedZones)) : true' proxyProtocol: description: ProxyProtocol enables the Proxy Protocol when communicating with the backend. diff --git a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml index d932b9e0ba..006f1c5a8b 100644 --- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml +++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml @@ -930,6 +930,36 @@ spec: minimum: 0 type: integer type: object + weightedZones: + description: |- + WeightedZones configures weight-based traffic distribution across locality zones. + Traffic is distributed proportionally based on the sum of all zone weights. + items: + description: WeightedZoneConfig defines the weight for a + specific locality zone. + properties: + weight: + description: |- + Weight defines the weight for this locality. + Higher values receive more traffic. The actual traffic distribution + is proportional to this value relative to other localities. + format: int32 + type: integer + zone: + description: |- + Zone specifies the topology zone this weight applies to. + The value should match the topology.kubernetes.io/zone label + of the nodes where endpoints are running. + Zones not listed in the configuration receive a default weight of 1. + type: string + required: + - weight + - zone + type: object + type: array + x-kubernetes-list-map-keys: + - zone + x-kubernetes-list-type: map type: object required: - type @@ -943,10 +973,14 @@ spec: LeastRequest load balancers. rule: 'self.type in [''Random'', ''ConsistentHash''] ? !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 ' + - message: PreferLocal zone-aware routing is not supported for ConsistentHash + load balancers. Use weightedZones instead. + rule: 'self.type == ''ConsistentHash'' && has(self.zoneAware) ? + !has(self.zoneAware.preferLocal) : true' + - message: ZoneAware PreferLocal and WeightedZones cannot be specified + together. + rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) && + has(self.zoneAware.weightedZones)) : true' mergeType: description: |- MergeType determines how this configuration is merged with existing BackendTrafficPolicy diff --git a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml index 97aeacf69e..b255bd38d9 100644 --- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml +++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml @@ -968,6 +968,36 @@ spec: minimum: 0 type: integer type: object + weightedZones: + description: |- + WeightedZones configures weight-based traffic distribution across locality zones. + Traffic is distributed proportionally based on the sum of all zone weights. + items: + description: WeightedZoneConfig defines the weight + for a specific locality zone. + properties: + weight: + description: |- + Weight defines the weight for this locality. + Higher values receive more traffic. The actual traffic distribution + is proportional to this value relative to other localities. + format: int32 + type: integer + zone: + description: |- + Zone specifies the topology zone this weight applies to. + The value should match the topology.kubernetes.io/zone label + of the nodes where endpoints are running. + Zones not listed in the configuration receive a default weight of 1. + type: string + required: + - weight + - zone + type: object + type: array + x-kubernetes-list-map-keys: + - zone + x-kubernetes-list-type: map type: object required: - type @@ -981,10 +1011,15 @@ spec: and LeastRequest load balancers. rule: 'self.type in [''Random'', ''ConsistentHash''] ? !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 ' + - message: PreferLocal zone-aware routing is not supported + for ConsistentHash load balancers. Use weightedZones + instead. + rule: 'self.type == ''ConsistentHash'' && has(self.zoneAware) + ? !has(self.zoneAware.preferLocal) : true' + - message: ZoneAware PreferLocal and WeightedZones cannot + be specified together. + rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) + && has(self.zoneAware.weightedZones)) : true' proxyProtocol: description: ProxyProtocol enables the Proxy Protocol when communicating with the backend. diff --git a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyproxies.yaml b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyproxies.yaml index a939a49317..73f0f74432 100644 --- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyproxies.yaml +++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyproxies.yaml @@ -12082,6 +12082,37 @@ spec: minimum: 0 type: integer type: object + weightedZones: + description: |- + WeightedZones configures weight-based traffic distribution across locality zones. + Traffic is distributed proportionally based on the sum of all zone weights. + items: + description: WeightedZoneConfig + defines the weight for a specific + locality zone. + properties: + weight: + description: |- + Weight defines the weight for this locality. + Higher values receive more traffic. The actual traffic distribution + is proportional to this value relative to other localities. + format: int32 + type: integer + zone: + description: |- + Zone specifies the topology zone this weight applies to. + The value should match the topology.kubernetes.io/zone label + of the nodes where endpoints are running. + Zones not listed in the configuration receive a default weight of 1. + type: string + required: + - weight + - zone + type: object + type: array + x-kubernetes-list-map-keys: + - zone + x-kubernetes-list-type: map type: object required: - type @@ -12096,11 +12127,18 @@ spec: load balancers. rule: 'self.type in [''Random'', ''ConsistentHash''] ? !has(self.slowStart) : true ' - - message: Currently ZoneAware is only - supported for LeastRequest, Random, - and RoundRobin load balancers. + - message: PreferLocal zone-aware routing + is not supported for ConsistentHash + load balancers. Use weightedZones + instead. rule: 'self.type == ''ConsistentHash'' - ? !has(self.zoneAware) : true ' + && has(self.zoneAware) ? !has(self.zoneAware.preferLocal) + : true' + - message: ZoneAware PreferLocal and WeightedZones + cannot be specified together. + rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) + && has(self.zoneAware.weightedZones)) + : true' proxyProtocol: description: ProxyProtocol enables the Proxy Protocol when communicating with @@ -13351,6 +13389,37 @@ spec: minimum: 0 type: integer type: object + weightedZones: + description: |- + WeightedZones configures weight-based traffic distribution across locality zones. + Traffic is distributed proportionally based on the sum of all zone weights. + items: + description: WeightedZoneConfig + defines the weight for a specific + locality zone. + properties: + weight: + description: |- + Weight defines the weight for this locality. + Higher values receive more traffic. The actual traffic distribution + is proportional to this value relative to other localities. + format: int32 + type: integer + zone: + description: |- + Zone specifies the topology zone this weight applies to. + The value should match the topology.kubernetes.io/zone label + of the nodes where endpoints are running. + Zones not listed in the configuration receive a default weight of 1. + type: string + required: + - weight + - zone + type: object + type: array + x-kubernetes-list-map-keys: + - zone + x-kubernetes-list-type: map type: object required: - type @@ -13365,11 +13434,18 @@ spec: load balancers. rule: 'self.type in [''Random'', ''ConsistentHash''] ? !has(self.slowStart) : true ' - - message: Currently ZoneAware is only - supported for LeastRequest, Random, - and RoundRobin load balancers. + - message: PreferLocal zone-aware routing + is not supported for ConsistentHash + load balancers. Use weightedZones + instead. rule: 'self.type == ''ConsistentHash'' - ? !has(self.zoneAware) : true ' + && has(self.zoneAware) ? !has(self.zoneAware.preferLocal) + : true' + - message: ZoneAware PreferLocal and WeightedZones + cannot be specified together. + rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) + && has(self.zoneAware.weightedZones)) + : true' proxyProtocol: description: ProxyProtocol enables the Proxy Protocol when communicating with @@ -14768,6 +14844,37 @@ spec: minimum: 0 type: integer type: object + weightedZones: + description: |- + WeightedZones configures weight-based traffic distribution across locality zones. + Traffic is distributed proportionally based on the sum of all zone weights. + items: + description: WeightedZoneConfig defines + the weight for a specific locality + zone. + properties: + weight: + description: |- + Weight defines the weight for this locality. + Higher values receive more traffic. The actual traffic distribution + is proportional to this value relative to other localities. + format: int32 + type: integer + zone: + description: |- + Zone specifies the topology zone this weight applies to. + The value should match the topology.kubernetes.io/zone label + of the nodes where endpoints are running. + Zones not listed in the configuration receive a default weight of 1. + type: string + required: + - weight + - zone + type: object + type: array + x-kubernetes-list-map-keys: + - zone + x-kubernetes-list-type: map type: object required: - type @@ -14781,11 +14888,17 @@ spec: for RoundRobin and LeastRequest load balancers. rule: 'self.type in [''Random'', ''ConsistentHash''] ? !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 ' + - message: PreferLocal zone-aware routing is + not supported for ConsistentHash load balancers. + Use weightedZones instead. + rule: 'self.type == ''ConsistentHash'' && + has(self.zoneAware) ? !has(self.zoneAware.preferLocal) + : true' + - message: ZoneAware PreferLocal and WeightedZones + cannot be specified together. + rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) + && has(self.zoneAware.weightedZones)) : + true' proxyProtocol: description: ProxyProtocol enables the Proxy Protocol when communicating with the backend. @@ -16105,6 +16218,36 @@ spec: minimum: 0 type: integer type: object + weightedZones: + description: |- + WeightedZones configures weight-based traffic distribution across locality zones. + Traffic is distributed proportionally based on the sum of all zone weights. + items: + description: WeightedZoneConfig defines + the weight for a specific locality zone. + properties: + weight: + description: |- + Weight defines the weight for this locality. + Higher values receive more traffic. The actual traffic distribution + is proportional to this value relative to other localities. + format: int32 + type: integer + zone: + description: |- + Zone specifies the topology zone this weight applies to. + The value should match the topology.kubernetes.io/zone label + of the nodes where endpoints are running. + Zones not listed in the configuration receive a default weight of 1. + type: string + required: + - weight + - zone + type: object + type: array + x-kubernetes-list-map-keys: + - zone + x-kubernetes-list-type: map type: object required: - type @@ -16118,10 +16261,15 @@ spec: RoundRobin and LeastRequest load balancers. rule: 'self.type in [''Random'', ''ConsistentHash''] ? !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 ' + - message: PreferLocal zone-aware routing is not supported + for ConsistentHash load balancers. Use weightedZones + instead. + rule: 'self.type == ''ConsistentHash'' && has(self.zoneAware) + ? !has(self.zoneAware.preferLocal) : true' + - message: ZoneAware PreferLocal and WeightedZones + cannot be specified together. + rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) + && has(self.zoneAware.weightedZones)) : true' proxyProtocol: description: ProxyProtocol enables the Proxy Protocol when communicating with the backend. diff --git a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_securitypolicies.yaml b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_securitypolicies.yaml index 8303f1b640..6e82fdf6d6 100644 --- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_securitypolicies.yaml +++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_securitypolicies.yaml @@ -1592,6 +1592,36 @@ spec: minimum: 0 type: integer type: object + weightedZones: + description: |- + WeightedZones configures weight-based traffic distribution across locality zones. + Traffic is distributed proportionally based on the sum of all zone weights. + items: + description: WeightedZoneConfig defines the + weight for a specific locality zone. + properties: + weight: + description: |- + Weight defines the weight for this locality. + Higher values receive more traffic. The actual traffic distribution + is proportional to this value relative to other localities. + format: int32 + type: integer + zone: + description: |- + Zone specifies the topology zone this weight applies to. + The value should match the topology.kubernetes.io/zone label + of the nodes where endpoints are running. + Zones not listed in the configuration receive a default weight of 1. + type: string + required: + - weight + - zone + type: object + type: array + x-kubernetes-list-map-keys: + - zone + x-kubernetes-list-type: map type: object required: - type @@ -1605,10 +1635,15 @@ spec: and LeastRequest load balancers. rule: 'self.type in [''Random'', ''ConsistentHash''] ? !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 ' + - message: PreferLocal zone-aware routing is not supported + for ConsistentHash load balancers. Use weightedZones + instead. + rule: 'self.type == ''ConsistentHash'' && has(self.zoneAware) + ? !has(self.zoneAware.preferLocal) : true' + - message: ZoneAware PreferLocal and WeightedZones cannot + be specified together. + rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) + && has(self.zoneAware.weightedZones)) : true' proxyProtocol: description: ProxyProtocol enables the Proxy Protocol when communicating with the backend. @@ -2749,6 +2784,36 @@ spec: minimum: 0 type: integer type: object + weightedZones: + description: |- + WeightedZones configures weight-based traffic distribution across locality zones. + Traffic is distributed proportionally based on the sum of all zone weights. + items: + description: WeightedZoneConfig defines the + weight for a specific locality zone. + properties: + weight: + description: |- + Weight defines the weight for this locality. + Higher values receive more traffic. The actual traffic distribution + is proportional to this value relative to other localities. + format: int32 + type: integer + zone: + description: |- + Zone specifies the topology zone this weight applies to. + The value should match the topology.kubernetes.io/zone label + of the nodes where endpoints are running. + Zones not listed in the configuration receive a default weight of 1. + type: string + required: + - weight + - zone + type: object + type: array + x-kubernetes-list-map-keys: + - zone + x-kubernetes-list-type: map type: object required: - type @@ -2762,10 +2827,15 @@ spec: and LeastRequest load balancers. rule: 'self.type in [''Random'', ''ConsistentHash''] ? !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 ' + - message: PreferLocal zone-aware routing is not supported + for ConsistentHash load balancers. Use weightedZones + instead. + rule: 'self.type == ''ConsistentHash'' && has(self.zoneAware) + ? !has(self.zoneAware.preferLocal) : true' + - message: ZoneAware PreferLocal and WeightedZones cannot + be specified together. + rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) + && has(self.zoneAware.weightedZones)) : true' proxyProtocol: description: ProxyProtocol enables the Proxy Protocol when communicating with the backend. @@ -4121,6 +4191,36 @@ spec: minimum: 0 type: integer type: object + weightedZones: + description: |- + WeightedZones configures weight-based traffic distribution across locality zones. + Traffic is distributed proportionally based on the sum of all zone weights. + items: + description: WeightedZoneConfig defines + the weight for a specific locality zone. + properties: + weight: + description: |- + Weight defines the weight for this locality. + Higher values receive more traffic. The actual traffic distribution + is proportional to this value relative to other localities. + format: int32 + type: integer + zone: + description: |- + Zone specifies the topology zone this weight applies to. + The value should match the topology.kubernetes.io/zone label + of the nodes where endpoints are running. + Zones not listed in the configuration receive a default weight of 1. + type: string + required: + - weight + - zone + type: object + type: array + x-kubernetes-list-map-keys: + - zone + x-kubernetes-list-type: map type: object required: - type @@ -4134,11 +4234,15 @@ spec: for RoundRobin and LeastRequest load balancers. rule: 'self.type in [''Random'', ''ConsistentHash''] ? !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 ' + - message: PreferLocal zone-aware routing is not + supported for ConsistentHash load balancers. + Use weightedZones instead. + rule: 'self.type == ''ConsistentHash'' && has(self.zoneAware) + ? !has(self.zoneAware.preferLocal) : true' + - message: ZoneAware PreferLocal and WeightedZones + cannot be specified together. + rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) + && has(self.zoneAware.weightedZones)) : true' proxyProtocol: description: ProxyProtocol enables the Proxy Protocol when communicating with the backend. @@ -5543,6 +5647,36 @@ spec: minimum: 0 type: integer type: object + weightedZones: + description: |- + WeightedZones configures weight-based traffic distribution across locality zones. + Traffic is distributed proportionally based on the sum of all zone weights. + items: + description: WeightedZoneConfig defines the + weight for a specific locality zone. + properties: + weight: + description: |- + Weight defines the weight for this locality. + Higher values receive more traffic. The actual traffic distribution + is proportional to this value relative to other localities. + format: int32 + type: integer + zone: + description: |- + Zone specifies the topology zone this weight applies to. + The value should match the topology.kubernetes.io/zone label + of the nodes where endpoints are running. + Zones not listed in the configuration receive a default weight of 1. + type: string + required: + - weight + - zone + type: object + type: array + x-kubernetes-list-map-keys: + - zone + x-kubernetes-list-type: map type: object required: - type @@ -5556,10 +5690,15 @@ spec: and LeastRequest load balancers. rule: 'self.type in [''Random'', ''ConsistentHash''] ? !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 ' + - message: PreferLocal zone-aware routing is not supported + for ConsistentHash load balancers. Use weightedZones + instead. + rule: 'self.type == ''ConsistentHash'' && has(self.zoneAware) + ? !has(self.zoneAware.preferLocal) : true' + - message: ZoneAware PreferLocal and WeightedZones cannot + be specified together. + rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) + && has(self.zoneAware.weightedZones)) : true' proxyProtocol: description: ProxyProtocol enables the Proxy Protocol when communicating with the backend. diff --git a/internal/gatewayapi/clustersettings.go b/internal/gatewayapi/clustersettings.go index 867d269f6a..51c668a3a7 100644 --- a/internal/gatewayapi/clustersettings.go +++ b/internal/gatewayapi/clustersettings.go @@ -357,6 +357,17 @@ func buildLoadBalancer(policy *egv1a1.ClusterSettings) (*ir.LoadBalancer, error) } } + // Add WeightedZones loadbalancer settings + if policy.LoadBalancer.ZoneAware != nil && len(policy.LoadBalancer.ZoneAware.WeightedZones) > 0 { + lb.WeightedZones = make([]ir.WeightedZoneConfig, len(policy.LoadBalancer.ZoneAware.WeightedZones)) + for i, wz := range policy.LoadBalancer.ZoneAware.WeightedZones { + lb.WeightedZones[i] = ir.WeightedZoneConfig{ + Zone: wz.Zone, + Weight: wz.Weight, + } + } + } + // Add EndpointOverride if specified if policy.LoadBalancer.EndpointOverride != nil { lb.EndpointOverride = buildEndpointOverride(*policy.LoadBalancer.EndpointOverride) diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-with-weighted-zones.in.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-with-weighted-zones.in.yaml new file mode 100644 index 0000000000..43a3911ed7 --- /dev/null +++ b/internal/gatewayapi/testdata/backendtrafficpolicy-with-weighted-zones.in.yaml @@ -0,0 +1,56 @@ +gateways: +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + namespace: envoy-gateway + name: gateway-1 + spec: + gatewayClassName: envoy-gateway-class + listeners: + - name: http + protocol: HTTP + port: 80 + allowedRoutes: + namespaces: + from: All +httpRoutes: +- apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + namespace: default + name: httproute-1 + spec: + hostnames: + - gateway.envoyproxy.io + parentRefs: + - namespace: envoy-gateway + name: gateway-1 + sectionName: http + rules: + - matches: + - path: + value: "/" + backendRefs: + - name: service-1 + port: 8080 +backendTrafficPolicies: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: BackendTrafficPolicy + metadata: + namespace: default + name: policy-for-route + spec: + targetRef: + group: gateway.networking.k8s.io + kind: HTTPRoute + name: httproute-1 + loadBalancer: + type: RoundRobin + zoneAware: + weightedZones: + - zone: us-east-1a + weight: 70 + - zone: us-east-1b + weight: 20 + - zone: us-west-2a + weight: 10 diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-with-weighted-zones.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-with-weighted-zones.out.yaml new file mode 100644 index 0000000000..462b5e4bfe --- /dev/null +++ b/internal/gatewayapi/testdata/backendtrafficpolicy-with-weighted-zones.out.yaml @@ -0,0 +1,230 @@ +backendTrafficPolicies: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: BackendTrafficPolicy + metadata: + name: policy-for-route + namespace: default + spec: + loadBalancer: + type: RoundRobin + zoneAware: + weightedZones: + - weight: 70 + zone: us-east-1a + - weight: 20 + zone: us-east-1b + - weight: 10 + zone: us-west-2a + targetRef: + group: gateway.networking.k8s.io + kind: HTTPRoute + name: httproute-1 + status: + ancestors: + - ancestorRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-1 + namespace: envoy-gateway + sectionName: http + conditions: + - lastTransitionTime: null + message: Policy has been accepted. + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: spec.targetRef is deprecated, use spec.targetRefs instead + reason: DeprecatedField + status: "True" + type: Warning + controllerName: gateway.envoyproxy.io/gatewayclass-controller +gateways: +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + name: gateway-1 + namespace: envoy-gateway + spec: + gatewayClassName: envoy-gateway-class + listeners: + - allowedRoutes: + namespaces: + from: All + name: http + port: 80 + protocol: HTTP + status: + listeners: + - attachedRoutes: 1 + conditions: + - lastTransitionTime: null + message: Sending translated listener configuration to the data plane + reason: Programmed + status: "True" + type: Programmed + - lastTransitionTime: null + message: Listener has been successfully translated + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: Listener references have been resolved + reason: ResolvedRefs + status: "True" + type: ResolvedRefs + name: http + supportedKinds: + - group: gateway.networking.k8s.io + kind: HTTPRoute + - group: gateway.networking.k8s.io + kind: GRPCRoute +httpRoutes: +- apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + name: httproute-1 + namespace: default + spec: + hostnames: + - gateway.envoyproxy.io + parentRefs: + - name: gateway-1 + namespace: envoy-gateway + sectionName: http + rules: + - backendRefs: + - name: service-1 + port: 8080 + matches: + - path: + value: / + status: + parents: + - conditions: + - lastTransitionTime: null + message: Route is accepted + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: Resolved all the Object references for the Route + reason: ResolvedRefs + status: "True" + type: ResolvedRefs + controllerName: gateway.envoyproxy.io/gatewayclass-controller + parentRef: + name: gateway-1 + namespace: envoy-gateway + sectionName: http +infraIR: + envoy-gateway/gateway-1: + proxy: + listeners: + - name: envoy-gateway/gateway-1/http + ports: + - containerPort: 10080 + name: http-80 + protocol: HTTP + servicePort: 80 + metadata: + labels: + gateway.envoyproxy.io/owning-gateway-name: gateway-1 + gateway.envoyproxy.io/owning-gateway-namespace: envoy-gateway + ownerReference: + kind: GatewayClass + name: envoy-gateway-class + name: envoy-gateway/gateway-1 + namespace: envoy-gateway-system +xdsIR: + envoy-gateway/gateway-1: + accessLog: + json: + - path: /dev/stdout + globalResources: + proxyServiceCluster: + metadata: + kind: Service + name: envoy-envoy-gateway-gateway-1-196ae069 + namespace: envoy-gateway-system + sectionName: "8080" + name: envoy-gateway/gateway-1 + settings: + - addressType: IP + endpoints: + - host: 7.6.5.4 + port: 8080 + zone: zone1 + metadata: + kind: Service + name: envoy-envoy-gateway-gateway-1-196ae069 + namespace: envoy-gateway-system + sectionName: "8080" + name: envoy-gateway/gateway-1 + protocol: TCP + http: + - address: 0.0.0.0 + externalPort: 80 + hostnames: + - '*' + isHTTP2: false + metadata: + kind: Gateway + name: gateway-1 + namespace: envoy-gateway + sectionName: http + name: envoy-gateway/gateway-1/http + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10080 + routes: + - destination: + metadata: + kind: HTTPRoute + name: httproute-1 + namespace: default + name: httproute/default/httproute-1/rule/0 + settings: + - addressType: IP + endpoints: + - host: 7.7.7.7 + port: 8080 + metadata: + kind: Service + name: service-1 + namespace: default + sectionName: "8080" + name: httproute/default/httproute-1/rule/0/backend/0 + protocol: HTTP + weight: 1 + hostname: gateway.envoyproxy.io + isHTTP2: false + metadata: + kind: HTTPRoute + name: httproute-1 + namespace: default + policies: + - kind: BackendTrafficPolicy + name: policy-for-route + namespace: default + name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io + pathMatch: + distinct: false + name: "" + prefix: / + traffic: + loadBalancer: + roundRobin: {} + weightedZones: + - weight: 70 + zone: us-east-1a + - weight: 20 + zone: us-east-1b + - weight: 10 + zone: us-west-2a + readyListener: + address: 0.0.0.0 + ipFamily: IPv4 + path: /ready + port: 19003 diff --git a/internal/ir/xds.go b/internal/ir/xds.go index d41e5afca8..1380222b31 100644 --- a/internal/ir/xds.go +++ b/internal/ir/xds.go @@ -893,7 +893,7 @@ func (h *HTTPRoute) GetRetry() *Retry { func (h *HTTPRoute) NeedsClusterPerSetting() bool { if h.Traffic != nil && h.Traffic.LoadBalancer != nil && - h.Traffic.LoadBalancer.PreferLocal != nil { + (h.Traffic.LoadBalancer.PreferLocal != nil || len(h.Traffic.LoadBalancer.WeightedZones) > 0) { return true } // When the destination has both valid and invalid backend weights, we use weighted clusters to distribute between @@ -2727,6 +2727,8 @@ type LoadBalancer struct { ConsistentHash *ConsistentHash `json:"consistentHash,omitempty" yaml:"consistentHash,omitempty"` // PreferLocal defines the configuration related to the distribution of requests between locality zones. PreferLocal *PreferLocalZone `json:"preferLocal,omitempty" yaml:"preferLocal,omitempty"` + // WeightedZones defines explicit weight-based traffic distribution across locality zones. + WeightedZones []WeightedZoneConfig `json:"weightedZones,omitempty" yaml:"weightedZones,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. @@ -3491,6 +3493,15 @@ type ForceLocalZone struct { MinEndpointsInZoneThreshold *uint32 `json:"minEndpointsInZoneThreshold,omitempty" yaml:"minEndpointsInZoneThreshold,omitempty"` } +// WeightedZoneConfig defines the weight for a specific locality zone. +// +k8s:deepcopy-gen=true +type WeightedZoneConfig struct { + // Zone is the locality zone name. + Zone string `json:"zone" yaml:"zone"` + // Weight is the proportional traffic weight for this zone. + Weight uint32 `json:"weight" yaml:"weight"` +} + // EndpointOverride defines the configuration for endpoint override. // +k8s:deepcopy-gen=true type EndpointOverride struct { diff --git a/internal/ir/zz_generated.deepcopy.go b/internal/ir/zz_generated.deepcopy.go index c746690126..463eefcce8 100644 --- a/internal/ir/zz_generated.deepcopy.go +++ b/internal/ir/zz_generated.deepcopy.go @@ -2631,6 +2631,11 @@ func (in *LoadBalancer) DeepCopyInto(out *LoadBalancer) { *out = new(PreferLocalZone) (*in).DeepCopyInto(*out) } + if in.WeightedZones != nil { + in, out := &in.WeightedZones, &out.WeightedZones + *out = make([]WeightedZoneConfig, len(*in)) + copy(*out, *in) + } if in.EndpointOverride != nil { in, out := &in.EndpointOverride, &out.EndpointOverride *out = new(EndpointOverride) @@ -4729,6 +4734,21 @@ func (in *Wasm) DeepCopy() *Wasm { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *WeightedZoneConfig) DeepCopyInto(out *WeightedZoneConfig) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WeightedZoneConfig. +func (in *WeightedZoneConfig) DeepCopy() *WeightedZoneConfig { + if in == nil { + return nil + } + out := new(WeightedZoneConfig) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *XForwardedClientCert) DeepCopyInto(out *XForwardedClientCert) { *out = *in diff --git a/internal/xds/translator/cluster.go b/internal/xds/translator/cluster.go index 0384f8dac7..0b3be55247 100644 --- a/internal/xds/translator/cluster.go +++ b/internal/xds/translator/cluster.go @@ -430,6 +430,10 @@ func buildXdsCluster(args *xdsClusterArgs) (*buildClusterResult, error) { if args.loadBalancer.ConsistentHash.TableSize != nil { consistentHash.TableSize = wrapperspb.UInt64(*args.loadBalancer.ConsistentHash.TableSize) } + // Enable locality weighted load balancing for Maglev when weighted zones are configured + if len(args.loadBalancer.WeightedZones) > 0 { + consistentHash.LocalityWeightedLbConfig = &commonv3.LocalityLbConfig_LocalityWeightedLbConfig{} + } typedConsistentHash, err := proto.ToAnyWithValidation(consistentHash) if err != nil { return nil, err @@ -759,7 +763,7 @@ func buildXdsClusterCircuitBreaker(circuitBreaker *ir.CircuitBreaker) *clusterv3 return ecb } -func buildXdsClusterLoadAssignment(clusterName string, destSettings []*ir.DestinationSetting, hc *ir.HealthCheck, preferLocal *ir.PreferLocalZone) *endpointv3.ClusterLoadAssignment { +func buildXdsClusterLoadAssignment(clusterName string, destSettings []*ir.DestinationSetting, hc *ir.HealthCheck, preferLocal *ir.PreferLocalZone, weightedZones []ir.WeightedZoneConfig) *endpointv3.ClusterLoadAssignment { localities := make([]*endpointv3.LocalityLbEndpoints, 0, len(destSettings)) for i, ds := range destSettings { @@ -783,9 +787,12 @@ func buildXdsClusterLoadAssignment(clusterName string, destSettings []*ir.Destin // if multiple backendRefs exist. This pushes part of the routing logic higher up the stack which can // limit host selection controls during retries and session affinity. // For more details see https://github.com/envoyproxy/gateway/issues/5307#issuecomment-2688767482 - if ds.PreferLocal != nil || preferLocal != nil { + switch { + case len(weightedZones) > 0: + localities = append(localities, buildWeightedZonalLocalities(metadata, ds, hc, weightedZones)...) + case ds.PreferLocal != nil || preferLocal != nil: localities = append(localities, buildZonalLocalities(metadata, ds, hc)...) - } else { + default: localities = append(localities, buildWeightedLocalities(metadata, ds, hc)) } } @@ -836,6 +843,63 @@ func buildZonalLocalities(metadata *corev3.Metadata, ds *ir.DestinationSetting, return localities } +func buildWeightedZonalLocalities(metadata *corev3.Metadata, ds *ir.DestinationSetting, hc *ir.HealthCheck, weightedZones []ir.WeightedZoneConfig) []*endpointv3.LocalityLbEndpoints { + // Build zone->weight lookup map + zoneWeights := make(map[string]uint32, len(weightedZones)) + for _, wz := range weightedZones { + zoneWeights[wz.Zone] = wz.Weight + } + + // Group endpoints by zone + zonalEndpoints := make(map[string][]*endpointv3.LbEndpoint) + for _, irEp := range ds.Endpoints { + healthStatus := corev3.HealthStatus_UNKNOWN + if irEp.Draining { + healthStatus = corev3.HealthStatus_DRAINING + } + lbEndpoint := &endpointv3.LbEndpoint{ + Metadata: metadata, + HostIdentifier: &endpointv3.LbEndpoint_Endpoint{ + Endpoint: &endpointv3.Endpoint{ + Hostname: ptr.Deref(irEp.Hostname, ""), + Address: buildAddress(irEp), + HealthCheckConfig: buildHealthCheckConfig(hc), + }, + }, + LoadBalancingWeight: wrapperspb.UInt32(1), + HealthStatus: healthStatus, + } + zone := ptr.Deref(irEp.Zone, "") + zonalEndpoints[zone] = append(zonalEndpoints[zone], lbEndpoint) + } + + localities := make([]*endpointv3.LocalityLbEndpoints, 0, len(zonalEndpoints)) + for zone, endPts := range zonalEndpoints { + // Look up configured weight; default to 1 if zone not explicitly listed + weight := uint32(1) + if w, ok := zoneWeights[zone]; ok { + weight = w + } + locality := &endpointv3.LocalityLbEndpoints{ + Locality: &corev3.Locality{ + Zone: zone, + }, + LbEndpoints: endPts, + LoadBalancingWeight: wrapperspb.UInt32(weight), + Priority: ptr.Deref(ds.Priority, 0), + Metadata: buildXdsMetadata(ds.Metadata), + } + localities = append(localities, locality) + } + + // Sort by zone for deterministic output + sort.Slice(localities, func(i, j int) bool { + return localities[i].Locality.Zone < localities[j].Locality.Zone + }) + + return localities +} + func buildWeightedLocalities(metadata *corev3.Metadata, ds *ir.DestinationSetting, hc *ir.HealthCheck) *endpointv3.LocalityLbEndpoints { endpoints := make([]*endpointv3.LbEndpoint, 0, len(ds.Endpoints)) diff --git a/internal/xds/translator/cluster_test.go b/internal/xds/translator/cluster_test.go index 98a06a6b34..119a44911a 100644 --- a/internal/xds/translator/cluster_test.go +++ b/internal/xds/translator/cluster_test.go @@ -60,7 +60,7 @@ func TestBuildXdsClusterLoadAssignment(t *testing.T) { Endpoints: []*ir.DestinationEndpoint{{Host: envoyGatewayXdsServerHost, Port: bootstrap.DefaultXdsServerPort}}, } settings := []*ir.DestinationSetting{ds} - dynamicXdsClusterLoadAssignment := buildXdsClusterLoadAssignment(bootstrapXdsCluster.Name, settings, nil, nil) + dynamicXdsClusterLoadAssignment := buildXdsClusterLoadAssignment(bootstrapXdsCluster.Name, settings, nil, nil, nil) requireCmpNoDiff(t, bootstrapXdsCluster.LoadAssignment.Endpoints[0].LbEndpoints[0], dynamicXdsClusterLoadAssignment.Endpoints[0].LbEndpoints[0]) } @@ -112,7 +112,7 @@ func TestBuildXdsClusterLoadAssignmentWithHealthCheckConfig(t *testing.T) { Endpoints: []*ir.DestinationEndpoint{{Host: envoyGatewayXdsServerHost, Port: 8080}}, }} - clusterLoadAssignment := buildXdsClusterLoadAssignment("test-cluster", settings, tc.healthCheck, nil) + clusterLoadAssignment := buildXdsClusterLoadAssignment("test-cluster", settings, tc.healthCheck, nil, nil) require.Len(t, clusterLoadAssignment.GetEndpoints(), 1) require.Len(t, clusterLoadAssignment.GetEndpoints()[0].GetLbEndpoints(), 1) diff --git a/internal/xds/translator/testdata/in/xds-ir/http-route-weighted-zones.yaml b/internal/xds/translator/testdata/in/xds-ir/http-route-weighted-zones.yaml new file mode 100644 index 0000000000..d3ca64b6e6 --- /dev/null +++ b/internal/xds/translator/testdata/in/xds-ir/http-route-weighted-zones.yaml @@ -0,0 +1,58 @@ +http: +- name: "first-listener" + address: "::" + port: 10080 + hostnames: + - "*" + routes: + - name: "route-with-weighted-zones-roundrobin" + hostname: "*" + destination: + name: "route-with-weighted-zones-roundrobin-dest" + settings: + - endpoints: + - host: "1.2.3.4" + port: 8080 + zone: us-east-1a + - host: "2.3.4.5" + port: 8080 + zone: us-east-1a + - host: "3.4.5.6" + port: 8080 + zone: us-east-1b + - host: "4.5.6.7" + port: 8080 + zone: us-east-1c + name: "route-with-weighted-zones-roundrobin-dest/backend/0" + weight: 1 + traffic: + loadBalancer: + roundRobin: {} + weightedZones: + - zone: us-east-1a + weight: 70 + - zone: us-east-1b + weight: 20 + - name: "route-with-weighted-zones-maglev" + hostname: "*" + destination: + name: "route-with-weighted-zones-maglev-dest" + settings: + - endpoints: + - host: "10.0.0.1" + port: 8080 + zone: us-west-2a + - host: "10.0.0.2" + port: 8080 + zone: us-west-2b + name: "route-with-weighted-zones-maglev-dest/backend/0" + weight: 1 + traffic: + loadBalancer: + consistentHash: + sourceIP: true + weightedZones: + - zone: us-west-2a + weight: 80 + - zone: us-west-2b + weight: 20 diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-weighted-zones.clusters.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-weighted-zones.clusters.yaml new file mode 100644 index 0000000000..cb66fa7fd1 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/http-route-weighted-zones.clusters.yaml @@ -0,0 +1,46 @@ +- circuitBreakers: + thresholds: + - maxRetries: 1024 + commonLbConfig: {} + connectTimeout: 10s + dnsLookupFamily: V4_PREFERRED + edsClusterConfig: + edsConfig: + ads: {} + resourceApiVersion: V3 + serviceName: route-with-weighted-zones-roundrobin-dest/backend/0 + ignoreHealthOnHostRemoval: true + loadBalancingPolicy: + policies: + - typedExtensionConfig: + name: envoy.load_balancing_policies.round_robin + typedConfig: + '@type': type.googleapis.com/envoy.extensions.load_balancing_policies.round_robin.v3.RoundRobin + localityLbConfig: + localityWeightedLbConfig: {} + name: route-with-weighted-zones-roundrobin-dest/backend/0 + perConnectionBufferLimitBytes: 32768 + type: EDS +- circuitBreakers: + thresholds: + - maxRetries: 1024 + commonLbConfig: {} + connectTimeout: 10s + dnsLookupFamily: V4_PREFERRED + edsClusterConfig: + edsConfig: + ads: {} + resourceApiVersion: V3 + serviceName: route-with-weighted-zones-maglev-dest/backend/0 + ignoreHealthOnHostRemoval: true + lbPolicy: MAGLEV + loadBalancingPolicy: + policies: + - typedExtensionConfig: + name: envoy.load_balancing_policies.maglev + typedConfig: + '@type': type.googleapis.com/envoy.extensions.load_balancing_policies.maglev.v3.Maglev + localityWeightedLbConfig: {} + name: route-with-weighted-zones-maglev-dest/backend/0 + perConnectionBufferLimitBytes: 32768 + type: EDS diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-weighted-zones.endpoints.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-weighted-zones.endpoints.yaml new file mode 100644 index 0000000000..694bdbf80f --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/http-route-weighted-zones.endpoints.yaml @@ -0,0 +1,60 @@ +- clusterName: route-with-weighted-zones-roundrobin-dest/backend/0 + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 1.2.3.4 + portValue: 8080 + loadBalancingWeight: 1 + - endpoint: + address: + socketAddress: + address: 2.3.4.5 + portValue: 8080 + loadBalancingWeight: 1 + loadBalancingWeight: 70 + locality: + zone: us-east-1a + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 3.4.5.6 + portValue: 8080 + loadBalancingWeight: 1 + loadBalancingWeight: 20 + locality: + zone: us-east-1b + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 4.5.6.7 + portValue: 8080 + loadBalancingWeight: 1 + loadBalancingWeight: 1 + locality: + zone: us-east-1c +- clusterName: route-with-weighted-zones-maglev-dest/backend/0 + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 10.0.0.1 + portValue: 8080 + loadBalancingWeight: 1 + loadBalancingWeight: 80 + locality: + zone: us-west-2a + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 10.0.0.2 + portValue: 8080 + loadBalancingWeight: 1 + loadBalancingWeight: 20 + locality: + zone: us-west-2b diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-weighted-zones.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-weighted-zones.listeners.yaml new file mode 100644 index 0000000000..5c7db41545 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/http-route-weighted-zones.listeners.yaml @@ -0,0 +1,33 @@ +- address: + socketAddress: + address: '::' + portValue: 10080 + defaultFilterChain: + filters: + - name: envoy.filters.network.http_connection_manager + typedConfig: + '@type': type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager + commonHttpProtocolOptions: + headersWithUnderscoresAction: REJECT_REQUEST + http2ProtocolOptions: + initialConnectionWindowSize: 1048576 + initialStreamWindowSize: 65536 + maxConcurrentStreams: 100 + httpFilters: + - name: envoy.filters.http.router + typedConfig: + '@type': type.googleapis.com/envoy.extensions.filters.http.router.v3.Router + suppressEnvoyHeaders: true + normalizePath: true + rds: + configSource: + ads: {} + resourceApiVersion: V3 + routeConfigName: first-listener + serverHeaderTransformation: PASS_THROUGH + statPrefix: http-10080 + useRemoteAddress: true + name: first-listener + maxConnectionsToAcceptPerSocketEvent: 1 + name: first-listener + perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-weighted-zones.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-weighted-zones.routes.yaml new file mode 100644 index 0000000000..ecca8196e4 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/http-route-weighted-zones.routes.yaml @@ -0,0 +1,32 @@ +- ignorePortInHostMatching: true + name: first-listener + virtualHosts: + - domains: + - '*' + name: first-listener/* + routes: + - match: + prefix: / + name: route-with-weighted-zones-roundrobin + route: + clusterNotFoundResponseCode: INTERNAL_SERVER_ERROR + upgradeConfigs: + - upgradeType: websocket + weightedClusters: + clusters: + - name: route-with-weighted-zones-roundrobin-dest/backend/0 + weight: 1 + - match: + prefix: / + name: route-with-weighted-zones-maglev + route: + clusterNotFoundResponseCode: INTERNAL_SERVER_ERROR + hashPolicy: + - connectionProperties: + sourceIp: true + upgradeConfigs: + - upgradeType: websocket + weightedClusters: + clusters: + - name: route-with-weighted-zones-maglev-dest/backend/0 + weight: 1 diff --git a/internal/xds/translator/translator.go b/internal/xds/translator/translator.go index 53b7737e7b..f5c6047a06 100644 --- a/internal/xds/translator/translator.go +++ b/internal/xds/translator/translator.go @@ -1105,8 +1105,8 @@ func addXdsCluster(tCtx *types.ResourceVersionTable, args *xdsClusterArgs) error return err } xdsCluster := result.cluster - preferLocal := ptr.Deref(args.loadBalancer, ir.LoadBalancer{}).PreferLocal - xdsEndpoints := buildXdsClusterLoadAssignment(args.name, args.settings, args.healthCheck, preferLocal) + lb := ptr.Deref(args.loadBalancer, ir.LoadBalancer{}) + xdsEndpoints := buildXdsClusterLoadAssignment(args.name, args.settings, args.healthCheck, lb.PreferLocal, lb.WeightedZones) for _, ds := range args.settings { shouldValidateTLS := ds.TLS != nil && !ds.TLS.InsecureSkipVerify if shouldValidateTLS { diff --git a/release-notes/current.yaml b/release-notes/current.yaml index cdce7e9f52..b4d0c5a0ad 100644 --- a/release-notes/current.yaml +++ b/release-notes/current.yaml @@ -14,6 +14,7 @@ new features: | Added support for shadow mode in local rate limiting. Added `egctl config envoy-gateway` commands to retrieve Envoy Gateway admin config dumps. The DirectResponse body in HTTPFilter now supports Envoy command operators for dynamic content. See https://www.envoyproxy.io/docs/envoy/latest/configuration/observability/access_log/usage#command-operators for more details. + Support for configuring weights for locality zones. bug fixes: | Rejected ClientTrafficPolicy if invalid TLS cipher suites are configured. diff --git a/site/content/en/latest/api/extension_types.md b/site/content/en/latest/api/extension_types.md index bad944cd57..08a7b0b8e3 100644 --- a/site/content/en/latest/api/extension_types.md +++ b/site/content/en/latest/api/extension_types.md @@ -5739,6 +5739,21 @@ _Appears in:_ | `hostKeys` | _string array_ | false | | HostKeys is a list of keys for environment variables from the host envoy process
that should be passed into the Wasm VM. This is useful for passing secrets to to Wasm extensions. | +#### WeightedZoneConfig + + + +WeightedZoneConfig defines the weight for a specific locality zone. + +_Appears in:_ +- [ZoneAware](#zoneaware) + +| Field | Type | Required | Default | Description | +| --- | --- | --- | --- | --- | +| `zone` | _string_ | true | | Zone specifies the topology zone this weight applies to.
The value should match the topology.kubernetes.io/zone label
of the nodes where endpoints are running.
Zones not listed in the configuration receive a default weight of 1. | +| `weight` | _integer_ | true | | Weight defines the weight for this locality.
Higher values receive more traffic. The actual traffic distribution
is proportional to this value relative to other localities. | + + #### WithUnderscoresAction _Underlying type:_ _string_ @@ -5902,6 +5917,7 @@ _Appears in:_ | Field | Type | Required | Default | Description | | --- | --- | --- | --- | --- | | `preferLocal` | _[PreferLocalZone](#preferlocalzone)_ | false | | PreferLocalZone configures zone-aware routing to prefer sending traffic to the local locality zone. | +| `weightedZones` | _[WeightedZoneConfig](#weightedzoneconfig) array_ | false | | WeightedZones configures weight-based traffic distribution across locality zones.
Traffic is distributed proportionally based on the sum of all zone weights. | #### ZstdCompressor diff --git a/test/cel-validation/backendtrafficpolicy_test.go b/test/cel-validation/backendtrafficpolicy_test.go index 741affc1ca..812d27b83c 100644 --- a/test/cel-validation/backendtrafficpolicy_test.go +++ b/test/cel-validation/backendtrafficpolicy_test.go @@ -349,7 +349,7 @@ func TestBackendTrafficPolicyTarget(t *testing.T) { }, }, { - desc: "consistentHash lb with zoneAware", + desc: "consistentHash lb with empty zoneAware", mutate: func(btp *egv1a1.BackendTrafficPolicy) { btp.Spec = egv1a1.BackendTrafficPolicySpec{ PolicyTargetReferences: egv1a1.PolicyTargetReferences{ @@ -372,10 +372,69 @@ func TestBackendTrafficPolicyTarget(t *testing.T) { }, } }, + wantErrors: []string{}, + }, + { + desc: "consistentHash lb with zoneAware preferLocal", + mutate: func(btp *egv1a1.BackendTrafficPolicy) { + btp.Spec = egv1a1.BackendTrafficPolicySpec{ + PolicyTargetReferences: egv1a1.PolicyTargetReferences{ + TargetRef: &gwapiv1.LocalPolicyTargetReferenceWithSectionName{ + LocalPolicyTargetReference: gwapiv1.LocalPolicyTargetReference{ + Group: gwapiv1.Group("gateway.networking.k8s.io"), + Kind: gwapiv1.Kind("Gateway"), + Name: gwapiv1.ObjectName("eg"), + }, + }, + }, + ClusterSettings: egv1a1.ClusterSettings{ + LoadBalancer: &egv1a1.LoadBalancer{ + Type: egv1a1.ConsistentHashLoadBalancerType, + ConsistentHash: &egv1a1.ConsistentHash{ + Type: "SourceIP", + }, + ZoneAware: &egv1a1.ZoneAware{ + PreferLocal: &egv1a1.PreferLocalZone{}, + }, + }, + }, + } + }, wantErrors: []string{ "spec.loadBalancer: Invalid value:", - ": Currently ZoneAware is only supported for LeastRequest, Random, and RoundRobin load balancers", + ": PreferLocal zone-aware routing is not supported for ConsistentHash load balancers. Use weightedZones instead.", + }, + }, + { + desc: "consistentHash lb with zoneAware weightedZones", + mutate: func(btp *egv1a1.BackendTrafficPolicy) { + btp.Spec = egv1a1.BackendTrafficPolicySpec{ + PolicyTargetReferences: egv1a1.PolicyTargetReferences{ + TargetRef: &gwapiv1.LocalPolicyTargetReferenceWithSectionName{ + LocalPolicyTargetReference: gwapiv1.LocalPolicyTargetReference{ + Group: gwapiv1.Group("gateway.networking.k8s.io"), + Kind: gwapiv1.Kind("Gateway"), + Name: gwapiv1.ObjectName("eg"), + }, + }, + }, + ClusterSettings: egv1a1.ClusterSettings{ + LoadBalancer: &egv1a1.LoadBalancer{ + Type: egv1a1.ConsistentHashLoadBalancerType, + ConsistentHash: &egv1a1.ConsistentHash{ + Type: "SourceIP", + }, + ZoneAware: &egv1a1.ZoneAware{ + WeightedZones: []egv1a1.WeightedZoneConfig{{ + Zone: "us-east-1a", + Weight: uint32(70), + }}, + }, + }, + }, + } }, + wantErrors: []string{}, }, { desc: "leastRequest with ConsistentHash nil", @@ -422,6 +481,68 @@ func TestBackendTrafficPolicyTarget(t *testing.T) { }, wantErrors: []string{}, }, + { + desc: "leastRequest with ZoneAware PreferLocal and WeightedZones set", + mutate: func(btp *egv1a1.BackendTrafficPolicy) { + btp.Spec = egv1a1.BackendTrafficPolicySpec{ + PolicyTargetReferences: egv1a1.PolicyTargetReferences{ + TargetRef: &gwapiv1.LocalPolicyTargetReferenceWithSectionName{ + LocalPolicyTargetReference: gwapiv1.LocalPolicyTargetReference{ + Group: gwapiv1.Group("gateway.networking.k8s.io"), + Kind: gwapiv1.Kind("Gateway"), + Name: gwapiv1.ObjectName("eg"), + }, + }, + }, + ClusterSettings: egv1a1.ClusterSettings{ + LoadBalancer: &egv1a1.LoadBalancer{ + Type: egv1a1.LeastRequestLoadBalancerType, + ZoneAware: &egv1a1.ZoneAware{ + PreferLocal: &egv1a1.PreferLocalZone{}, + WeightedZones: []egv1a1.WeightedZoneConfig{{ + Zone: "zone1", + Weight: uint32(10), + }}, + }, + }, + }, + } + }, + wantErrors: []string{ + "spec.loadBalancer: Invalid value:", + ": ZoneAware PreferLocal and WeightedZones cannot be specified together", + }, + }, + { + desc: "weightedZones with duplicate zone names", + mutate: func(btp *egv1a1.BackendTrafficPolicy) { + btp.Spec = egv1a1.BackendTrafficPolicySpec{ + PolicyTargetReferences: egv1a1.PolicyTargetReferences{ + TargetRef: &gwapiv1.LocalPolicyTargetReferenceWithSectionName{ + LocalPolicyTargetReference: gwapiv1.LocalPolicyTargetReference{ + Group: gwapiv1.Group("gateway.networking.k8s.io"), + Kind: gwapiv1.Kind("Gateway"), + Name: gwapiv1.ObjectName("eg"), + }, + }, + }, + ClusterSettings: egv1a1.ClusterSettings{ + LoadBalancer: &egv1a1.LoadBalancer{ + Type: egv1a1.RoundRobinLoadBalancerType, + ZoneAware: &egv1a1.ZoneAware{ + WeightedZones: []egv1a1.WeightedZoneConfig{ + {Zone: "us-east-1a", Weight: 70}, + {Zone: "us-east-1a", Weight: 30}, + }, + }, + }, + }, + } + }, + wantErrors: []string{ + "spec.loadBalancer.zoneAware.weightedZones[1]: Duplicate value:", + }, + }, { desc: "leastRequest with SlowStar is set", mutate: func(btp *egv1a1.BackendTrafficPolicy) { diff --git a/test/e2e/testdata/weighted-zones.yaml b/test/e2e/testdata/weighted-zones.yaml new file mode 100644 index 0000000000..979652dcf7 --- /dev/null +++ b/test/e2e/testdata/weighted-zones.yaml @@ -0,0 +1,129 @@ +apiVersion: v1 +kind: Service +metadata: + name: weighted-zones-backend + namespace: gateway-conformance-infra +spec: + selector: + app: weighted-zones-backend + ports: + - protocol: TCP + port: 8080 + name: http11 + targetPort: 3000 +--- +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: weighted-zones-route + namespace: gateway-conformance-infra +spec: + parentRefs: + - name: same-namespace + rules: + - matches: + - path: + type: PathPrefix + value: /weighted-zones + backendRefs: + - name: weighted-zones-backend + port: 8080 +--- +apiVersion: gateway.envoyproxy.io/v1alpha1 +kind: BackendTrafficPolicy +metadata: + name: weighted-zones-policy + namespace: gateway-conformance-infra +spec: + targetRefs: + - group: gateway.networking.k8s.io + kind: HTTPRoute + name: weighted-zones-route + loadBalancer: + type: RoundRobin + zoneAware: + weightedZones: + - zone: "1" + weight: 80 + - zone: "2" + weight: 20 +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: weighted-zones-backend-zone1 + namespace: gateway-conformance-infra + labels: + app: weighted-zones-backend +spec: + replicas: 1 + selector: + matchLabels: + app: weighted-zones-backend + zone: "1" + template: + metadata: + labels: + app: weighted-zones-backend + zone: "1" + spec: + nodeSelector: + topology.kubernetes.io/zone: "1" + containers: + - name: weighted-zones-backend + # From https://github.com/kubernetes-sigs/gateway-api/blob/main/conformance/echo-basic/echo-basic.go + image: gcr.io/k8s-staging-gateway-api/echo-basic:v20231214-v1.0.0-140-gf544a46e + env: + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: SERVICE_NAME + value: weighted-zones-backend + resources: + requests: + cpu: 10m +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: weighted-zones-backend-zone2 + namespace: gateway-conformance-infra + labels: + app: weighted-zones-backend +spec: + replicas: 1 + selector: + matchLabels: + app: weighted-zones-backend + zone: "2" + template: + metadata: + labels: + app: weighted-zones-backend + zone: "2" + spec: + nodeSelector: + topology.kubernetes.io/zone: "2" + containers: + - name: weighted-zones-backend + # From https://github.com/kubernetes-sigs/gateway-api/blob/main/conformance/echo-basic/echo-basic.go + image: gcr.io/k8s-staging-gateway-api/echo-basic:v20231214-v1.0.0-140-gf544a46e + env: + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: SERVICE_NAME + value: weighted-zones-backend + resources: + requests: + cpu: 10m diff --git a/test/e2e/tests/weighted_zones.go b/test/e2e/tests/weighted_zones.go new file mode 100644 index 0000000000..dbc333cffd --- /dev/null +++ b/test/e2e/tests/weighted_zones.go @@ -0,0 +1,58 @@ +// Copyright Envoy Gateway Authors +// SPDX-License-Identifier: Apache-2.0 +// The full text of the Apache license is available in the LICENSE file at +// the root of the repo. + +//go:build e2e + +package tests + +import ( + "math" + "testing" + + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/types" + gwapiv1 "sigs.k8s.io/gateway-api/apis/v1" + "sigs.k8s.io/gateway-api/conformance/utils/suite" + + "github.com/envoyproxy/gateway/internal/gatewayapi" + "github.com/envoyproxy/gateway/internal/gatewayapi/resource" +) + +func init() { + ConformanceTests = append(ConformanceTests, WeightedZonesTest) +} + +var WeightedZonesTest = suite.ConformanceTest{ + ShortName: "WeightedZones", + Description: "Test weighted zone traffic distribution via BackendTrafficPolicy", + Manifests: []string{"testdata/weighted-zones.yaml"}, + Test: func(t *testing.T, suite *suite.ConformanceTestSuite) { + ns := "gateway-conformance-infra" + + WaitForPods(t, suite.Client, ns, map[string]string{"app": "weighted-zones-backend"}, corev1.PodRunning, &PodReady) + + BackendTrafficPolicyMustBeAccepted(t, + suite.Client, + types.NamespacedName{Name: "weighted-zones-policy", Namespace: ns}, + suite.ControllerName, + gwapiv1.ParentReference{ + Group: gatewayapi.GroupPtr(gwapiv1.GroupName), + Kind: gatewayapi.KindPtr(resource.KindGateway), + Namespace: gatewayapi.NamespacePtr(ns), + Name: gwapiv1.ObjectName("same-namespace"), + }, + ) + + t.Run("traffic should be distributed according to zone weights", func(t *testing.T) { + // BTP configures zone "1" with weight 80 and zone "2" with weight 20. + // Deployments pin one pod per zone via nodeSelector. + expected := map[string]int{ + "weighted-zones-backend-zone1": int(math.Round(sendRequests * 0.80)), + "weighted-zones-backend-zone2": int(math.Round(sendRequests * 0.20)), + } + runWeightedBackendTest(t, suite, nil, "weighted-zones-route", "/weighted-zones", "weighted-zones-backend", expected) + }) + }, +} diff --git a/test/helm/gateway-crds-helm/all.out.yaml b/test/helm/gateway-crds-helm/all.out.yaml index 831d23b3ea..a38447564d 100644 --- a/test/helm/gateway-crds-helm/all.out.yaml +++ b/test/helm/gateway-crds-helm/all.out.yaml @@ -22097,6 +22097,36 @@ spec: minimum: 0 type: integer type: object + weightedZones: + description: |- + WeightedZones configures weight-based traffic distribution across locality zones. + Traffic is distributed proportionally based on the sum of all zone weights. + items: + description: WeightedZoneConfig defines the weight for a + specific locality zone. + properties: + weight: + description: |- + Weight defines the weight for this locality. + Higher values receive more traffic. The actual traffic distribution + is proportional to this value relative to other localities. + format: int32 + type: integer + zone: + description: |- + Zone specifies the topology zone this weight applies to. + The value should match the topology.kubernetes.io/zone label + of the nodes where endpoints are running. + Zones not listed in the configuration receive a default weight of 1. + type: string + required: + - weight + - zone + type: object + type: array + x-kubernetes-list-map-keys: + - zone + x-kubernetes-list-type: map type: object required: - type @@ -22110,10 +22140,14 @@ spec: LeastRequest load balancers. rule: 'self.type in [''Random'', ''ConsistentHash''] ? !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 ' + - message: PreferLocal zone-aware routing is not supported for ConsistentHash + load balancers. Use weightedZones instead. + rule: 'self.type == ''ConsistentHash'' && has(self.zoneAware) ? + !has(self.zoneAware.preferLocal) : true' + - message: ZoneAware PreferLocal and WeightedZones cannot be specified + together. + rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) && + has(self.zoneAware.weightedZones)) : true' mergeType: description: |- MergeType determines how this configuration is merged with existing BackendTrafficPolicy @@ -27058,6 +27092,36 @@ spec: minimum: 0 type: integer type: object + weightedZones: + description: |- + WeightedZones configures weight-based traffic distribution across locality zones. + Traffic is distributed proportionally based on the sum of all zone weights. + items: + description: WeightedZoneConfig defines the weight + for a specific locality zone. + properties: + weight: + description: |- + Weight defines the weight for this locality. + Higher values receive more traffic. The actual traffic distribution + is proportional to this value relative to other localities. + format: int32 + type: integer + zone: + description: |- + Zone specifies the topology zone this weight applies to. + The value should match the topology.kubernetes.io/zone label + of the nodes where endpoints are running. + Zones not listed in the configuration receive a default weight of 1. + type: string + required: + - weight + - zone + type: object + type: array + x-kubernetes-list-map-keys: + - zone + x-kubernetes-list-type: map type: object required: - type @@ -27071,10 +27135,15 @@ spec: and LeastRequest load balancers. rule: 'self.type in [''Random'', ''ConsistentHash''] ? !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 ' + - message: PreferLocal zone-aware routing is not supported + for ConsistentHash load balancers. Use weightedZones + instead. + rule: 'self.type == ''ConsistentHash'' && has(self.zoneAware) + ? !has(self.zoneAware.preferLocal) : true' + - message: ZoneAware PreferLocal and WeightedZones cannot + be specified together. + rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) + && has(self.zoneAware.weightedZones)) : true' proxyProtocol: description: ProxyProtocol enables the Proxy Protocol when communicating with the backend. @@ -40865,6 +40934,37 @@ spec: minimum: 0 type: integer type: object + weightedZones: + description: |- + WeightedZones configures weight-based traffic distribution across locality zones. + Traffic is distributed proportionally based on the sum of all zone weights. + items: + description: WeightedZoneConfig + defines the weight for a specific + locality zone. + properties: + weight: + description: |- + Weight defines the weight for this locality. + Higher values receive more traffic. The actual traffic distribution + is proportional to this value relative to other localities. + format: int32 + type: integer + zone: + description: |- + Zone specifies the topology zone this weight applies to. + The value should match the topology.kubernetes.io/zone label + of the nodes where endpoints are running. + Zones not listed in the configuration receive a default weight of 1. + type: string + required: + - weight + - zone + type: object + type: array + x-kubernetes-list-map-keys: + - zone + x-kubernetes-list-type: map type: object required: - type @@ -40879,11 +40979,18 @@ spec: load balancers. rule: 'self.type in [''Random'', ''ConsistentHash''] ? !has(self.slowStart) : true ' - - message: Currently ZoneAware is only - supported for LeastRequest, Random, - and RoundRobin load balancers. + - message: PreferLocal zone-aware routing + is not supported for ConsistentHash + load balancers. Use weightedZones + instead. rule: 'self.type == ''ConsistentHash'' - ? !has(self.zoneAware) : true ' + && has(self.zoneAware) ? !has(self.zoneAware.preferLocal) + : true' + - message: ZoneAware PreferLocal and WeightedZones + cannot be specified together. + rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) + && has(self.zoneAware.weightedZones)) + : true' proxyProtocol: description: ProxyProtocol enables the Proxy Protocol when communicating with @@ -42134,6 +42241,37 @@ spec: minimum: 0 type: integer type: object + weightedZones: + description: |- + WeightedZones configures weight-based traffic distribution across locality zones. + Traffic is distributed proportionally based on the sum of all zone weights. + items: + description: WeightedZoneConfig + defines the weight for a specific + locality zone. + properties: + weight: + description: |- + Weight defines the weight for this locality. + Higher values receive more traffic. The actual traffic distribution + is proportional to this value relative to other localities. + format: int32 + type: integer + zone: + description: |- + Zone specifies the topology zone this weight applies to. + The value should match the topology.kubernetes.io/zone label + of the nodes where endpoints are running. + Zones not listed in the configuration receive a default weight of 1. + type: string + required: + - weight + - zone + type: object + type: array + x-kubernetes-list-map-keys: + - zone + x-kubernetes-list-type: map type: object required: - type @@ -42148,11 +42286,18 @@ spec: load balancers. rule: 'self.type in [''Random'', ''ConsistentHash''] ? !has(self.slowStart) : true ' - - message: Currently ZoneAware is only - supported for LeastRequest, Random, - and RoundRobin load balancers. + - message: PreferLocal zone-aware routing + is not supported for ConsistentHash + load balancers. Use weightedZones + instead. rule: 'self.type == ''ConsistentHash'' - ? !has(self.zoneAware) : true ' + && has(self.zoneAware) ? !has(self.zoneAware.preferLocal) + : true' + - message: ZoneAware PreferLocal and WeightedZones + cannot be specified together. + rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) + && has(self.zoneAware.weightedZones)) + : true' proxyProtocol: description: ProxyProtocol enables the Proxy Protocol when communicating with @@ -43551,6 +43696,37 @@ spec: minimum: 0 type: integer type: object + weightedZones: + description: |- + WeightedZones configures weight-based traffic distribution across locality zones. + Traffic is distributed proportionally based on the sum of all zone weights. + items: + description: WeightedZoneConfig defines + the weight for a specific locality + zone. + properties: + weight: + description: |- + Weight defines the weight for this locality. + Higher values receive more traffic. The actual traffic distribution + is proportional to this value relative to other localities. + format: int32 + type: integer + zone: + description: |- + Zone specifies the topology zone this weight applies to. + The value should match the topology.kubernetes.io/zone label + of the nodes where endpoints are running. + Zones not listed in the configuration receive a default weight of 1. + type: string + required: + - weight + - zone + type: object + type: array + x-kubernetes-list-map-keys: + - zone + x-kubernetes-list-type: map type: object required: - type @@ -43564,11 +43740,17 @@ spec: for RoundRobin and LeastRequest load balancers. rule: 'self.type in [''Random'', ''ConsistentHash''] ? !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 ' + - message: PreferLocal zone-aware routing is + not supported for ConsistentHash load balancers. + Use weightedZones instead. + rule: 'self.type == ''ConsistentHash'' && + has(self.zoneAware) ? !has(self.zoneAware.preferLocal) + : true' + - message: ZoneAware PreferLocal and WeightedZones + cannot be specified together. + rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) + && has(self.zoneAware.weightedZones)) : + true' proxyProtocol: description: ProxyProtocol enables the Proxy Protocol when communicating with the backend. @@ -44888,6 +45070,36 @@ spec: minimum: 0 type: integer type: object + weightedZones: + description: |- + WeightedZones configures weight-based traffic distribution across locality zones. + Traffic is distributed proportionally based on the sum of all zone weights. + items: + description: WeightedZoneConfig defines + the weight for a specific locality zone. + properties: + weight: + description: |- + Weight defines the weight for this locality. + Higher values receive more traffic. The actual traffic distribution + is proportional to this value relative to other localities. + format: int32 + type: integer + zone: + description: |- + Zone specifies the topology zone this weight applies to. + The value should match the topology.kubernetes.io/zone label + of the nodes where endpoints are running. + Zones not listed in the configuration receive a default weight of 1. + type: string + required: + - weight + - zone + type: object + type: array + x-kubernetes-list-map-keys: + - zone + x-kubernetes-list-type: map type: object required: - type @@ -44901,10 +45113,15 @@ spec: RoundRobin and LeastRequest load balancers. rule: 'self.type in [''Random'', ''ConsistentHash''] ? !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 ' + - message: PreferLocal zone-aware routing is not supported + for ConsistentHash load balancers. Use weightedZones + instead. + rule: 'self.type == ''ConsistentHash'' && has(self.zoneAware) + ? !has(self.zoneAware.preferLocal) : true' + - message: ZoneAware PreferLocal and WeightedZones + cannot be specified together. + rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) + && has(self.zoneAware.weightedZones)) : true' proxyProtocol: description: ProxyProtocol enables the Proxy Protocol when communicating with the backend. @@ -47569,6 +47786,36 @@ spec: minimum: 0 type: integer type: object + weightedZones: + description: |- + WeightedZones configures weight-based traffic distribution across locality zones. + Traffic is distributed proportionally based on the sum of all zone weights. + items: + description: WeightedZoneConfig defines the + weight for a specific locality zone. + properties: + weight: + description: |- + Weight defines the weight for this locality. + Higher values receive more traffic. The actual traffic distribution + is proportional to this value relative to other localities. + format: int32 + type: integer + zone: + description: |- + Zone specifies the topology zone this weight applies to. + The value should match the topology.kubernetes.io/zone label + of the nodes where endpoints are running. + Zones not listed in the configuration receive a default weight of 1. + type: string + required: + - weight + - zone + type: object + type: array + x-kubernetes-list-map-keys: + - zone + x-kubernetes-list-type: map type: object required: - type @@ -47582,10 +47829,15 @@ spec: and LeastRequest load balancers. rule: 'self.type in [''Random'', ''ConsistentHash''] ? !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 ' + - message: PreferLocal zone-aware routing is not supported + for ConsistentHash load balancers. Use weightedZones + instead. + rule: 'self.type == ''ConsistentHash'' && has(self.zoneAware) + ? !has(self.zoneAware.preferLocal) : true' + - message: ZoneAware PreferLocal and WeightedZones cannot + be specified together. + rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) + && has(self.zoneAware.weightedZones)) : true' proxyProtocol: description: ProxyProtocol enables the Proxy Protocol when communicating with the backend. @@ -48726,6 +48978,36 @@ spec: minimum: 0 type: integer type: object + weightedZones: + description: |- + WeightedZones configures weight-based traffic distribution across locality zones. + Traffic is distributed proportionally based on the sum of all zone weights. + items: + description: WeightedZoneConfig defines the + weight for a specific locality zone. + properties: + weight: + description: |- + Weight defines the weight for this locality. + Higher values receive more traffic. The actual traffic distribution + is proportional to this value relative to other localities. + format: int32 + type: integer + zone: + description: |- + Zone specifies the topology zone this weight applies to. + The value should match the topology.kubernetes.io/zone label + of the nodes where endpoints are running. + Zones not listed in the configuration receive a default weight of 1. + type: string + required: + - weight + - zone + type: object + type: array + x-kubernetes-list-map-keys: + - zone + x-kubernetes-list-type: map type: object required: - type @@ -48739,10 +49021,15 @@ spec: and LeastRequest load balancers. rule: 'self.type in [''Random'', ''ConsistentHash''] ? !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 ' + - message: PreferLocal zone-aware routing is not supported + for ConsistentHash load balancers. Use weightedZones + instead. + rule: 'self.type == ''ConsistentHash'' && has(self.zoneAware) + ? !has(self.zoneAware.preferLocal) : true' + - message: ZoneAware PreferLocal and WeightedZones cannot + be specified together. + rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) + && has(self.zoneAware.weightedZones)) : true' proxyProtocol: description: ProxyProtocol enables the Proxy Protocol when communicating with the backend. @@ -50098,6 +50385,36 @@ spec: minimum: 0 type: integer type: object + weightedZones: + description: |- + WeightedZones configures weight-based traffic distribution across locality zones. + Traffic is distributed proportionally based on the sum of all zone weights. + items: + description: WeightedZoneConfig defines + the weight for a specific locality zone. + properties: + weight: + description: |- + Weight defines the weight for this locality. + Higher values receive more traffic. The actual traffic distribution + is proportional to this value relative to other localities. + format: int32 + type: integer + zone: + description: |- + Zone specifies the topology zone this weight applies to. + The value should match the topology.kubernetes.io/zone label + of the nodes where endpoints are running. + Zones not listed in the configuration receive a default weight of 1. + type: string + required: + - weight + - zone + type: object + type: array + x-kubernetes-list-map-keys: + - zone + x-kubernetes-list-type: map type: object required: - type @@ -50111,11 +50428,15 @@ spec: for RoundRobin and LeastRequest load balancers. rule: 'self.type in [''Random'', ''ConsistentHash''] ? !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 ' + - message: PreferLocal zone-aware routing is not + supported for ConsistentHash load balancers. + Use weightedZones instead. + rule: 'self.type == ''ConsistentHash'' && has(self.zoneAware) + ? !has(self.zoneAware.preferLocal) : true' + - message: ZoneAware PreferLocal and WeightedZones + cannot be specified together. + rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) + && has(self.zoneAware.weightedZones)) : true' proxyProtocol: description: ProxyProtocol enables the Proxy Protocol when communicating with the backend. @@ -51520,6 +51841,36 @@ spec: minimum: 0 type: integer type: object + weightedZones: + description: |- + WeightedZones configures weight-based traffic distribution across locality zones. + Traffic is distributed proportionally based on the sum of all zone weights. + items: + description: WeightedZoneConfig defines the + weight for a specific locality zone. + properties: + weight: + description: |- + Weight defines the weight for this locality. + Higher values receive more traffic. The actual traffic distribution + is proportional to this value relative to other localities. + format: int32 + type: integer + zone: + description: |- + Zone specifies the topology zone this weight applies to. + The value should match the topology.kubernetes.io/zone label + of the nodes where endpoints are running. + Zones not listed in the configuration receive a default weight of 1. + type: string + required: + - weight + - zone + type: object + type: array + x-kubernetes-list-map-keys: + - zone + x-kubernetes-list-type: map type: object required: - type @@ -51533,10 +51884,15 @@ spec: and LeastRequest load balancers. rule: 'self.type in [''Random'', ''ConsistentHash''] ? !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 ' + - message: PreferLocal zone-aware routing is not supported + for ConsistentHash load balancers. Use weightedZones + instead. + rule: 'self.type == ''ConsistentHash'' && has(self.zoneAware) + ? !has(self.zoneAware.preferLocal) : true' + - message: ZoneAware PreferLocal and WeightedZones cannot + be specified together. + rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) + && has(self.zoneAware.weightedZones)) : true' proxyProtocol: description: ProxyProtocol enables the Proxy Protocol when communicating with the backend. diff --git a/test/helm/gateway-crds-helm/envoy-gateway-crds.out.yaml b/test/helm/gateway-crds-helm/envoy-gateway-crds.out.yaml index ea8e53af07..ba8d3a77c7 100644 --- a/test/helm/gateway-crds-helm/envoy-gateway-crds.out.yaml +++ b/test/helm/gateway-crds-helm/envoy-gateway-crds.out.yaml @@ -1427,6 +1427,36 @@ spec: minimum: 0 type: integer type: object + weightedZones: + description: |- + WeightedZones configures weight-based traffic distribution across locality zones. + Traffic is distributed proportionally based on the sum of all zone weights. + items: + description: WeightedZoneConfig defines the weight for a + specific locality zone. + properties: + weight: + description: |- + Weight defines the weight for this locality. + Higher values receive more traffic. The actual traffic distribution + is proportional to this value relative to other localities. + format: int32 + type: integer + zone: + description: |- + Zone specifies the topology zone this weight applies to. + The value should match the topology.kubernetes.io/zone label + of the nodes where endpoints are running. + Zones not listed in the configuration receive a default weight of 1. + type: string + required: + - weight + - zone + type: object + type: array + x-kubernetes-list-map-keys: + - zone + x-kubernetes-list-type: map type: object required: - type @@ -1440,10 +1470,14 @@ spec: LeastRequest load balancers. rule: 'self.type in [''Random'', ''ConsistentHash''] ? !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 ' + - message: PreferLocal zone-aware routing is not supported for ConsistentHash + load balancers. Use weightedZones instead. + rule: 'self.type == ''ConsistentHash'' && has(self.zoneAware) ? + !has(self.zoneAware.preferLocal) : true' + - message: ZoneAware PreferLocal and WeightedZones cannot be specified + together. + rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) && + has(self.zoneAware.weightedZones)) : true' mergeType: description: |- MergeType determines how this configuration is merged with existing BackendTrafficPolicy @@ -6388,6 +6422,36 @@ spec: minimum: 0 type: integer type: object + weightedZones: + description: |- + WeightedZones configures weight-based traffic distribution across locality zones. + Traffic is distributed proportionally based on the sum of all zone weights. + items: + description: WeightedZoneConfig defines the weight + for a specific locality zone. + properties: + weight: + description: |- + Weight defines the weight for this locality. + Higher values receive more traffic. The actual traffic distribution + is proportional to this value relative to other localities. + format: int32 + type: integer + zone: + description: |- + Zone specifies the topology zone this weight applies to. + The value should match the topology.kubernetes.io/zone label + of the nodes where endpoints are running. + Zones not listed in the configuration receive a default weight of 1. + type: string + required: + - weight + - zone + type: object + type: array + x-kubernetes-list-map-keys: + - zone + x-kubernetes-list-type: map type: object required: - type @@ -6401,10 +6465,15 @@ spec: and LeastRequest load balancers. rule: 'self.type in [''Random'', ''ConsistentHash''] ? !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 ' + - message: PreferLocal zone-aware routing is not supported + for ConsistentHash load balancers. Use weightedZones + instead. + rule: 'self.type == ''ConsistentHash'' && has(self.zoneAware) + ? !has(self.zoneAware.preferLocal) : true' + - message: ZoneAware PreferLocal and WeightedZones cannot + be specified together. + rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) + && has(self.zoneAware.weightedZones)) : true' proxyProtocol: description: ProxyProtocol enables the Proxy Protocol when communicating with the backend. @@ -20195,6 +20264,37 @@ spec: minimum: 0 type: integer type: object + weightedZones: + description: |- + WeightedZones configures weight-based traffic distribution across locality zones. + Traffic is distributed proportionally based on the sum of all zone weights. + items: + description: WeightedZoneConfig + defines the weight for a specific + locality zone. + properties: + weight: + description: |- + Weight defines the weight for this locality. + Higher values receive more traffic. The actual traffic distribution + is proportional to this value relative to other localities. + format: int32 + type: integer + zone: + description: |- + Zone specifies the topology zone this weight applies to. + The value should match the topology.kubernetes.io/zone label + of the nodes where endpoints are running. + Zones not listed in the configuration receive a default weight of 1. + type: string + required: + - weight + - zone + type: object + type: array + x-kubernetes-list-map-keys: + - zone + x-kubernetes-list-type: map type: object required: - type @@ -20209,11 +20309,18 @@ spec: load balancers. rule: 'self.type in [''Random'', ''ConsistentHash''] ? !has(self.slowStart) : true ' - - message: Currently ZoneAware is only - supported for LeastRequest, Random, - and RoundRobin load balancers. + - message: PreferLocal zone-aware routing + is not supported for ConsistentHash + load balancers. Use weightedZones + instead. rule: 'self.type == ''ConsistentHash'' - ? !has(self.zoneAware) : true ' + && has(self.zoneAware) ? !has(self.zoneAware.preferLocal) + : true' + - message: ZoneAware PreferLocal and WeightedZones + cannot be specified together. + rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) + && has(self.zoneAware.weightedZones)) + : true' proxyProtocol: description: ProxyProtocol enables the Proxy Protocol when communicating with @@ -21464,6 +21571,37 @@ spec: minimum: 0 type: integer type: object + weightedZones: + description: |- + WeightedZones configures weight-based traffic distribution across locality zones. + Traffic is distributed proportionally based on the sum of all zone weights. + items: + description: WeightedZoneConfig + defines the weight for a specific + locality zone. + properties: + weight: + description: |- + Weight defines the weight for this locality. + Higher values receive more traffic. The actual traffic distribution + is proportional to this value relative to other localities. + format: int32 + type: integer + zone: + description: |- + Zone specifies the topology zone this weight applies to. + The value should match the topology.kubernetes.io/zone label + of the nodes where endpoints are running. + Zones not listed in the configuration receive a default weight of 1. + type: string + required: + - weight + - zone + type: object + type: array + x-kubernetes-list-map-keys: + - zone + x-kubernetes-list-type: map type: object required: - type @@ -21478,11 +21616,18 @@ spec: load balancers. rule: 'self.type in [''Random'', ''ConsistentHash''] ? !has(self.slowStart) : true ' - - message: Currently ZoneAware is only - supported for LeastRequest, Random, - and RoundRobin load balancers. + - message: PreferLocal zone-aware routing + is not supported for ConsistentHash + load balancers. Use weightedZones + instead. rule: 'self.type == ''ConsistentHash'' - ? !has(self.zoneAware) : true ' + && has(self.zoneAware) ? !has(self.zoneAware.preferLocal) + : true' + - message: ZoneAware PreferLocal and WeightedZones + cannot be specified together. + rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) + && has(self.zoneAware.weightedZones)) + : true' proxyProtocol: description: ProxyProtocol enables the Proxy Protocol when communicating with @@ -22881,6 +23026,37 @@ spec: minimum: 0 type: integer type: object + weightedZones: + description: |- + WeightedZones configures weight-based traffic distribution across locality zones. + Traffic is distributed proportionally based on the sum of all zone weights. + items: + description: WeightedZoneConfig defines + the weight for a specific locality + zone. + properties: + weight: + description: |- + Weight defines the weight for this locality. + Higher values receive more traffic. The actual traffic distribution + is proportional to this value relative to other localities. + format: int32 + type: integer + zone: + description: |- + Zone specifies the topology zone this weight applies to. + The value should match the topology.kubernetes.io/zone label + of the nodes where endpoints are running. + Zones not listed in the configuration receive a default weight of 1. + type: string + required: + - weight + - zone + type: object + type: array + x-kubernetes-list-map-keys: + - zone + x-kubernetes-list-type: map type: object required: - type @@ -22894,11 +23070,17 @@ spec: for RoundRobin and LeastRequest load balancers. rule: 'self.type in [''Random'', ''ConsistentHash''] ? !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 ' + - message: PreferLocal zone-aware routing is + not supported for ConsistentHash load balancers. + Use weightedZones instead. + rule: 'self.type == ''ConsistentHash'' && + has(self.zoneAware) ? !has(self.zoneAware.preferLocal) + : true' + - message: ZoneAware PreferLocal and WeightedZones + cannot be specified together. + rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) + && has(self.zoneAware.weightedZones)) : + true' proxyProtocol: description: ProxyProtocol enables the Proxy Protocol when communicating with the backend. @@ -24218,6 +24400,36 @@ spec: minimum: 0 type: integer type: object + weightedZones: + description: |- + WeightedZones configures weight-based traffic distribution across locality zones. + Traffic is distributed proportionally based on the sum of all zone weights. + items: + description: WeightedZoneConfig defines + the weight for a specific locality zone. + properties: + weight: + description: |- + Weight defines the weight for this locality. + Higher values receive more traffic. The actual traffic distribution + is proportional to this value relative to other localities. + format: int32 + type: integer + zone: + description: |- + Zone specifies the topology zone this weight applies to. + The value should match the topology.kubernetes.io/zone label + of the nodes where endpoints are running. + Zones not listed in the configuration receive a default weight of 1. + type: string + required: + - weight + - zone + type: object + type: array + x-kubernetes-list-map-keys: + - zone + x-kubernetes-list-type: map type: object required: - type @@ -24231,10 +24443,15 @@ spec: RoundRobin and LeastRequest load balancers. rule: 'self.type in [''Random'', ''ConsistentHash''] ? !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 ' + - message: PreferLocal zone-aware routing is not supported + for ConsistentHash load balancers. Use weightedZones + instead. + rule: 'self.type == ''ConsistentHash'' && has(self.zoneAware) + ? !has(self.zoneAware.preferLocal) : true' + - message: ZoneAware PreferLocal and WeightedZones + cannot be specified together. + rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) + && has(self.zoneAware.weightedZones)) : true' proxyProtocol: description: ProxyProtocol enables the Proxy Protocol when communicating with the backend. @@ -26899,6 +27116,36 @@ spec: minimum: 0 type: integer type: object + weightedZones: + description: |- + WeightedZones configures weight-based traffic distribution across locality zones. + Traffic is distributed proportionally based on the sum of all zone weights. + items: + description: WeightedZoneConfig defines the + weight for a specific locality zone. + properties: + weight: + description: |- + Weight defines the weight for this locality. + Higher values receive more traffic. The actual traffic distribution + is proportional to this value relative to other localities. + format: int32 + type: integer + zone: + description: |- + Zone specifies the topology zone this weight applies to. + The value should match the topology.kubernetes.io/zone label + of the nodes where endpoints are running. + Zones not listed in the configuration receive a default weight of 1. + type: string + required: + - weight + - zone + type: object + type: array + x-kubernetes-list-map-keys: + - zone + x-kubernetes-list-type: map type: object required: - type @@ -26912,10 +27159,15 @@ spec: and LeastRequest load balancers. rule: 'self.type in [''Random'', ''ConsistentHash''] ? !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 ' + - message: PreferLocal zone-aware routing is not supported + for ConsistentHash load balancers. Use weightedZones + instead. + rule: 'self.type == ''ConsistentHash'' && has(self.zoneAware) + ? !has(self.zoneAware.preferLocal) : true' + - message: ZoneAware PreferLocal and WeightedZones cannot + be specified together. + rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) + && has(self.zoneAware.weightedZones)) : true' proxyProtocol: description: ProxyProtocol enables the Proxy Protocol when communicating with the backend. @@ -28056,6 +28308,36 @@ spec: minimum: 0 type: integer type: object + weightedZones: + description: |- + WeightedZones configures weight-based traffic distribution across locality zones. + Traffic is distributed proportionally based on the sum of all zone weights. + items: + description: WeightedZoneConfig defines the + weight for a specific locality zone. + properties: + weight: + description: |- + Weight defines the weight for this locality. + Higher values receive more traffic. The actual traffic distribution + is proportional to this value relative to other localities. + format: int32 + type: integer + zone: + description: |- + Zone specifies the topology zone this weight applies to. + The value should match the topology.kubernetes.io/zone label + of the nodes where endpoints are running. + Zones not listed in the configuration receive a default weight of 1. + type: string + required: + - weight + - zone + type: object + type: array + x-kubernetes-list-map-keys: + - zone + x-kubernetes-list-type: map type: object required: - type @@ -28069,10 +28351,15 @@ spec: and LeastRequest load balancers. rule: 'self.type in [''Random'', ''ConsistentHash''] ? !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 ' + - message: PreferLocal zone-aware routing is not supported + for ConsistentHash load balancers. Use weightedZones + instead. + rule: 'self.type == ''ConsistentHash'' && has(self.zoneAware) + ? !has(self.zoneAware.preferLocal) : true' + - message: ZoneAware PreferLocal and WeightedZones cannot + be specified together. + rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) + && has(self.zoneAware.weightedZones)) : true' proxyProtocol: description: ProxyProtocol enables the Proxy Protocol when communicating with the backend. @@ -29428,6 +29715,36 @@ spec: minimum: 0 type: integer type: object + weightedZones: + description: |- + WeightedZones configures weight-based traffic distribution across locality zones. + Traffic is distributed proportionally based on the sum of all zone weights. + items: + description: WeightedZoneConfig defines + the weight for a specific locality zone. + properties: + weight: + description: |- + Weight defines the weight for this locality. + Higher values receive more traffic. The actual traffic distribution + is proportional to this value relative to other localities. + format: int32 + type: integer + zone: + description: |- + Zone specifies the topology zone this weight applies to. + The value should match the topology.kubernetes.io/zone label + of the nodes where endpoints are running. + Zones not listed in the configuration receive a default weight of 1. + type: string + required: + - weight + - zone + type: object + type: array + x-kubernetes-list-map-keys: + - zone + x-kubernetes-list-type: map type: object required: - type @@ -29441,11 +29758,15 @@ spec: for RoundRobin and LeastRequest load balancers. rule: 'self.type in [''Random'', ''ConsistentHash''] ? !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 ' + - message: PreferLocal zone-aware routing is not + supported for ConsistentHash load balancers. + Use weightedZones instead. + rule: 'self.type == ''ConsistentHash'' && has(self.zoneAware) + ? !has(self.zoneAware.preferLocal) : true' + - message: ZoneAware PreferLocal and WeightedZones + cannot be specified together. + rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) + && has(self.zoneAware.weightedZones)) : true' proxyProtocol: description: ProxyProtocol enables the Proxy Protocol when communicating with the backend. @@ -30850,6 +31171,36 @@ spec: minimum: 0 type: integer type: object + weightedZones: + description: |- + WeightedZones configures weight-based traffic distribution across locality zones. + Traffic is distributed proportionally based on the sum of all zone weights. + items: + description: WeightedZoneConfig defines the + weight for a specific locality zone. + properties: + weight: + description: |- + Weight defines the weight for this locality. + Higher values receive more traffic. The actual traffic distribution + is proportional to this value relative to other localities. + format: int32 + type: integer + zone: + description: |- + Zone specifies the topology zone this weight applies to. + The value should match the topology.kubernetes.io/zone label + of the nodes where endpoints are running. + Zones not listed in the configuration receive a default weight of 1. + type: string + required: + - weight + - zone + type: object + type: array + x-kubernetes-list-map-keys: + - zone + x-kubernetes-list-type: map type: object required: - type @@ -30863,10 +31214,15 @@ spec: and LeastRequest load balancers. rule: 'self.type in [''Random'', ''ConsistentHash''] ? !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 ' + - message: PreferLocal zone-aware routing is not supported + for ConsistentHash load balancers. Use weightedZones + instead. + rule: 'self.type == ''ConsistentHash'' && has(self.zoneAware) + ? !has(self.zoneAware.preferLocal) : true' + - message: ZoneAware PreferLocal and WeightedZones cannot + be specified together. + rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) + && has(self.zoneAware.weightedZones)) : true' proxyProtocol: description: ProxyProtocol enables the Proxy Protocol when communicating with the backend.