Skip to content

Commit 08e320f

Browse files
committed
support ipv6 in bind address
use split host port func instead trim specific character add unit test for metrics and healthz bind address recover import package refactor set default kube proxy configuration fix ipv4 condition fix set default port condition rewrite call function occasion to reduce error set ipv6 default value move get GetBindAddressHostPort to util use one func to handle deprecated series update bazel define address type return earlier in the error case refactor set default kube proxy configuration logic recover import package preserve some of the original comments add get default address func add append port if needed unit test rewrite unit test for deprecated flags remove unused codes
1 parent b8b7ab3 commit 08e320f

File tree

7 files changed

+181
-40
lines changed

7 files changed

+181
-40
lines changed

cmd/kube-proxy/app/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ go_library(
3131
"//pkg/proxy/iptables:go_default_library",
3232
"//pkg/proxy/ipvs:go_default_library",
3333
"//pkg/proxy/userspace:go_default_library",
34+
"//pkg/proxy/util:go_default_library",
3435
"//pkg/util/configz:go_default_library",
3536
"//pkg/util/filesystem:go_default_library",
3637
"//pkg/util/flag:go_default_library",

cmd/kube-proxy/app/server.go

Lines changed: 11 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ import (
6161
"k8s.io/kubernetes/pkg/proxy/iptables"
6262
"k8s.io/kubernetes/pkg/proxy/ipvs"
6363
"k8s.io/kubernetes/pkg/proxy/userspace"
64+
proxyutil "k8s.io/kubernetes/pkg/proxy/util"
6465
"k8s.io/kubernetes/pkg/util/configz"
6566
"k8s.io/kubernetes/pkg/util/filesystem"
6667
utilflag "k8s.io/kubernetes/pkg/util/flag"
@@ -212,8 +213,8 @@ func NewOptions() *Options {
212213
func (o *Options) Complete() error {
213214
if len(o.ConfigFile) == 0 && len(o.WriteConfigTo) == 0 {
214215
klog.Warning("WARNING: all flags other than --config, --write-config-to, and --cleanup are deprecated. Please begin using a config file ASAP.")
215-
o.applyDeprecatedHealthzPortToConfig()
216-
o.applyDeprecatedMetricsPortToConfig()
216+
o.config.HealthzBindAddress = addressFromDeprecatedFlags(o.config.HealthzBindAddress, o.healthzPort)
217+
o.config.MetricsBindAddress = addressFromDeprecatedFlags(o.config.MetricsBindAddress, o.metricsPort)
217218
}
218219

219220
// Load the config file here in Complete, so that Validate validates the fully-resolved config.
@@ -357,38 +358,15 @@ func (o *Options) writeConfigFile() error {
357358
return nil
358359
}
359360

360-
// applyDeprecatedHealthzPortToConfig sets o.config.HealthzBindAddress from
361-
// flags passed on the command line based on the following rules:
362-
//
363-
// 1. If --healthz-port is 0, disable the healthz server.
364-
// 2. Otherwise, use the value of --healthz-port for the port portion of
365-
// o.config.HealthzBindAddress
366-
func (o *Options) applyDeprecatedHealthzPortToConfig() {
367-
if o.healthzPort == 0 {
368-
o.config.HealthzBindAddress = ""
369-
return
361+
// addressFromDeprecatedFlags returns server address from flags
362+
// passed on the command line based on the following rules:
363+
// 1. If port is 0, disable the server (e.g. set address to empty).
364+
// 2. Otherwise, set the port portion of the config accordingly.
365+
func addressFromDeprecatedFlags(addr string, port int32) string {
366+
if port == 0 {
367+
return ""
370368
}
371-
372-
index := strings.Index(o.config.HealthzBindAddress, ":")
373-
if index != -1 {
374-
o.config.HealthzBindAddress = o.config.HealthzBindAddress[0:index]
375-
}
376-
377-
o.config.HealthzBindAddress = fmt.Sprintf("%s:%d", o.config.HealthzBindAddress, o.healthzPort)
378-
}
379-
380-
func (o *Options) applyDeprecatedMetricsPortToConfig() {
381-
if o.metricsPort == 0 {
382-
o.config.MetricsBindAddress = ""
383-
return
384-
}
385-
386-
index := strings.Index(o.config.MetricsBindAddress, ":")
387-
if index != -1 {
388-
o.config.MetricsBindAddress = o.config.MetricsBindAddress[0:index]
389-
}
390-
391-
o.config.MetricsBindAddress = fmt.Sprintf("%s:%d", o.config.MetricsBindAddress, o.metricsPort)
369+
return proxyutil.AppendPortIfNeeded(addr, port)
392370
}
393371

394372
// loadConfigFromFile loads the contents of file and decodes it as a

cmd/kube-proxy/app/server_test.go

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -549,3 +549,79 @@ func (s *fakeProxyServerError) Run() error {
549549
return fmt.Errorf("mocking error from ProxyServer.Run()")
550550
}
551551
}
552+
553+
func TestAddressFromDeprecatedFlags(t *testing.T) {
554+
testCases := []struct {
555+
name string
556+
healthzPort int32
557+
healthzBindAddress string
558+
metricsPort int32
559+
metricsBindAddress string
560+
expHealthz string
561+
expMetrics string
562+
}{
563+
{
564+
name: "IPv4 bind address",
565+
healthzBindAddress: "1.2.3.4",
566+
healthzPort: 12345,
567+
metricsBindAddress: "2.3.4.5",
568+
metricsPort: 23456,
569+
expHealthz: "1.2.3.4:12345",
570+
expMetrics: "2.3.4.5:23456",
571+
},
572+
{
573+
name: "IPv4 bind address has port",
574+
healthzBindAddress: "1.2.3.4:12345",
575+
healthzPort: 23456,
576+
metricsBindAddress: "2.3.4.5:12345",
577+
metricsPort: 23456,
578+
expHealthz: "1.2.3.4:12345",
579+
expMetrics: "2.3.4.5:12345",
580+
},
581+
{
582+
name: "IPv6 bind address",
583+
healthzBindAddress: "fd00:1::5",
584+
healthzPort: 12345,
585+
metricsBindAddress: "fd00:1::6",
586+
metricsPort: 23456,
587+
expHealthz: "[fd00:1::5]:12345",
588+
expMetrics: "[fd00:1::6]:23456",
589+
},
590+
{
591+
name: "IPv6 bind address has port",
592+
healthzBindAddress: "[fd00:1::5]:12345",
593+
healthzPort: 56789,
594+
metricsBindAddress: "[fd00:1::6]:56789",
595+
metricsPort: 12345,
596+
expHealthz: "[fd00:1::5]:12345",
597+
expMetrics: "[fd00:1::6]:56789",
598+
},
599+
{
600+
name: "Invalid IPv6 Config",
601+
healthzBindAddress: "[fd00:1::5]",
602+
healthzPort: 12345,
603+
metricsBindAddress: "[fd00:1::6]",
604+
metricsPort: 56789,
605+
expHealthz: "[fd00:1::5]",
606+
expMetrics: "[fd00:1::6]",
607+
},
608+
}
609+
610+
for i := range testCases {
611+
gotHealthz := addressFromDeprecatedFlags(testCases[i].healthzBindAddress, testCases[i].healthzPort)
612+
gotMetrics := addressFromDeprecatedFlags(testCases[i].metricsBindAddress, testCases[i].metricsPort)
613+
614+
errFn := func(name, except, got string) {
615+
t.Errorf("case %s: expected %v, got %v", name, except, got)
616+
}
617+
618+
if gotHealthz != testCases[i].expHealthz {
619+
errFn(testCases[i].name, testCases[i].expHealthz, gotHealthz)
620+
}
621+
622+
if gotMetrics != testCases[i].expMetrics {
623+
errFn(testCases[i].name, testCases[i].expMetrics, gotMetrics)
624+
}
625+
626+
}
627+
}

pkg/proxy/apis/config/v1alpha1/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ go_library(
2020
"//pkg/kubelet/qos:go_default_library",
2121
"//pkg/master/ports:go_default_library",
2222
"//pkg/proxy/apis/config:go_default_library",
23+
"//pkg/proxy/util:go_default_library",
2324
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
2425
"//staging/src/k8s.io/apimachinery/pkg/conversion:go_default_library",
2526
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",

pkg/proxy/apis/config/v1alpha1/defaults.go

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,16 @@ package v1alpha1
1818

1919
import (
2020
"fmt"
21-
"strings"
21+
"net"
2222
"time"
2323

2424
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2525
kruntime "k8s.io/apimachinery/pkg/runtime"
2626
kubeproxyconfigv1alpha1 "k8s.io/kube-proxy/config/v1alpha1"
27+
2728
"k8s.io/kubernetes/pkg/kubelet/qos"
2829
"k8s.io/kubernetes/pkg/master/ports"
30+
proxyutil "k8s.io/kubernetes/pkg/proxy/util"
2931
"k8s.io/utils/pointer"
3032
)
3133

@@ -34,19 +36,24 @@ func addDefaultingFuncs(scheme *kruntime.Scheme) error {
3436
}
3537

3638
func SetDefaults_KubeProxyConfiguration(obj *kubeproxyconfigv1alpha1.KubeProxyConfiguration) {
39+
3740
if len(obj.BindAddress) == 0 {
3841
obj.BindAddress = "0.0.0.0"
3942
}
43+
44+
defaultHealthzAddress, defaultMetricsAddress := getDefaultAddresses(obj.BindAddress)
45+
4046
if obj.HealthzBindAddress == "" {
41-
obj.HealthzBindAddress = fmt.Sprintf("0.0.0.0:%v", ports.ProxyHealthzPort)
42-
} else if !strings.Contains(obj.HealthzBindAddress, ":") {
43-
obj.HealthzBindAddress += fmt.Sprintf(":%v", ports.ProxyHealthzPort)
47+
obj.HealthzBindAddress = fmt.Sprintf("%s:%v", defaultHealthzAddress, ports.ProxyHealthzPort)
48+
} else {
49+
obj.HealthzBindAddress = proxyutil.AppendPortIfNeeded(obj.HealthzBindAddress, ports.ProxyHealthzPort)
4450
}
4551
if obj.MetricsBindAddress == "" {
46-
obj.MetricsBindAddress = fmt.Sprintf("127.0.0.1:%v", ports.ProxyStatusPort)
47-
} else if !strings.Contains(obj.MetricsBindAddress, ":") {
48-
obj.MetricsBindAddress += fmt.Sprintf(":%v", ports.ProxyStatusPort)
52+
obj.MetricsBindAddress = fmt.Sprintf("%s:%v", defaultMetricsAddress, ports.ProxyStatusPort)
53+
} else {
54+
obj.MetricsBindAddress = proxyutil.AppendPortIfNeeded(obj.MetricsBindAddress, ports.ProxyStatusPort)
4955
}
56+
5057
if obj.OOMScoreAdj == nil {
5158
temp := int32(qos.KubeProxyOOMScoreAdj)
5259
obj.OOMScoreAdj = &temp
@@ -121,3 +128,13 @@ func SetDefaults_KubeProxyConfiguration(obj *kubeproxyconfigv1alpha1.KubeProxyCo
121128
obj.FeatureGates = make(map[string]bool)
122129
}
123130
}
131+
132+
// getDefaultAddresses returns default address of healthz and metrics server
133+
// based on the given bind address. IPv6 addresses are enclosed in square
134+
// brackets for appending port.
135+
func getDefaultAddresses(bindAddress string) (defaultHealthzAddress, defaultMetricsAddress string) {
136+
if net.ParseIP(bindAddress).To4() != nil {
137+
return "0.0.0.0", "127.0.0.1"
138+
}
139+
return "[::]", "[::1]"
140+
}

pkg/proxy/util/utils.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,3 +214,24 @@ func filterWithCondition(strs []string, expectedCondition bool, conditionFunc fu
214214
}
215215
return corrects, incorrects
216216
}
217+
218+
// AppendPortIfNeeded appends the given port to IP address unless it is already in
219+
// "ipv4:port" or "[ipv6]:port" format.
220+
func AppendPortIfNeeded(addr string, port int32) string {
221+
// Return if address is already in "ipv4:port" or "[ipv6]:port" format.
222+
if _, _, err := net.SplitHostPort(addr); err == nil {
223+
return addr
224+
}
225+
226+
// Simply return for invalid case. This should be caught by validation instead.
227+
ip := net.ParseIP(addr)
228+
if ip == nil {
229+
return addr
230+
}
231+
232+
// Append port to address.
233+
if ip.To4() != nil {
234+
return fmt.Sprintf("%s:%d", addr, port)
235+
}
236+
return fmt.Sprintf("[%s]:%d", addr, port)
237+
}

pkg/proxy/util/utils_test.go

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -396,3 +396,50 @@ func TestGetNodeAddressses(t *testing.T) {
396396
}
397397
}
398398
}
399+
400+
func TestAppendPortIfNeeded(t *testing.T) {
401+
testCases := []struct {
402+
name string
403+
addr string
404+
port int32
405+
expect string
406+
}{
407+
{
408+
name: "IPv4 all-zeros bind address has port",
409+
addr: "0.0.0.0:12345",
410+
port: 23456,
411+
expect: "0.0.0.0:12345",
412+
},
413+
{
414+
name: "non-zeros IPv4 config",
415+
addr: "9.8.7.6",
416+
port: 12345,
417+
expect: "9.8.7.6:12345",
418+
},
419+
{
420+
name: "IPv6 \"[::]\" bind address has port",
421+
addr: "[::]:12345",
422+
port: 23456,
423+
expect: "[::]:12345",
424+
},
425+
{
426+
name: "IPv6 config",
427+
addr: "fd00:1::5",
428+
port: 23456,
429+
expect: "[fd00:1::5]:23456",
430+
},
431+
{
432+
name: "Invalid IPv6 Config",
433+
addr: "[fd00:1::5]",
434+
port: 12345,
435+
expect: "[fd00:1::5]",
436+
},
437+
}
438+
439+
for i := range testCases {
440+
got := AppendPortIfNeeded(testCases[i].addr, testCases[i].port)
441+
if testCases[i].expect != got {
442+
t.Errorf("case %s: expected %v, got %v", testCases[i].name, testCases[i].expect, got)
443+
}
444+
}
445+
}

0 commit comments

Comments
 (0)