Skip to content

Commit 547055c

Browse files
committed
Update default lb-method to be least_conn
1 parent ae9c98c commit 547055c

File tree

6 files changed

+80
-15
lines changed

6 files changed

+80
-15
lines changed

examples/customization/README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ The table below summarizes all of the options. For some of them, there are examp
3939
| N/A | `http-snippets` | Sets a custom snippet in http context. | N/A | |
4040
| `nginx.org/location-snippets` | `location-snippets` | Sets a custom snippet in location context. | N/A | |
4141
| `nginx.org/server-snippets` | `server-snippets` | Sets a custom snippet in server context. | N/A | |
42-
| `nginx.org/lb-method` | `lb-method` | Sets the [load balancing method](https://www.nginx.com/resources/admin-guide/load-balancer/#method). The default `""` specifies the round-robin method. | `""` | |
42+
| `nginx.org/lb-method` | `lb-method` | Sets the [load balancing method](https://docs.nginx.com/nginx/admin-guide/load-balancer/http-load-balancer/#choosing-a-load-balancing-method). To use the round-robin method, specify `"round_robin"`. | `"least_conn"` | |
4343
| `nginx.org/listen-ports` | N/A | Configures HTTP ports that NGINX will listen on. | `[80]` | |
4444
| `nginx.org/listen-ports-ssl` | N/A | Configures HTTPS ports that NGINX will listen on. | `[443]` | |
4545
| N/A | `worker-processes` | Sets the value of the [worker_processes](http://nginx.org/en/docs/ngx_core_module.html#worker_processes) directive. | `auto` | |
@@ -64,7 +64,7 @@ The table below summarizes all of the options. For some of them, there are examp
6464

6565
1. Make sure that you specify the configmaps resource to use when you start an Ingress controller.
6666
For example, `-nginx-configmaps=default/nginx-config`, where we specify
67-
the config map to use with the following format: `<namespace>/<name>`.
67+
the config map to use with the following format: `<namespace>/<name>`.
6868

6969
1. Create a configmaps file with the name *nginx-config.yaml* and set the values
7070
that make sense for your setup:

examples/customization/nginx-config.yaml

+1
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ data:
4545
if ($new_uri) {
4646
rewrite ^ $new_uri permanent;
4747
}
48+
lb-method: "round_robin" # default is least_conn. Sets the load balancing method for upstreams. See https://docs.nginx.com/nginx/admin-guide/load-balancer/http-load-balancer/#choosing-a-load-balancing-method
4849
location-snippets: | # No default. Pipe is used for multiple line snippets. Make sure the snippet is not a default value, in order to avoid duplication.
4950
proxy_temp_path /var/nginx/proxy_temp;
5051
charset koi8-r;

nginx-controller/controller/controller.go

+11-3
Original file line numberDiff line numberDiff line change
@@ -450,10 +450,18 @@ func (lbc *LoadBalancerController) syncCfgm(task Task) {
450450
}
451451

452452
if lbMethod, exists := cfgm.Data["lb-method"]; exists {
453-
if parsedMethod, err := nginx.ParseLBMethod(lbMethod); err != nil {
454-
glog.Errorf("Configmap %s/%s: Invalid value for the lb-method key: got %q", cfgm.GetNamespace(), cfgm.GetName(), lbMethod)
453+
if lbc.nginxPlus {
454+
if parsedMethod, err := nginx.ParseLBMethodForPlus(lbMethod); err != nil {
455+
glog.Errorf("Configmap %s/%s: Invalid value for the lb-method key: got %q: %v", cfgm.GetNamespace(), cfgm.GetName(), lbMethod, err)
456+
} else {
457+
cfg.LBMethod = parsedMethod
458+
}
455459
} else {
456-
cfg.LBMethod = parsedMethod
460+
if parsedMethod, err := nginx.ParseLBMethod(lbMethod); err != nil {
461+
glog.Errorf("Configmap %s/%s: Invalid value for the lb-method key: got %q: %v", cfgm.GetNamespace(), cfgm.GetName(), lbMethod, err)
462+
} else {
463+
cfg.LBMethod = parsedMethod
464+
}
457465
}
458466
}
459467

nginx-controller/nginx/configurator.go

+11-3
Original file line numberDiff line numberDiff line change
@@ -280,10 +280,18 @@ func (cnf *Configurator) createConfig(ingEx *IngressEx) Config {
280280

281281
//Override from annotation
282282
if lbMethod, exists := ingEx.Ingress.Annotations["nginx.org/lb-method"]; exists {
283-
if parsedMethod, err := ParseLBMethod(lbMethod); err != nil {
284-
glog.Errorf("Ingress %s/%s: Invalid value for the nginx.org/lb-method: got %q", ingEx.Ingress.GetNamespace(), ingEx.Ingress.GetName(), lbMethod)
283+
if cnf.isPlus() {
284+
if parsedMethod, err := ParseLBMethodForPlus(lbMethod); err != nil {
285+
glog.Errorf("Ingress %s/%s: Invalid value for the nginx.org/lb-method: got %q: %v", ingEx.Ingress.GetNamespace(), ingEx.Ingress.GetName(), lbMethod, err)
286+
} else {
287+
ingCfg.LBMethod = parsedMethod
288+
}
285289
} else {
286-
ingCfg.LBMethod = parsedMethod
290+
if parsedMethod, err := ParseLBMethod(lbMethod); err != nil {
291+
glog.Errorf("Ingress %s/%s: Invalid value for the nginx.org/lb-method: got %q: %v", ingEx.Ingress.GetNamespace(), ingEx.Ingress.GetName(), lbMethod, err)
292+
} else {
293+
ingCfg.LBMethod = parsedMethod
294+
}
287295
}
288296
}
289297

nginx-controller/nginx/extensions.go

+48-2
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,61 @@
11
package nginx
22

3+
import (
4+
"fmt"
5+
"strings"
6+
)
7+
8+
// ParseLBMethod parses method and matches it to a corresponding load balancing method in NGINX. An error is returned if method is not valid
39
func ParseLBMethod(method string) (string, error) {
10+
method = strings.TrimSpace(method)
411
if method == "round_robin" {
512
return "", nil
613
}
7-
return method, nil
14+
if strings.HasPrefix(method, "hash") {
15+
method, err := validateHashLBMethod(method)
16+
return method, err
17+
}
18+
19+
if method == "least_conn" || method == "ip_hash" {
20+
return method, nil
21+
}
22+
return "", fmt.Errorf("Invalid load balancing method: %q", method)
23+
}
24+
25+
var nginxPlusLBValidInput = map[string]bool{
26+
"least_time": true,
27+
"last_byte": true,
28+
"least_conn": true,
29+
"ip_hash": true,
30+
"least_time header": true,
31+
"least_time last_byte": true,
32+
"least_time header inflight": true,
33+
"least_time last_byte inflight": true,
834
}
935

36+
// ParseLBMethodForPlus parses method and matches it to a corresponding load balancing method in NGINX Plus. An error is returned if method is not valid
1037
func ParseLBMethodForPlus(method string) (string, error) {
38+
method = strings.TrimSpace(method)
1139
if method == "round_robin" {
1240
return "", nil
1341
}
14-
return method, nil
42+
if strings.HasPrefix(method, "hash") {
43+
method, err := validateHashLBMethod(method)
44+
return method, err
45+
}
46+
47+
if _, exists := nginxPlusLBValidInput[method]; exists {
48+
return method, nil
49+
}
50+
return "", fmt.Errorf("Invalid load balancing method: %q", method)
51+
}
52+
53+
func validateHashLBMethod(method string) (string, error) {
54+
keyWords := strings.Split(method, " ")
55+
if keyWords[0] == "hash" {
56+
if len(keyWords) == 2 || len(keyWords) == 3 && keyWords[2] == "consistent" {
57+
return method, nil
58+
}
59+
}
60+
return "", fmt.Errorf("Invalid load balancing method: %q", method)
1561
}

nginx-controller/nginx/extensions_test.go

+7-5
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,19 @@ func TestParseLBMethod(t *testing.T) {
77
input string
88
expected string
99
}{
10-
{"", "least_conn"},
1110
{"least_conn", "least_conn"},
1211
{"round_robin", ""},
1312
{"ip_hash", "ip_hash"},
1413
{"hash $request_id", "hash $request_id"},
14+
{"hash $request_id consistent", "hash $request_id consistent"},
1515
}
1616

1717
var invalidInput = []string{
18+
"",
1819
"blabla",
1920
"least_time header",
2021
"hash123",
22+
"hash $request_id conwrongspelling",
2123
}
2224

2325
for _, test := range testsWithValidInput {
@@ -44,7 +46,6 @@ func TestParseLBMethodForPlus(t *testing.T) {
4446
input string
4547
expected string
4648
}{
47-
{"", "least_conn"},
4849
{"least_conn", "least_conn"},
4950
{"round_robin", ""},
5051
{"ip_hash", "ip_hash"},
@@ -56,13 +57,14 @@ func TestParseLBMethodForPlus(t *testing.T) {
5657
}
5758

5859
var invalidInput = []string{
60+
"",
5961
"blabla",
6062
"hash123",
61-
"least_time header inflight",
63+
"least_time inflight header",
6264
}
6365

6466
for _, test := range testsWithValidInput {
65-
result, err := ParseLBMethod(test.input)
67+
result, err := ParseLBMethodForPlus(test.input)
6668
if err != nil {
6769
t.Errorf("TestParseLBMethod(%q) returned an error for valid input", test.input)
6870
}
@@ -73,7 +75,7 @@ func TestParseLBMethodForPlus(t *testing.T) {
7375
}
7476

7577
for _, input := range invalidInput {
76-
_, err := ParseLBMethod(input)
78+
_, err := ParseLBMethodForPlus(input)
7779
if err == nil {
7880
t.Errorf("TestParseLBMethod(%q) does not return an error for invalid input", input)
7981
}

0 commit comments

Comments
 (0)