Add check for IPv6 '::' when calculating kube-proxy's node IP

kube-proxy currently checks for a bind address of 0.0.0.0 (IPv4 all-zeros)
when calculating kube-proxy's node IP, but it does not check for
an address of '::' (IPv6 all-zeros). For either of those all-zeros
addresses, the node IP should be determined based on the hostname,
rather than using the address directly.

Also added a helpful log message when the kube-proxy protocol is
determined to be IPv6.

fixes #52613
pull/6/head
Dane LeBlanc 2017-09-17 13:42:09 -04:00
parent e381a737fe
commit 6d71eb590b
3 changed files with 59 additions and 9 deletions

View File

@ -65,6 +65,7 @@ func NewProxyServer(config *componentconfig.KubeProxyConfiguration, cleanupAndEx
protocol := utiliptables.ProtocolIpv4
if net.ParseIP(config.BindAddress).To4() == nil {
glog.V(0).Infof("IPv6 bind address (%s), assume IPv6 operation", config.BindAddress)
protocol = utiliptables.ProtocolIpv6
}
@ -115,10 +116,8 @@ func NewProxyServer(config *componentconfig.KubeProxyConfiguration, cleanupAndEx
proxyMode := getProxyMode(string(config.Mode), iptInterface, iptables.LinuxKernelCompatTester{})
if proxyMode == proxyModeIPTables {
glog.V(0).Info("Using iptables Proxier.")
var nodeIP net.IP
if config.BindAddress != "0.0.0.0" {
nodeIP = net.ParseIP(config.BindAddress)
} else {
nodeIP := net.ParseIP(config.BindAddress)
if nodeIP.Equal(net.IPv4zero) || nodeIP.Equal(net.IPv6zero) {
nodeIP = getNodeIP(client, hostname)
}
if config.IPTables.MasqueradeBit == nil {

View File

@ -177,7 +177,7 @@ func TestProxyServerWithCleanupAndExit(t *testing.T) {
// Each bind address below is a separate test case
bindAddresses := []string{
"0.0.0.0",
"2001:db8::1",
"::",
}
for _, addr := range bindAddresses {
options, err := NewOptions()
@ -308,13 +308,54 @@ udpTimeoutMilliseconds: 123ms
metricsBindAddress string
}{
{
name: "iptables mode, IPv4 config",
name: "iptables mode, IPv4 all-zeros bind address",
mode: "iptables",
bindAddress: "0.0.0.0",
clusterCIDR: "1.2.3.0/24",
healthzBindAddress: "1.2.3.4:12345",
metricsBindAddress: "2.3.4.5:23456",
},
{
name: "iptables mode, non-zeros IPv4 config",
mode: "iptables",
bindAddress: "9.8.7.6",
clusterCIDR: "1.2.3.0/24",
healthzBindAddress: "1.2.3.4:12345",
metricsBindAddress: "2.3.4.5:23456",
},
{
// Test for 'bindAddress: "::"' (IPv6 all-zeros) in kube-proxy
// config file. The user will need to put quotes around '::' since
// 'bindAddress: ::' is invalid yaml syntax.
name: "iptables mode, IPv6 \"::\" bind address",
mode: "iptables",
bindAddress: "\"::\"",
clusterCIDR: "fd00:1::0/64",
healthzBindAddress: "[fd00:1::5]:12345",
metricsBindAddress: "[fd00:2::5]:23456",
},
{
// Test for 'bindAddress: "[::]"' (IPv6 all-zeros in brackets)
// in kube-proxy config file. The user will need to use
// surrounding quotes here since 'bindAddress: [::]' is invalid
// yaml syntax.
name: "iptables mode, IPv6 \"[::]\" bind address",
mode: "iptables",
bindAddress: "\"[::]\"",
clusterCIDR: "fd00:1::0/64",
healthzBindAddress: "[fd00:1::5]:12345",
metricsBindAddress: "[fd00:2::5]:23456",
},
{
// Test for 'bindAddress: ::0' (another form of IPv6 all-zeros).
// No surrounding quotes are required around '::0'.
name: "iptables mode, IPv6 ::0 bind address",
mode: "iptables",
bindAddress: "::0",
clusterCIDR: "fd00:1::0/64",
healthzBindAddress: "[fd00:1::5]:12345",
metricsBindAddress: "[fd00:2::5]:23456",
},
{
name: "ipvs mode, IPv6 config",
mode: "ipvs",
@ -326,8 +367,13 @@ udpTimeoutMilliseconds: 123ms
}
for _, tc := range testCases {
expBindAddr := tc.bindAddress
if tc.bindAddress[0] == '"' {
// Surrounding double quotes will get stripped by the yaml parser.
expBindAddr = expBindAddr[1 : len(tc.bindAddress)-1]
}
expected := &componentconfig.KubeProxyConfiguration{
BindAddress: tc.bindAddress,
BindAddress: expBindAddr,
ClientConnection: componentconfig.ClientConnectionConfiguration{
AcceptContentTypes: "abc",
Burst: 100,
@ -374,7 +420,7 @@ udpTimeoutMilliseconds: 123ms
config, err := options.loadConfig([]byte(yaml))
assert.NoError(t, err, "unexpected error for %s: %v", tc.name, err)
if !reflect.DeepEqual(expected, config) {
t.Fatalf("unexpected config for %s test, diff = %s", tc.name, diff.ObjectDiff(config, expected))
t.Fatalf("unexpected config for %s, diff = %s", tc.name, diff.ObjectDiff(config, expected))
}
}
}
@ -396,6 +442,11 @@ func TestLoadConfigFailures(t *testing.T) {
config: "kind: KubeSchedulerConfiguration",
expErr: "unexpected config type",
},
{
name: "Missing quotes around :: bindAddress",
config: "bindAddress: ::",
expErr: "mapping values are not allowed in this context",
},
}
version := "apiVersion: componentconfig/v1alpha1"
for _, tc := range testCases {

View File

@ -942,7 +942,7 @@ func iptablesFlush(ipt iptables.Interface) error {
var zeroIPv4 = net.ParseIP("0.0.0.0")
var localhostIPv4 = net.ParseIP("127.0.0.1")
var zeroIPv6 = net.ParseIP("::0")
var zeroIPv6 = net.ParseIP("::")
var localhostIPv6 = net.ParseIP("::1")
// Build a slice of iptables args that are common to from-container and from-host portal rules.