Skip to content

Commit 912649a

Browse files
committed
add all load balancing methods
1 parent 9863bd1 commit 912649a

29 files changed

+1119
-32
lines changed

apis/v1alpha1/upstreamsettingspolicy_types.go

Lines changed: 101 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ type UpstreamSettingsPolicyList struct {
3636
}
3737

3838
// UpstreamSettingsPolicySpec defines the desired state of the UpstreamSettingsPolicy.
39+
// +kubebuilder:validation:XValidation:rule="!(has(self.loadBalancingMethod) && (self.loadBalancingMethod == 'hash' || self.loadBalancingMethod == 'hash consistent')) || has(self.hashKey)",message="hashKey is required when loadBalancingMethod is 'hash' or 'hash consistent'"
40+
//
41+
//nolint:lll
3942
type UpstreamSettingsPolicySpec struct {
4043
// ZoneSize is the size of the shared memory zone used by the upstream. This memory zone is used to share
4144
// the upstream configuration between nginx worker processes. The more servers that an upstream has,
@@ -58,6 +61,12 @@ type UpstreamSettingsPolicySpec struct {
5861
// +optional
5962
LoadBalancingMethod *LoadBalancingType `json:"loadBalancingMethod,omitempty"`
6063

64+
// HashKey defines the key used for hash-based load balancing methods.
65+
// This field is required when `LoadBalancingMethod` is set to `hash` or `hash consistent`.
66+
//
67+
// +optional
68+
HashKey *HashMethodKey `json:"hashKey,omitempty"`
69+
6170
// TargetRefs identifies API object(s) to apply the policy to.
6271
// Objects must be in the same namespace as the policy.
6372
// Support: Service
@@ -108,19 +117,107 @@ type UpstreamKeepAlive struct {
108117

109118
// LoadBalancingType defines the supported load balancing methods.
110119
//
111-
// +kubebuilder:validation:Enum=ip_hash;random two least_conn
120+
// +kubebuilder:validation:Enum=round_robin;least_conn;ip_hash;hash;hash consistent;random;random two;random two least_conn;random two least_time;random two least_time=header;random two least_time=last_byte;least_time;least_time header;least_time last_byte;least_time header inflight;least_time last_byte inflight
121+
//
122+
//nolint:lll
112123
type LoadBalancingType string
113124

114125
const (
126+
// Combination of NGINX directive
127+
// - https://nginx.org/en/docs/http/ngx_http_upstream_module.html#random
128+
// - https://nginx.org/en/docs/http/ngx_http_upstream_module.html#least_conn
129+
// - https://nginx.org/en/docs/http/ngx_http_upstream_module.html#least_time
130+
// - https://nginx.org/en/docs/http/ngx_http_upstream_module.html#upstream
131+
// - https://nginx.org/en/docs/http/ngx_http_upstream_module.html#ip_hash
132+
// - https://nginx.org/en/docs/http/ngx_http_upstream_module.html#hash
133+
134+
// LoadBalancingMethods for NGINX OSS.
135+
136+
// LoadBalancingTypeRoundRobin enables round-robin load balancing,
137+
// distributing requests evenly across all upstream servers.
138+
// NGINX defaults to this method if no load balancing method is specified.
139+
LoadBalancingTypeRoundRobin LoadBalancingType = "round_robin"
140+
141+
// LoadBalancingTypeLeastConn enables least-connections load balancing,
142+
// routing requests to the upstream server with the fewest active connections.
143+
LoadBalancingTypeLeastConnection LoadBalancingType = "least_conn"
144+
115145
// LoadBalancingTypeIPHash enables IP hash-based load balancing,
116146
// ensuring requests from the same client IP are routed to the same upstream server.
117-
// NGINX directive: https://nginx.org/en/docs/http/ngx_http_upstream_module.html#ip_hash
118147
LoadBalancingTypeIPHash LoadBalancingType = "ip_hash"
119148

149+
// LoadBalancingTypeHash enables generic hash-based load balancing,
150+
// routing requests to upstream servers based on a hash of a specified key
151+
// HashKey field must be set when this method is selected.
152+
// Example configuration: hash $binary_remote_addr;.
153+
LoadBalancingTypeHash LoadBalancingType = "hash"
154+
155+
// LoadBalancingTypeHashConsistent enables consistent hash-based load balancing,
156+
// which minimizes the number of keys remapped when a server is added or removed.
157+
// HashKey field must be set when this method is selected.
158+
// Example configuration: hash $binary_remote_addr consistent;.
159+
LoadBalancingTypeHashConsistent LoadBalancingType = "hash consistent"
160+
161+
// LoadBalancingTypeRandom enables random load balancing,
162+
// routing requests to upstream servers in a random manner.
163+
LoadBalancingTypeRandom LoadBalancingType = "random"
164+
165+
// LoadBalancingTypeRandomTwo enables a variation of random load balancing
166+
// that randomly selects two servers and forwards traffic to one of them.
167+
// The default method is least_conn which passes a request to a server with the least number of active connections.
168+
LoadBalancingTypeRandomTwo LoadBalancingType = "random two"
169+
120170
// LoadBalancingTypeRandomTwoLeastConnection enables a variation of least-connections
121171
// balancing that randomly selects two servers and forwards traffic to the one with
122172
// fewer active connections.
123-
// NGINX directive least_conn: https://nginx.org/en/docs/http/ngx_http_upstream_module.html#least_conn
124-
// NGINX directive random: https://nginx.org/en/docs/http/ngx_http_upstream_module.html#random
125173
LoadBalancingTypeRandomTwoLeastConnection LoadBalancingType = "random two least_conn"
174+
175+
// LoadBalancingMethods for NGINX Plus along with OSS methods.
176+
177+
// LoadBalancingTypeRandomTwoLeastTime enables a variation of least-time load balancing
178+
// that randomly selects two servers and forwards traffic to the one with the
179+
// least average response time, and least number of active connections.
180+
LoadBalancingTypeRandomTwoLeastTime LoadBalancingType = "random two least_time"
181+
182+
// LoadBalancingTypeRandomTwoLeastTimeHeader enables a variation of least-time load balancing
183+
// that randomly selects two servers and forwards traffic to the one with the least
184+
// time to receive the response header.
185+
LoadBalancingTypeRandomTwoLeastTimeHeader LoadBalancingType = "random two least_time=header"
186+
187+
// LoadBalancingTypeRandomTwoLeastTimeLastByte enables a variation of least-time load balancing
188+
// that randomly selects two servers and forwards traffic to the one with the least time
189+
// to receive the full response.
190+
LoadBalancingTypeRandomTwoLeastTimeLastByte LoadBalancingType = "random two least_time=last_byte"
191+
192+
// LoadBalancingTypeLeastTime enables least-time load balancing,
193+
// routing requests to the upstream server with the least average response time,
194+
// and least number of active connections.
195+
LoadBalancingTypeLeastTime LoadBalancingType = "least_time"
196+
197+
// LoadBalancingTypeLeastTimeHeader enables least-time load balancing,
198+
// routing requests to the upstream server with the least time to receive the response header.
199+
LoadBalancingTypeLeastTimeHeader LoadBalancingType = "least_time header"
200+
201+
// LoadBalancingTypeLeastTimeLastByte enables least-time load balancing,
202+
// routing requests to the upstream server with the least time to receive the full response.
203+
LoadBalancingTypeLeastTimeLastByte LoadBalancingType = "least_time last_byte"
204+
205+
// LoadBalancingTypeLeastTimeHeaderInflight enables least-time load balancing,
206+
// routing requests to the upstream server with the least time to receive the response header,
207+
// considering the incomplete requests.
208+
LoadBalancingTypeLeastTimeHeaderInflight LoadBalancingType = "least_time header inflight"
209+
210+
// LoadBalancingTypeLeastTimeLastByteInflight enables least-time load balancing,
211+
// routing requests to the upstream server with the least time to receive the full response,
212+
// considering the incomplete requests.
213+
LoadBalancingTypeLeastTimeLastByteInflight LoadBalancingType = "least_time last_byte inflight"
126214
)
215+
216+
// HashMethodKey defines the key used for hash-based load balancing methods.
217+
// The key must be a valid NGINX variable name starting with '$' followed by lowercase
218+
// letters and underscores only.
219+
// For a full list of NGINX variables,
220+
// refer to: https://nginx.org/en/docs/http/ngx_http_upstream_module.html#variables
221+
//
222+
// +kubebuilder:validation:Pattern=`^\$[a-z_]+$`
223+
type HashMethodKey string

apis/v1alpha1/zz_generated.deepcopy.go

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

config/crd/bases/gateway.nginx.org_upstreamsettingspolicies.yaml

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,12 @@ spec:
5151
spec:
5252
description: Spec defines the desired state of the UpstreamSettingsPolicy.
5353
properties:
54+
hashKey:
55+
description: |-
56+
HashKey defines the key used for hash-based load balancing methods.
57+
This field is required when `LoadBalancingMethod` is set to `hash` or `hash consistent`.
58+
pattern: ^\$[a-z_]+$
59+
type: string
5460
keepAlive:
5561
description: KeepAlive defines the keep-alive settings.
5662
properties:
@@ -91,8 +97,22 @@ spec:
9197
If not specified, NGINX Gateway Fabric defaults to `random two least_conn`,
9298
which differs from the standard NGINX default `round-robin`.
9399
enum:
100+
- round_robin
101+
- least_conn
94102
- ip_hash
103+
- hash
104+
- hash consistent
105+
- random
106+
- random two
95107
- random two least_conn
108+
- random two least_time
109+
- random two least_time=header
110+
- random two least_time=last_byte
111+
- least_time
112+
- least_time header
113+
- least_time last_byte
114+
- least_time header inflight
115+
- least_time last_byte inflight
96116
type: string
97117
targetRefs:
98118
description: |-
@@ -152,6 +172,12 @@ spec:
152172
required:
153173
- targetRefs
154174
type: object
175+
x-kubernetes-validations:
176+
- message: hashKey is required when loadBalancingMethod is 'hash' or 'hash
177+
consistent'
178+
rule: '!(has(self.loadBalancingMethod) && (self.loadBalancingMethod
179+
== ''hash'' || self.loadBalancingMethod == ''hash consistent'')) ||
180+
has(self.hashKey)'
155181
status:
156182
description: Status defines the state of the UpstreamSettingsPolicy.
157183
properties:

deploy/crds.yaml

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9578,6 +9578,12 @@ spec:
95789578
spec:
95799579
description: Spec defines the desired state of the UpstreamSettingsPolicy.
95809580
properties:
9581+
hashKey:
9582+
description: |-
9583+
HashKey defines the key used for hash-based load balancing methods.
9584+
This field is required when `LoadBalancingMethod` is set to `hash` or `hash consistent`.
9585+
pattern: ^\$[a-z_]+$
9586+
type: string
95819587
keepAlive:
95829588
description: KeepAlive defines the keep-alive settings.
95839589
properties:
@@ -9618,8 +9624,22 @@ spec:
96189624
If not specified, NGINX Gateway Fabric defaults to `random two least_conn`,
96199625
which differs from the standard NGINX default `round-robin`.
96209626
enum:
9627+
- round_robin
9628+
- least_conn
96219629
- ip_hash
9630+
- hash
9631+
- hash consistent
9632+
- random
9633+
- random two
96229634
- random two least_conn
9635+
- random two least_time
9636+
- random two least_time=header
9637+
- random two least_time=last_byte
9638+
- least_time
9639+
- least_time header
9640+
- least_time last_byte
9641+
- least_time header inflight
9642+
- least_time last_byte inflight
96239643
type: string
96249644
targetRefs:
96259645
description: |-
@@ -9679,6 +9699,12 @@ spec:
96799699
required:
96809700
- targetRefs
96819701
type: object
9702+
x-kubernetes-validations:
9703+
- message: hashKey is required when loadBalancingMethod is 'hash' or 'hash
9704+
consistent'
9705+
rule: '!(has(self.loadBalancingMethod) && (self.loadBalancingMethod
9706+
== ''hash'' || self.loadBalancingMethod == ''hash consistent'')) ||
9707+
has(self.hashKey)'
96829708
status:
96839709
description: Status defines the state of the UpstreamSettingsPolicy.
96849710
properties:

internal/controller/manager.go

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,11 @@ func StartManager(cfg config.Config) error {
131131
return err
132132
}
133133

134+
flags := graph.Flags{
135+
Plus: cfg.Plus,
136+
Experimental: cfg.ExperimentalFeatures,
137+
}
138+
134139
processor := state.NewChangeProcessorImpl(state.ChangeProcessorConfig{
135140
GatewayCtlrName: cfg.GatewayCtlrName,
136141
GatewayClassName: cfg.GatewayClassName,
@@ -140,10 +145,10 @@ func StartManager(cfg config.Config) error {
140145
GenericValidator: genericValidator,
141146
PolicyValidator: policyManager,
142147
},
143-
EventRecorder: recorder,
144-
MustExtractGVK: mustExtractGVK,
145-
PlusSecrets: plusSecrets,
146-
ExperimentalFeatures: cfg.ExperimentalFeatures,
148+
EventRecorder: recorder,
149+
MustExtractGVK: mustExtractGVK,
150+
PlusSecrets: plusSecrets,
151+
Flags: flags,
147152
})
148153

149154
var handlerCollector handlerMetricsCollector = collectors.NewControllerNoopCollector()

internal/controller/nginx/config/http/config.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package http
22

33
import (
4+
ngfAPI "github.com/nginx/nginx-gateway-fabric/v2/apis/v1alpha1"
45
"github.com/nginx/nginx-gateway-fabric/v2/internal/controller/nginx/config/shared"
56
)
67

@@ -123,6 +124,7 @@ type Upstream struct {
123124
ZoneSize string // format: 512k, 1m
124125
StateFile string
125126
LoadBalancingMethod string
127+
HashKey string
126128
KeepAlive UpstreamKeepAlive
127129
Servers []UpstreamServer
128130
}
@@ -167,3 +169,35 @@ type ServerConfig struct {
167169
Plus bool
168170
DisableSNIHostValidation bool
169171
}
172+
173+
var (
174+
PlusAllowedLBMethods = map[ngfAPI.LoadBalancingType]struct{}{
175+
ngfAPI.LoadBalancingTypeRoundRobin: {},
176+
ngfAPI.LoadBalancingTypeLeastConnection: {},
177+
ngfAPI.LoadBalancingTypeIPHash: {},
178+
ngfAPI.LoadBalancingTypeRandom: {},
179+
ngfAPI.LoadBalancingTypeHash: {},
180+
ngfAPI.LoadBalancingTypeHashConsistent: {},
181+
ngfAPI.LoadBalancingTypeRandomTwo: {},
182+
ngfAPI.LoadBalancingTypeRandomTwoLeastConnection: {},
183+
ngfAPI.LoadBalancingTypeLeastTime: {},
184+
ngfAPI.LoadBalancingTypeLeastTimeHeader: {},
185+
ngfAPI.LoadBalancingTypeLeastTimeLastByte: {},
186+
ngfAPI.LoadBalancingTypeLeastTimeHeaderInflight: {},
187+
ngfAPI.LoadBalancingTypeLeastTimeLastByteInflight: {},
188+
ngfAPI.LoadBalancingTypeRandomTwoLeastTime: {},
189+
ngfAPI.LoadBalancingTypeRandomTwoLeastTimeHeader: {},
190+
ngfAPI.LoadBalancingTypeRandomTwoLeastTimeLastByte: {},
191+
}
192+
193+
OSSAllowedLBMethods = map[ngfAPI.LoadBalancingType]struct{}{
194+
ngfAPI.LoadBalancingTypeRoundRobin: {},
195+
ngfAPI.LoadBalancingTypeLeastConnection: {},
196+
ngfAPI.LoadBalancingTypeIPHash: {},
197+
ngfAPI.LoadBalancingTypeRandom: {},
198+
ngfAPI.LoadBalancingTypeHash: {},
199+
ngfAPI.LoadBalancingTypeHashConsistent: {},
200+
ngfAPI.LoadBalancingTypeRandomTwo: {},
201+
ngfAPI.LoadBalancingTypeRandomTwoLeastConnection: {},
202+
}
203+
)

internal/controller/nginx/config/policies/clientsettings/validator.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,14 @@ func (v *Validator) ValidateGlobalSettings(
5050
return nil
5151
}
5252

53+
// ValidateLoadBalancingMethod validates the load balancing method for upstream servers.
54+
func (v *Validator) ValidateLoadBalancingMethod(
55+
_ policies.Policy,
56+
_ bool,
57+
) []conditions.Condition {
58+
return nil
59+
}
60+
5361
// Conflicts returns true if the two ClientSettingsPolicies conflict.
5462
func (v *Validator) Conflicts(polA, polB policies.Policy) bool {
5563
cspA := helpers.MustCastObject[*ngfAPI.ClientSettingsPolicy](polA)

internal/controller/nginx/config/policies/observability/validator.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,3 +141,11 @@ func (v *Validator) validateSettings(spec ngfAPIv1alpha2.ObservabilityPolicySpec
141141

142142
return allErrs.ToAggregate()
143143
}
144+
145+
// ValidateLoadBalancingMethod validates the load balancing method for upstream servers.
146+
func (v *Validator) ValidateLoadBalancingMethod(
147+
_ policies.Policy,
148+
_ bool,
149+
) []conditions.Condition {
150+
return nil
151+
}

0 commit comments

Comments
 (0)