Skip to content

Commit ff3ad8e

Browse files
committed
add support for ip_hash lb method
1 parent 2d2539b commit ff3ad8e

File tree

8 files changed

+190
-32
lines changed

8 files changed

+190
-32
lines changed

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

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -119,11 +119,12 @@ const (
119119

120120
// Upstream holds all configuration for an HTTP upstream.
121121
type Upstream struct {
122-
Name string
123-
ZoneSize string // format: 512k, 1m
124-
StateFile string
125-
KeepAlive UpstreamKeepAlive
126-
Servers []UpstreamServer
122+
Name string
123+
ZoneSize string // format: 512k, 1m
124+
StateFile string
125+
KeepAlive UpstreamKeepAlive
126+
LoadBalancingMethod string
127+
Servers []UpstreamServer
127128
}
128129

129130
// UpstreamKeepAlive holds the keepalive configuration for an HTTP upstream.

internal/controller/nginx/config/policies/upstreamsettings/processor.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ type Processor struct{}
1313
type UpstreamSettings struct {
1414
// ZoneSize is the zone size setting.
1515
ZoneSize string
16+
// LoadBalancingMethod is the load balancing method setting.
17+
LoadBalancingMethod string
1618
// KeepAlive contains the keepalive settings.
1719
KeepAlive http.UpstreamKeepAlive
1820
}
@@ -61,6 +63,10 @@ func processPolicies(pols []policies.Policy) UpstreamSettings {
6163
upstreamSettings.KeepAlive.Timeout = string(*usp.Spec.KeepAlive.Timeout)
6264
}
6365
}
66+
67+
if usp.Spec.LoadBalancingMethod != nil {
68+
upstreamSettings.LoadBalancingMethod = string(*usp.Spec.LoadBalancingMethod)
69+
}
6470
}
6571

6672
return upstreamSettings

internal/controller/nginx/config/policies/upstreamsettings/processor_test.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ func TestProcess(t *testing.T) {
3737
Time: helpers.GetPointer[ngfAPIv1alpha1.Duration]("5s"),
3838
Timeout: helpers.GetPointer[ngfAPIv1alpha1.Duration]("10s"),
3939
}),
40+
LoadBalancingMethod: helpers.GetPointer(ngfAPIv1alpha1.LoadBalancingTypeIPHash),
4041
},
4142
},
4243
},
@@ -48,6 +49,24 @@ func TestProcess(t *testing.T) {
4849
Time: "5s",
4950
Timeout: "10s",
5051
},
52+
LoadBalancingMethod: string(ngfAPIv1alpha1.LoadBalancingTypeIPHash),
53+
},
54+
},
55+
{
56+
name: "load balancing method set",
57+
policies: []policies.Policy{
58+
&ngfAPIv1alpha1.UpstreamSettingsPolicy{
59+
ObjectMeta: metav1.ObjectMeta{
60+
Name: "usp",
61+
Namespace: "test",
62+
},
63+
Spec: ngfAPIv1alpha1.UpstreamSettingsPolicySpec{
64+
LoadBalancingMethod: helpers.GetPointer(ngfAPIv1alpha1.LoadBalancingTypeRandomTwoLeastConnection),
65+
},
66+
},
67+
},
68+
expUpstreamSettings: UpstreamSettings{
69+
LoadBalancingMethod: string(ngfAPIv1alpha1.LoadBalancingTypeRandomTwoLeastConnection),
5170
},
5271
},
5372
{
@@ -220,6 +239,15 @@ func TestProcess(t *testing.T) {
220239
}),
221240
},
222241
},
242+
&ngfAPIv1alpha1.UpstreamSettingsPolicy{
243+
ObjectMeta: metav1.ObjectMeta{
244+
Name: "usp-loadBalancingMethod",
245+
Namespace: "test",
246+
},
247+
Spec: ngfAPIv1alpha1.UpstreamSettingsPolicySpec{
248+
LoadBalancingMethod: helpers.GetPointer(ngfAPIv1alpha1.LoadBalancingTypeIPHash),
249+
},
250+
},
223251
},
224252
expUpstreamSettings: UpstreamSettings{
225253
ZoneSize: "2m",
@@ -229,6 +257,7 @@ func TestProcess(t *testing.T) {
229257
Time: "5s",
230258
Timeout: "10s",
231259
},
260+
LoadBalancingMethod: string(ngfAPIv1alpha1.LoadBalancingTypeIPHash),
232261
},
233262
},
234263
{

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

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,10 @@ func conflicts(a, b ngfAPI.UpstreamSettingsPolicySpec) bool {
8383
}
8484
}
8585

86+
if a.LoadBalancingMethod != nil && b.LoadBalancingMethod != nil {
87+
return true
88+
}
89+
8690
return false
8791
}
8892

@@ -103,6 +107,11 @@ func (v Validator) validateSettings(spec ngfAPI.UpstreamSettingsPolicySpec) erro
103107
allErrs = append(allErrs, v.validateUpstreamKeepAlive(*spec.KeepAlive, fieldPath.Child("keepAlive"))...)
104108
}
105109

110+
allErrs = append(
111+
allErrs,
112+
v.validateLoadBalancingMethod(*spec.LoadBalancingMethod, fieldPath.Child("loadBalancingMethod"))...,
113+
)
114+
106115
return allErrs.ToAggregate()
107116
}
108117

@@ -130,3 +139,25 @@ func (v Validator) validateUpstreamKeepAlive(
130139

131140
return allErrs
132141
}
142+
143+
func (v Validator) validateLoadBalancingMethod(
144+
method ngfAPI.LoadBalancingType,
145+
fieldPath *field.Path,
146+
) field.ErrorList {
147+
var allErrs field.ErrorList
148+
149+
switch method {
150+
case ngfAPI.LoadBalancingTypeIPHash, ngfAPI.LoadBalancingTypeRandomTwoLeastConnection:
151+
default:
152+
allErrs = append(allErrs, field.NotSupported(
153+
fieldPath,
154+
method,
155+
[]string{
156+
string(ngfAPI.LoadBalancingTypeIPHash),
157+
string(ngfAPI.LoadBalancingTypeRandomTwoLeastConnection),
158+
},
159+
))
160+
}
161+
162+
return allErrs
163+
}

internal/controller/nginx/config/policies/upstreamsettings/validator_test.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ func createValidPolicy() *ngfAPI.UpstreamSettingsPolicy {
3838
Timeout: helpers.GetPointer[ngfAPI.Duration]("30s"),
3939
Connections: helpers.GetPointer[int32](100),
4040
},
41+
LoadBalancingMethod: helpers.GetPointer(ngfAPI.LoadBalancingTypeRandomTwoLeastConnection),
4142
},
4243
Status: v1.PolicyStatus{},
4344
}
@@ -117,6 +118,17 @@ func TestValidator_Validate(t *testing.T) {
117118
"'must contain an, at most, four digit number followed by 'ms', 's', 'm', or 'h'')]"),
118119
},
119120
},
121+
{
122+
name: "invalid load balancing method",
123+
policy: createModifiedPolicy(func(p *ngfAPI.UpstreamSettingsPolicy) *ngfAPI.UpstreamSettingsPolicy {
124+
p.Spec.LoadBalancingMethod = helpers.GetPointer[ngfAPI.LoadBalancingType]("invalid-lb-method")
125+
return p
126+
}),
127+
expConditions: []conditions.Condition{
128+
conditions.NewPolicyInvalid("spec.loadBalancingMethod: Unsupported value: \"invalid-lb-method\": " +
129+
"supported values: \"ip_hash\", \"random two least_conn\""),
130+
},
131+
},
120132
{
121133
name: "valid",
122134
policy: createValidPolicy(),
@@ -246,6 +258,16 @@ func TestValidator_Conflicts(t *testing.T) {
246258
},
247259
conflicts: true,
248260
},
261+
{
262+
name: "load balancing method conflicts",
263+
polA: createValidPolicy(),
264+
polB: &ngfAPI.UpstreamSettingsPolicy{
265+
Spec: ngfAPI.UpstreamSettingsPolicySpec{
266+
LoadBalancingMethod: helpers.GetPointer(ngfAPI.LoadBalancingTypeIPHash),
267+
},
268+
},
269+
conflicts: true,
270+
},
249271
}
250272

251273
v := upstreamsettings.NewValidator(nil)

internal/controller/nginx/config/upstreams.go

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ const (
3232
plusZoneSizeStream = "1m"
3333
// stateDir is the directory for storing state files.
3434
stateDir = "/var/lib/nginx/state"
35+
// default load balancing method.
36+
randomTwoLeastConnLB = "random two least_conn"
3537
)
3638

3739
// keepAliveChecker takes an upstream name and returns if it has keep alive settings enabled.
@@ -185,12 +187,18 @@ func (g GeneratorImpl) createUpstream(
185187
}
186188
}
187189

190+
chosenLBMethod := randomTwoLeastConnLB
191+
if upstreamPolicySettings.LoadBalancingMethod != "" {
192+
chosenLBMethod = upstreamPolicySettings.LoadBalancingMethod
193+
}
194+
188195
return http.Upstream{
189-
Name: up.Name,
190-
ZoneSize: zoneSize,
191-
StateFile: stateFile,
192-
Servers: upstreamServers,
193-
KeepAlive: upstreamPolicySettings.KeepAlive,
196+
Name: up.Name,
197+
ZoneSize: zoneSize,
198+
StateFile: stateFile,
199+
Servers: upstreamServers,
200+
KeepAlive: upstreamPolicySettings.KeepAlive,
201+
LoadBalancingMethod: chosenLBMethod,
194202
}
195203
}
196204

internal/controller/nginx/config/upstreams_template.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@ package config
1010
const upstreamsTemplateText = `
1111
{{ range $u := . }}
1212
upstream {{ $u.Name }} {
13-
random two least_conn;
13+
{{ if $u.LoadBalancingMethod -}}
14+
{{ $u.LoadBalancingMethod }};
15+
{{- end }}
1416
{{ if $u.ZoneSize -}}
1517
zone {{ $u.Name }} {{ $u.ZoneSize }};
1618
{{ end -}}

0 commit comments

Comments
 (0)