From f1f390f13b8e6be75fa58f1f1f33eabaf72f5806 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Sun, 28 Apr 2024 11:51:23 -0400 Subject: [PATCH] clean up LocalTrafficDetector construction / tests (#124582) * LocalTrafficDetector construction and test improvements * Reorder getLocalDetector unit test fields so "input" args come before "output" args * Don't pass DetectLocalMode as a separate arg to getLocalDetector It's already part of `config` * Clarify test names in preparation for merging * Merge single-stack/dual-stack LocalTrafficDetector construction Also, only warn if the *primary* IP family is not correctly configured (since we don't actually know if the cluster is really dual-stack or not), and pass the pair of detectors to the proxiers as a map rather than an array. * Remove the rest of Test_getDualStackLocalDetectorTuple --- cmd/kube-proxy/app/server_linux.go | 80 ++-- cmd/kube-proxy/app/server_linux_test.go | 475 ++++++++++++------------ pkg/proxy/iptables/proxier.go | 12 +- pkg/proxy/ipvs/proxier.go | 6 +- pkg/proxy/nftables/proxier.go | 12 +- 5 files changed, 283 insertions(+), 302 deletions(-) diff --git a/cmd/kube-proxy/app/server_linux.go b/cmd/kube-proxy/app/server_linux.go index 6c9fd531fbe..f1e150e3a70 100644 --- a/cmd/kube-proxy/app/server_linux.go +++ b/cmd/kube-proxy/app/server_linux.go @@ -162,18 +162,16 @@ func (s *ProxyServer) platformCheckSupported(ctx context.Context) (ipv4Supported func (s *ProxyServer) createProxier(ctx context.Context, config *proxyconfigapi.KubeProxyConfiguration, dualStack, initOnly bool) (proxy.Provider, error) { logger := klog.FromContext(ctx) var proxier proxy.Provider - var localDetectors [2]proxyutil.LocalTrafficDetector - var localDetector proxyutil.LocalTrafficDetector var err error + localDetectors := getLocalDetectors(logger, s.PrimaryIPFamily, config, s.podCIDRs) + if config.Mode == proxyconfigapi.ProxyModeIPTables { logger.Info("Using iptables Proxier") if dualStack { ipt, _ := getIPTables(s.PrimaryIPFamily) - localDetectors = getDualStackLocalDetectorTuple(logger, config.DetectLocalMode, config, s.podCIDRs) - // TODO this has side effects that should only happen when Run() is invoked. proxier, err = iptables.NewDualStackProxier( ctx, @@ -196,7 +194,6 @@ func (s *ProxyServer) createProxier(ctx context.Context, config *proxyconfigapi. } else { // Create a single-stack proxier if and only if the node does not support dual-stack (i.e, no iptables support). _, iptInterface := getIPTables(s.PrimaryIPFamily) - localDetector = getLocalDetector(logger, s.PrimaryIPFamily, config.DetectLocalMode, config, s.podCIDRs) // TODO this has side effects that should only happen when Run() is invoked. proxier, err = iptables.NewProxier( @@ -210,7 +207,7 @@ func (s *ProxyServer) createProxier(ctx context.Context, config *proxyconfigapi. config.IPTables.MasqueradeAll, *config.IPTables.LocalhostNodePorts, int(*config.IPTables.MasqueradeBit), - localDetector, + localDetectors[s.PrimaryIPFamily], s.Hostname, s.NodeIPs[s.PrimaryIPFamily], s.Recorder, @@ -234,10 +231,6 @@ func (s *ProxyServer) createProxier(ctx context.Context, config *proxyconfigapi. logger.Info("Using ipvs Proxier") if dualStack { ipt, _ := getIPTables(s.PrimaryIPFamily) - - // Always ordered to match []ipt - localDetectors = getDualStackLocalDetectorTuple(logger, config.DetectLocalMode, config, s.podCIDRs) - proxier, err = ipvs.NewDualStackProxier( ctx, ipt, @@ -265,8 +258,6 @@ func (s *ProxyServer) createProxier(ctx context.Context, config *proxyconfigapi. ) } else { _, iptInterface := getIPTables(s.PrimaryIPFamily) - localDetector = getLocalDetector(logger, s.PrimaryIPFamily, config.DetectLocalMode, config, s.podCIDRs) - proxier, err = ipvs.NewProxier( ctx, s.PrimaryIPFamily, @@ -284,7 +275,7 @@ func (s *ProxyServer) createProxier(ctx context.Context, config *proxyconfigapi. config.IPVS.UDPTimeout.Duration, config.IPTables.MasqueradeAll, int(*config.IPTables.MasqueradeBit), - localDetector, + localDetectors[s.PrimaryIPFamily], s.Hostname, s.NodeIPs[s.PrimaryIPFamily], s.Recorder, @@ -301,8 +292,6 @@ func (s *ProxyServer) createProxier(ctx context.Context, config *proxyconfigapi. logger.Info("Using nftables Proxier") if dualStack { - localDetectors = getDualStackLocalDetectorTuple(logger, config.DetectLocalMode, config, s.podCIDRs) - // TODO this has side effects that should only happen when Run() is invoked. proxier, err = nftables.NewDualStackProxier( ctx, @@ -321,8 +310,6 @@ func (s *ProxyServer) createProxier(ctx context.Context, config *proxyconfigapi. ) } else { // Create a single-stack proxier if and only if the node does not support dual-stack - localDetector = getLocalDetector(logger, s.PrimaryIPFamily, config.DetectLocalMode, config, s.podCIDRs) - // TODO this has side effects that should only happen when Run() is invoked. proxier, err = nftables.NewProxier( ctx, @@ -332,7 +319,7 @@ func (s *ProxyServer) createProxier(ctx context.Context, config *proxyconfigapi. config.NFTables.MinSyncPeriod.Duration, config.NFTables.MasqueradeAll, int(*config.NFTables.MasqueradeBit), - localDetector, + localDetectors[s.PrimaryIPFamily], s.Hostname, s.NodeIPs[s.PrimaryIPFamily], s.Recorder, @@ -484,48 +471,45 @@ func detectNumCPU() int { return numCPU } -func getLocalDetector(logger klog.Logger, ipFamily v1.IPFamily, mode proxyconfigapi.LocalMode, config *proxyconfigapi.KubeProxyConfiguration, nodePodCIDRs []string) proxyutil.LocalTrafficDetector { - switch mode { +func getLocalDetectors(logger klog.Logger, primaryIPFamily v1.IPFamily, config *proxyconfigapi.KubeProxyConfiguration, nodePodCIDRs []string) map[v1.IPFamily]proxyutil.LocalTrafficDetector { + localDetectors := map[v1.IPFamily]proxyutil.LocalTrafficDetector{ + v1.IPv4Protocol: proxyutil.NewNoOpLocalDetector(), + v1.IPv6Protocol: proxyutil.NewNoOpLocalDetector(), + } + + switch config.DetectLocalMode { case proxyconfigapi.LocalModeClusterCIDR: - // LocalModeClusterCIDR is the default if --detect-local-mode wasn't passed, - // but --cluster-cidr is optional. - clusterCIDRs := strings.TrimSpace(config.ClusterCIDR) - if len(clusterCIDRs) == 0 { - logger.Info("Detect-local-mode set to ClusterCIDR, but no cluster CIDR defined") - break + clusterCIDRs := strings.Split(strings.TrimSpace(config.ClusterCIDR), ",") + for family, cidrs := range proxyutil.MapCIDRsByIPFamily(clusterCIDRs) { + localDetectors[family] = proxyutil.NewDetectLocalByCIDR(cidrs[0].String()) } - - cidrsByFamily := proxyutil.MapCIDRsByIPFamily(strings.Split(clusterCIDRs, ",")) - if len(cidrsByFamily[ipFamily]) != 0 { - return proxyutil.NewDetectLocalByCIDR(cidrsByFamily[ipFamily][0].String()) + if !localDetectors[primaryIPFamily].IsImplemented() { + logger.Info("Detect-local-mode set to ClusterCIDR, but no cluster CIDR specified for primary IP family", "ipFamily", primaryIPFamily, "clusterCIDR", config.ClusterCIDR) } - logger.Info("Detect-local-mode set to ClusterCIDR, but no cluster CIDR for family", "ipFamily", ipFamily) - case proxyconfigapi.LocalModeNodeCIDR: - cidrsByFamily := proxyutil.MapCIDRsByIPFamily(nodePodCIDRs) - if len(cidrsByFamily[ipFamily]) != 0 { - return proxyutil.NewDetectLocalByCIDR(cidrsByFamily[ipFamily][0].String()) + for family, cidrs := range proxyutil.MapCIDRsByIPFamily(nodePodCIDRs) { + localDetectors[family] = proxyutil.NewDetectLocalByCIDR(cidrs[0].String()) + } + if !localDetectors[primaryIPFamily].IsImplemented() { + logger.Info("Detect-local-mode set to NodeCIDR, but no PodCIDR defined at node for primary IP family", "ipFamily", primaryIPFamily, "podCIDRs", nodePodCIDRs) } - logger.Info("Detect-local-mode set to NodeCIDR, but no PodCIDR defined at node for family", "ipFamily", ipFamily) - case proxyconfigapi.LocalModeBridgeInterface: - return proxyutil.NewDetectLocalByBridgeInterface(config.DetectLocal.BridgeInterface) + localDetector := proxyutil.NewDetectLocalByBridgeInterface(config.DetectLocal.BridgeInterface) + localDetectors[v1.IPv4Protocol] = localDetector + localDetectors[v1.IPv6Protocol] = localDetector case proxyconfigapi.LocalModeInterfaceNamePrefix: - return proxyutil.NewDetectLocalByInterfaceNamePrefix(config.DetectLocal.InterfaceNamePrefix) + localDetector := proxyutil.NewDetectLocalByInterfaceNamePrefix(config.DetectLocal.InterfaceNamePrefix) + localDetectors[v1.IPv4Protocol] = localDetector + localDetectors[v1.IPv6Protocol] = localDetector + + default: + logger.Info("Defaulting to no-op detect-local") } - logger.Info("Defaulting to no-op detect-local") - return proxyutil.NewNoOpLocalDetector() -} - -func getDualStackLocalDetectorTuple(logger klog.Logger, mode proxyconfigapi.LocalMode, config *proxyconfigapi.KubeProxyConfiguration, nodePodCIDRs []string) [2]proxyutil.LocalTrafficDetector { - return [2]proxyutil.LocalTrafficDetector{ - getLocalDetector(logger, v1.IPv4Protocol, mode, config, nodePodCIDRs), - getLocalDetector(logger, v1.IPv6Protocol, mode, config, nodePodCIDRs), - } + return localDetectors } // platformCleanup removes stale kube-proxy rules that can be safely removed. If diff --git a/cmd/kube-proxy/app/server_linux_test.go b/cmd/kube-proxy/app/server_linux_test.go index 776c5d0fa14..ad4d28ca001 100644 --- a/cmd/kube-proxy/app/server_linux_test.go +++ b/cmd/kube-proxy/app/server_linux_test.go @@ -108,299 +108,292 @@ func Test_platformApplyDefaults(t *testing.T) { } } -func Test_getLocalDetector(t *testing.T) { +func Test_getLocalDetectors(t *testing.T) { cases := []struct { - name string - mode proxyconfigapi.LocalMode - config *proxyconfigapi.KubeProxyConfiguration - family v1.IPFamily - expected proxyutil.LocalTrafficDetector - nodePodCIDRs []string + name string + config *proxyconfigapi.KubeProxyConfiguration + primaryIPFamily v1.IPFamily + nodePodCIDRs []string + expected map[v1.IPFamily]proxyutil.LocalTrafficDetector }{ // LocalModeClusterCIDR { - name: "LocalModeClusterCIDR, IPv4 cluster", - mode: proxyconfigapi.LocalModeClusterCIDR, - config: &proxyconfigapi.KubeProxyConfiguration{ClusterCIDR: "10.0.0.0/14"}, - family: v1.IPv4Protocol, - expected: proxyutil.NewDetectLocalByCIDR("10.0.0.0/14"), + name: "LocalModeClusterCIDR, single-stack IPv4 cluster", + config: &proxyconfigapi.KubeProxyConfiguration{ + DetectLocalMode: proxyconfigapi.LocalModeClusterCIDR, + ClusterCIDR: "10.0.0.0/14", + }, + primaryIPFamily: v1.IPv4Protocol, + expected: map[v1.IPFamily]proxyutil.LocalTrafficDetector{ + v1.IPv4Protocol: proxyutil.NewDetectLocalByCIDR("10.0.0.0/14"), + v1.IPv6Protocol: proxyutil.NewNoOpLocalDetector(), + }, }, { - name: "LocalModeClusterCIDR, IPv6 cluster", - mode: proxyconfigapi.LocalModeClusterCIDR, - config: &proxyconfigapi.KubeProxyConfiguration{ClusterCIDR: "2002:0:0:1234::/64"}, - family: v1.IPv6Protocol, - expected: proxyutil.NewDetectLocalByCIDR("2002:0:0:1234::/64"), + name: "LocalModeClusterCIDR, single-stack IPv6 cluster", + config: &proxyconfigapi.KubeProxyConfiguration{ + DetectLocalMode: proxyconfigapi.LocalModeClusterCIDR, + ClusterCIDR: "2002:0:0:1234::/64", + }, + primaryIPFamily: v1.IPv6Protocol, + expected: map[v1.IPFamily]proxyutil.LocalTrafficDetector{ + v1.IPv4Protocol: proxyutil.NewNoOpLocalDetector(), + v1.IPv6Protocol: proxyutil.NewDetectLocalByCIDR("2002:0:0:1234::/64"), + }, }, { - name: "LocalModeClusterCIDR, IPv6 cluster with IPv4 config", - mode: proxyconfigapi.LocalModeClusterCIDR, - config: &proxyconfigapi.KubeProxyConfiguration{ClusterCIDR: "10.0.0.0/14"}, - family: v1.IPv6Protocol, - expected: proxyutil.NewNoOpLocalDetector(), + name: "LocalModeClusterCIDR, single-stack IPv6 cluster with single-stack IPv4 config", + config: &proxyconfigapi.KubeProxyConfiguration{ + DetectLocalMode: proxyconfigapi.LocalModeClusterCIDR, + ClusterCIDR: "10.0.0.0/14", + }, + primaryIPFamily: v1.IPv6Protocol, + // This will output a warning that there is no IPv6 CIDR but it + // will still use the provided IPv4 CIDR for IPv4. + expected: map[v1.IPFamily]proxyutil.LocalTrafficDetector{ + v1.IPv4Protocol: proxyutil.NewDetectLocalByCIDR("10.0.0.0/14"), + v1.IPv6Protocol: proxyutil.NewNoOpLocalDetector(), + }, }, { - name: "LocalModeClusterCIDR, IPv4 cluster with IPv6 config", - mode: proxyconfigapi.LocalModeClusterCIDR, - config: &proxyconfigapi.KubeProxyConfiguration{ClusterCIDR: "2002:0:0:1234::/64"}, - family: v1.IPv4Protocol, - expected: proxyutil.NewNoOpLocalDetector(), + name: "LocalModeClusterCIDR, single-stack IPv4 cluster with single-stack IPv6 config", + config: &proxyconfigapi.KubeProxyConfiguration{ + DetectLocalMode: proxyconfigapi.LocalModeClusterCIDR, + ClusterCIDR: "2002:0:0:1234::/64", + }, + primaryIPFamily: v1.IPv4Protocol, + // This will output a warning that there is no IPv4 CIDR but it + // will still use the provided IPv6 CIDR for IPv6. + expected: map[v1.IPFamily]proxyutil.LocalTrafficDetector{ + v1.IPv4Protocol: proxyutil.NewNoOpLocalDetector(), + v1.IPv6Protocol: proxyutil.NewDetectLocalByCIDR("2002:0:0:1234::/64"), + }, }, { - name: "LocalModeClusterCIDR, IPv4 kube-proxy in dual-stack IPv6-primary cluster", - mode: proxyconfigapi.LocalModeClusterCIDR, - config: &proxyconfigapi.KubeProxyConfiguration{ClusterCIDR: "2002:0:0:1234::/64,10.0.0.0/14"}, - family: v1.IPv4Protocol, - expected: proxyutil.NewDetectLocalByCIDR("10.0.0.0/14"), + name: "LocalModeClusterCIDR, dual-stack IPv4-primary cluster", + config: &proxyconfigapi.KubeProxyConfiguration{ + DetectLocalMode: proxyconfigapi.LocalModeClusterCIDR, + ClusterCIDR: "10.0.0.0/14,2002:0:0:1234::/64", + }, + primaryIPFamily: v1.IPv4Protocol, + expected: map[v1.IPFamily]proxyutil.LocalTrafficDetector{ + v1.IPv4Protocol: proxyutil.NewDetectLocalByCIDR("10.0.0.0/14"), + v1.IPv6Protocol: proxyutil.NewDetectLocalByCIDR("2002:0:0:1234::/64"), + }, }, { - name: "LocalModeClusterCIDR, no ClusterCIDR", - mode: proxyconfigapi.LocalModeClusterCIDR, - config: &proxyconfigapi.KubeProxyConfiguration{ClusterCIDR: ""}, - family: v1.IPv4Protocol, - expected: proxyutil.NewNoOpLocalDetector(), + name: "LocalModeClusterCIDR, dual-stack IPv6-primary cluster", + config: &proxyconfigapi.KubeProxyConfiguration{ + DetectLocalMode: proxyconfigapi.LocalModeClusterCIDR, + ClusterCIDR: "2002:0:0:1234::/64,10.0.0.0/14", + }, + primaryIPFamily: v1.IPv6Protocol, + expected: map[v1.IPFamily]proxyutil.LocalTrafficDetector{ + v1.IPv4Protocol: proxyutil.NewDetectLocalByCIDR("10.0.0.0/14"), + v1.IPv6Protocol: proxyutil.NewDetectLocalByCIDR("2002:0:0:1234::/64"), + }, + }, + { + name: "LocalModeClusterCIDR, IPv4-primary kube-proxy / IPv6-primary config", + config: &proxyconfigapi.KubeProxyConfiguration{ + DetectLocalMode: proxyconfigapi.LocalModeClusterCIDR, + ClusterCIDR: "2002:0:0:1234::/64,10.0.0.0/14", + }, + primaryIPFamily: v1.IPv4Protocol, + expected: map[v1.IPFamily]proxyutil.LocalTrafficDetector{ + v1.IPv4Protocol: proxyutil.NewDetectLocalByCIDR("10.0.0.0/14"), + v1.IPv6Protocol: proxyutil.NewDetectLocalByCIDR("2002:0:0:1234::/64"), + }, + }, + { + name: "LocalModeClusterCIDR, no ClusterCIDR", + config: &proxyconfigapi.KubeProxyConfiguration{ + DetectLocalMode: proxyconfigapi.LocalModeClusterCIDR, + ClusterCIDR: "", + }, + primaryIPFamily: v1.IPv4Protocol, + expected: map[v1.IPFamily]proxyutil.LocalTrafficDetector{ + v1.IPv4Protocol: proxyutil.NewNoOpLocalDetector(), + v1.IPv6Protocol: proxyutil.NewNoOpLocalDetector(), + }, }, // LocalModeNodeCIDR { - name: "LocalModeNodeCIDR, IPv4 cluster", - mode: proxyconfigapi.LocalModeNodeCIDR, - config: &proxyconfigapi.KubeProxyConfiguration{ClusterCIDR: "10.0.0.0/14"}, - family: v1.IPv4Protocol, - expected: proxyutil.NewDetectLocalByCIDR("10.0.0.0/24"), - nodePodCIDRs: []string{"10.0.0.0/24"}, + name: "LocalModeNodeCIDR, single-stack IPv4 cluster", + config: &proxyconfigapi.KubeProxyConfiguration{ + DetectLocalMode: proxyconfigapi.LocalModeNodeCIDR, + ClusterCIDR: "10.0.0.0/14", + }, + primaryIPFamily: v1.IPv4Protocol, + nodePodCIDRs: []string{"10.0.0.0/24"}, + expected: map[v1.IPFamily]proxyutil.LocalTrafficDetector{ + v1.IPv4Protocol: proxyutil.NewDetectLocalByCIDR("10.0.0.0/24"), + v1.IPv6Protocol: proxyutil.NewNoOpLocalDetector(), + }, }, { - name: "LocalModeNodeCIDR, IPv6 cluster", - mode: proxyconfigapi.LocalModeNodeCIDR, - config: &proxyconfigapi.KubeProxyConfiguration{ClusterCIDR: "2002:0:0:1234::/64"}, - family: v1.IPv6Protocol, - expected: proxyutil.NewDetectLocalByCIDR("2002::1234:abcd:ffff:0:0/96"), - nodePodCIDRs: []string{"2002::1234:abcd:ffff:0:0/96"}, + name: "LocalModeNodeCIDR, single-stack IPv6 cluster", + config: &proxyconfigapi.KubeProxyConfiguration{ + DetectLocalMode: proxyconfigapi.LocalModeNodeCIDR, + ClusterCIDR: "2002:0:0:1234::/64", + }, + primaryIPFamily: v1.IPv6Protocol, + nodePodCIDRs: []string{"2002::1234:abcd:ffff:0:0/96"}, + expected: map[v1.IPFamily]proxyutil.LocalTrafficDetector{ + v1.IPv4Protocol: proxyutil.NewNoOpLocalDetector(), + v1.IPv6Protocol: proxyutil.NewDetectLocalByCIDR("2002::1234:abcd:ffff:0:0/96"), + }, }, { - name: "LocalModeNodeCIDR, IPv6 cluster with IPv4 config", - mode: proxyconfigapi.LocalModeNodeCIDR, - config: &proxyconfigapi.KubeProxyConfiguration{ClusterCIDR: "10.0.0.0/14"}, - family: v1.IPv6Protocol, - expected: proxyutil.NewNoOpLocalDetector(), - nodePodCIDRs: []string{"10.0.0.0/24"}, + name: "LocalModeNodeCIDR, single-stack IPv6 cluster with single-stack IPv4 config", + config: &proxyconfigapi.KubeProxyConfiguration{ + DetectLocalMode: proxyconfigapi.LocalModeNodeCIDR, + ClusterCIDR: "10.0.0.0/14", + }, + primaryIPFamily: v1.IPv6Protocol, + nodePodCIDRs: []string{"10.0.0.0/24"}, + // This will output a warning that there is no IPv6 CIDR but it + // will still use the provided IPv4 CIDR for IPv4. + expected: map[v1.IPFamily]proxyutil.LocalTrafficDetector{ + v1.IPv4Protocol: proxyutil.NewDetectLocalByCIDR("10.0.0.0/24"), + v1.IPv6Protocol: proxyutil.NewNoOpLocalDetector(), + }, }, { - name: "LocalModeNodeCIDR, IPv4 cluster with IPv6 config", - mode: proxyconfigapi.LocalModeNodeCIDR, - config: &proxyconfigapi.KubeProxyConfiguration{ClusterCIDR: "2002:0:0:1234::/64"}, - family: v1.IPv4Protocol, - expected: proxyutil.NewNoOpLocalDetector(), - nodePodCIDRs: []string{"2002::1234:abcd:ffff:0:0/96"}, + name: "LocalModeNodeCIDR, single-stack IPv4 cluster with single-stack IPv6 config", + config: &proxyconfigapi.KubeProxyConfiguration{ + DetectLocalMode: proxyconfigapi.LocalModeNodeCIDR, + ClusterCIDR: "2002:0:0:1234::/64", + }, + primaryIPFamily: v1.IPv4Protocol, + nodePodCIDRs: []string{"2002::1234:abcd:ffff:0:0/96"}, + // This will output a warning that there is no IPv4 CIDR but it + // will still use the provided IPv6 CIDR for IPv6. + expected: map[v1.IPFamily]proxyutil.LocalTrafficDetector{ + v1.IPv4Protocol: proxyutil.NewNoOpLocalDetector(), + v1.IPv6Protocol: proxyutil.NewDetectLocalByCIDR("2002::1234:abcd:ffff:0:0/96"), + }, }, { - name: "LocalModeNodeCIDR, IPv6 kube-proxy in dual-stack IPv4-primary cluster", - mode: proxyconfigapi.LocalModeNodeCIDR, - config: &proxyconfigapi.KubeProxyConfiguration{ClusterCIDR: "10.0.0.0/14,2002:0:0:1234::/64"}, - family: v1.IPv6Protocol, - expected: proxyutil.NewDetectLocalByCIDR("2002::1234:abcd:ffff:0:0/96"), - nodePodCIDRs: []string{"10.0.0.0/24", "2002::1234:abcd:ffff:0:0/96"}, + name: "LocalModeNodeCIDR, dual-stack IPv4-primary cluster", + config: &proxyconfigapi.KubeProxyConfiguration{ + DetectLocalMode: proxyconfigapi.LocalModeNodeCIDR, + ClusterCIDR: "10.0.0.0/14,2002:0:0:1234::/64", + }, + primaryIPFamily: v1.IPv4Protocol, + nodePodCIDRs: []string{"10.0.0.0/24", "2002::1234:abcd:ffff:0:0/96"}, + expected: map[v1.IPFamily]proxyutil.LocalTrafficDetector{ + v1.IPv4Protocol: proxyutil.NewDetectLocalByCIDR("10.0.0.0/24"), + v1.IPv6Protocol: proxyutil.NewDetectLocalByCIDR("2002::1234:abcd:ffff:0:0/96"), + }, }, { - name: "LocalModeNodeCIDR, no PodCIDRs", - mode: proxyconfigapi.LocalModeNodeCIDR, - config: &proxyconfigapi.KubeProxyConfiguration{ClusterCIDR: ""}, - family: v1.IPv4Protocol, - expected: proxyutil.NewNoOpLocalDetector(), - nodePodCIDRs: []string{}, + name: "LocalModeNodeCIDR, dual-stack IPv6-primary cluster", + config: &proxyconfigapi.KubeProxyConfiguration{ + DetectLocalMode: proxyconfigapi.LocalModeNodeCIDR, + ClusterCIDR: "2002:0:0:1234::/64,10.0.0.0/14", + }, + primaryIPFamily: v1.IPv6Protocol, + nodePodCIDRs: []string{"2002::1234:abcd:ffff:0:0/96", "10.0.0.0/24"}, + expected: map[v1.IPFamily]proxyutil.LocalTrafficDetector{ + v1.IPv4Protocol: proxyutil.NewDetectLocalByCIDR("10.0.0.0/24"), + v1.IPv6Protocol: proxyutil.NewDetectLocalByCIDR("2002::1234:abcd:ffff:0:0/96"), + }, + }, + { + name: "LocalModeNodeCIDR, IPv6-primary kube-proxy / IPv4-primary config", + config: &proxyconfigapi.KubeProxyConfiguration{ + DetectLocalMode: proxyconfigapi.LocalModeNodeCIDR, + ClusterCIDR: "10.0.0.0/14,2002:0:0:1234::/64", + }, + primaryIPFamily: v1.IPv6Protocol, + nodePodCIDRs: []string{"10.0.0.0/24", "2002::1234:abcd:ffff:0:0/96"}, + expected: map[v1.IPFamily]proxyutil.LocalTrafficDetector{ + v1.IPv4Protocol: proxyutil.NewDetectLocalByCIDR("10.0.0.0/24"), + v1.IPv6Protocol: proxyutil.NewDetectLocalByCIDR("2002::1234:abcd:ffff:0:0/96"), + }, + }, + { + name: "LocalModeNodeCIDR, no PodCIDRs", + config: &proxyconfigapi.KubeProxyConfiguration{ + DetectLocalMode: proxyconfigapi.LocalModeNodeCIDR, + ClusterCIDR: "", + }, + primaryIPFamily: v1.IPv4Protocol, + nodePodCIDRs: []string{}, + expected: map[v1.IPFamily]proxyutil.LocalTrafficDetector{ + v1.IPv4Protocol: proxyutil.NewNoOpLocalDetector(), + v1.IPv6Protocol: proxyutil.NewNoOpLocalDetector(), + }, }, // unknown mode { - name: "unknown LocalMode", - mode: proxyconfigapi.LocalMode("abcd"), - config: &proxyconfigapi.KubeProxyConfiguration{ClusterCIDR: "10.0.0.0/14"}, - family: v1.IPv4Protocol, - expected: proxyutil.NewNoOpLocalDetector(), - }, - // LocalModeBridgeInterface - { - name: "LocalModeBrideInterface", - mode: proxyconfigapi.LocalModeBridgeInterface, + name: "unknown LocalMode", config: &proxyconfigapi.KubeProxyConfiguration{ - DetectLocal: proxyconfigapi.DetectLocalConfiguration{BridgeInterface: "eth"}, + DetectLocalMode: proxyconfigapi.LocalMode("abcd"), + ClusterCIDR: "10.0.0.0/14", }, - family: v1.IPv4Protocol, - expected: proxyutil.NewDetectLocalByBridgeInterface("eth"), - }, - { - name: "LocalModeBridgeInterface, strange bridge name", - mode: proxyconfigapi.LocalModeBridgeInterface, - config: &proxyconfigapi.KubeProxyConfiguration{ - DetectLocal: proxyconfigapi.DetectLocalConfiguration{BridgeInterface: "1234567890123456789"}, + primaryIPFamily: v1.IPv4Protocol, + expected: map[v1.IPFamily]proxyutil.LocalTrafficDetector{ + v1.IPv4Protocol: proxyutil.NewNoOpLocalDetector(), + v1.IPv6Protocol: proxyutil.NewNoOpLocalDetector(), }, - family: v1.IPv4Protocol, - expected: proxyutil.NewDetectLocalByBridgeInterface("1234567890123456789"), - }, - // LocalModeInterfaceNamePrefix - { - name: "LocalModeInterfaceNamePrefix", - mode: proxyconfigapi.LocalModeInterfaceNamePrefix, - config: &proxyconfigapi.KubeProxyConfiguration{ - DetectLocal: proxyconfigapi.DetectLocalConfiguration{InterfaceNamePrefix: "eth"}, - }, - family: v1.IPv4Protocol, - expected: proxyutil.NewDetectLocalByInterfaceNamePrefix("eth"), - }, - { - name: "LocalModeInterfaceNamePrefix, strange interface name", - mode: proxyconfigapi.LocalModeInterfaceNamePrefix, - config: &proxyconfigapi.KubeProxyConfiguration{ - DetectLocal: proxyconfigapi.DetectLocalConfiguration{InterfaceNamePrefix: "1234567890123456789"}, - }, - family: v1.IPv4Protocol, - expected: proxyutil.NewDetectLocalByInterfaceNamePrefix("1234567890123456789"), - }, - } - for _, c := range cases { - t.Run(c.name, func(t *testing.T) { - logger, _ := ktesting.NewTestContext(t) - r := getLocalDetector(logger, c.family, c.mode, c.config, c.nodePodCIDRs) - if !reflect.DeepEqual(r, c.expected) { - t.Errorf("Unexpected detect-local implementation, expected: %q, got: %q", c.expected, r) - } - }) - } -} - -func Test_getDualStackLocalDetectorTuple(t *testing.T) { - cases := []struct { - name string - mode proxyconfigapi.LocalMode - config *proxyconfigapi.KubeProxyConfiguration - expected [2]proxyutil.LocalTrafficDetector - nodePodCIDRs []string - }{ - // LocalModeClusterCIDR - { - name: "LocalModeClusterCIDR, dual-stack IPv4-primary cluster", - mode: proxyconfigapi.LocalModeClusterCIDR, - config: &proxyconfigapi.KubeProxyConfiguration{ClusterCIDR: "10.0.0.0/14,2002:0:0:1234::/64"}, - expected: [2]proxyutil.LocalTrafficDetector{ - proxyutil.NewDetectLocalByCIDR("10.0.0.0/14"), - proxyutil.NewDetectLocalByCIDR("2002:0:0:1234::/64"), - }, - }, - { - name: "LocalModeClusterCIDR, dual-stack IPv6-primary cluster", - mode: proxyconfigapi.LocalModeClusterCIDR, - config: &proxyconfigapi.KubeProxyConfiguration{ClusterCIDR: "2002:0:0:1234::/64,10.0.0.0/14"}, - expected: [2]proxyutil.LocalTrafficDetector{ - proxyutil.NewDetectLocalByCIDR("10.0.0.0/14"), - proxyutil.NewDetectLocalByCIDR("2002:0:0:1234::/64"), - }, - }, - { - name: "LocalModeClusterCIDR, single-stack IPv4 cluster", - mode: proxyconfigapi.LocalModeClusterCIDR, - config: &proxyconfigapi.KubeProxyConfiguration{ClusterCIDR: "10.0.0.0/14"}, - expected: [2]proxyutil.LocalTrafficDetector{ - proxyutil.NewDetectLocalByCIDR("10.0.0.0/14"), - proxyutil.NewNoOpLocalDetector(), - }, - }, - { - name: "LocalModeClusterCIDR, single-stack IPv6 cluster", - mode: proxyconfigapi.LocalModeClusterCIDR, - config: &proxyconfigapi.KubeProxyConfiguration{ClusterCIDR: "2002:0:0:1234::/64"}, - expected: [2]proxyutil.LocalTrafficDetector{ - proxyutil.NewNoOpLocalDetector(), - proxyutil.NewDetectLocalByCIDR("2002:0:0:1234::/64"), - }, - }, - { - name: "LocalModeClusterCIDR, no ClusterCIDR", - mode: proxyconfigapi.LocalModeClusterCIDR, - config: &proxyconfigapi.KubeProxyConfiguration{ClusterCIDR: ""}, - expected: [2]proxyutil.LocalTrafficDetector{ - proxyutil.NewNoOpLocalDetector(), - proxyutil.NewNoOpLocalDetector(), - }, - }, - // LocalModeNodeCIDR - { - name: "LocalModeNodeCIDR, dual-stack IPv4-primary cluster", - mode: proxyconfigapi.LocalModeNodeCIDR, - config: &proxyconfigapi.KubeProxyConfiguration{ClusterCIDR: "10.0.0.0/14,2002:0:0:1234::/64"}, - expected: [2]proxyutil.LocalTrafficDetector{ - proxyutil.NewDetectLocalByCIDR("10.0.0.0/24"), - proxyutil.NewDetectLocalByCIDR("2002::1234:abcd:ffff:0:0/96"), - }, - nodePodCIDRs: []string{"10.0.0.0/24", "2002::1234:abcd:ffff:0:0/96"}, - }, - { - name: "LocalModeNodeCIDR, dual-stack IPv6-primary cluster", - mode: proxyconfigapi.LocalModeNodeCIDR, - config: &proxyconfigapi.KubeProxyConfiguration{ClusterCIDR: "2002:0:0:1234::/64,10.0.0.0/14"}, - expected: [2]proxyutil.LocalTrafficDetector{ - proxyutil.NewDetectLocalByCIDR("10.0.0.0/24"), - proxyutil.NewDetectLocalByCIDR("2002::1234:abcd:ffff:0:0/96"), - }, - nodePodCIDRs: []string{"2002::1234:abcd:ffff:0:0/96", "10.0.0.0/24"}, - }, - { - name: "LocalModeNodeCIDR, single-stack IPv4 cluster", - mode: proxyconfigapi.LocalModeNodeCIDR, - config: &proxyconfigapi.KubeProxyConfiguration{ClusterCIDR: "10.0.0.0/14"}, - expected: [2]proxyutil.LocalTrafficDetector{ - proxyutil.NewDetectLocalByCIDR("10.0.0.0/24"), - proxyutil.NewNoOpLocalDetector(), - }, - nodePodCIDRs: []string{"10.0.0.0/24"}, - }, - { - name: "LocalModeNodeCIDR, single-stack IPv6 cluster", - mode: proxyconfigapi.LocalModeNodeCIDR, - config: &proxyconfigapi.KubeProxyConfiguration{ClusterCIDR: "2002:0:0:1234::/64"}, - expected: [2]proxyutil.LocalTrafficDetector{ - proxyutil.NewNoOpLocalDetector(), - proxyutil.NewDetectLocalByCIDR("2002::1234:abcd:ffff:0:0/96"), - }, - nodePodCIDRs: []string{"2002::1234:abcd:ffff:0:0/96"}, - }, - { - name: "LocalModeNodeCIDR, no PodCIDRs", - mode: proxyconfigapi.LocalModeNodeCIDR, - config: &proxyconfigapi.KubeProxyConfiguration{ClusterCIDR: ""}, - expected: [2]proxyutil.LocalTrafficDetector{ - proxyutil.NewNoOpLocalDetector(), - proxyutil.NewNoOpLocalDetector(), - }, - nodePodCIDRs: []string{}, }, // LocalModeBridgeInterface { name: "LocalModeBridgeInterface", - mode: proxyconfigapi.LocalModeBridgeInterface, config: &proxyconfigapi.KubeProxyConfiguration{ - DetectLocal: proxyconfigapi.DetectLocalConfiguration{BridgeInterface: "eth"}, + DetectLocalMode: proxyconfigapi.LocalModeBridgeInterface, + DetectLocal: proxyconfigapi.DetectLocalConfiguration{BridgeInterface: "eth"}, }, - expected: [2]proxyutil.LocalTrafficDetector{ - proxyutil.NewDetectLocalByBridgeInterface("eth"), - proxyutil.NewDetectLocalByBridgeInterface("eth"), + primaryIPFamily: v1.IPv4Protocol, + expected: map[v1.IPFamily]proxyutil.LocalTrafficDetector{ + v1.IPv4Protocol: proxyutil.NewDetectLocalByBridgeInterface("eth"), + v1.IPv6Protocol: proxyutil.NewDetectLocalByBridgeInterface("eth"), + }, + }, + { + name: "LocalModeBridgeInterface, strange bridge name", + config: &proxyconfigapi.KubeProxyConfiguration{ + DetectLocalMode: proxyconfigapi.LocalModeBridgeInterface, + DetectLocal: proxyconfigapi.DetectLocalConfiguration{BridgeInterface: "1234567890123456789"}, + }, + primaryIPFamily: v1.IPv4Protocol, + expected: map[v1.IPFamily]proxyutil.LocalTrafficDetector{ + v1.IPv4Protocol: proxyutil.NewDetectLocalByBridgeInterface("1234567890123456789"), + v1.IPv6Protocol: proxyutil.NewDetectLocalByBridgeInterface("1234567890123456789"), }, }, // LocalModeInterfaceNamePrefix { name: "LocalModeInterfaceNamePrefix", - mode: proxyconfigapi.LocalModeInterfaceNamePrefix, config: &proxyconfigapi.KubeProxyConfiguration{ - DetectLocal: proxyconfigapi.DetectLocalConfiguration{InterfaceNamePrefix: "veth"}, + DetectLocalMode: proxyconfigapi.LocalModeInterfaceNamePrefix, + DetectLocal: proxyconfigapi.DetectLocalConfiguration{InterfaceNamePrefix: "eth"}, }, - expected: [2]proxyutil.LocalTrafficDetector{ - proxyutil.NewDetectLocalByInterfaceNamePrefix("veth"), - proxyutil.NewDetectLocalByInterfaceNamePrefix("veth"), + primaryIPFamily: v1.IPv4Protocol, + expected: map[v1.IPFamily]proxyutil.LocalTrafficDetector{ + v1.IPv4Protocol: proxyutil.NewDetectLocalByInterfaceNamePrefix("eth"), + v1.IPv6Protocol: proxyutil.NewDetectLocalByInterfaceNamePrefix("eth"), + }, + }, + { + name: "LocalModeInterfaceNamePrefix, strange interface name", + config: &proxyconfigapi.KubeProxyConfiguration{ + DetectLocalMode: proxyconfigapi.LocalModeInterfaceNamePrefix, + DetectLocal: proxyconfigapi.DetectLocalConfiguration{InterfaceNamePrefix: "1234567890123456789"}, + }, + primaryIPFamily: v1.IPv4Protocol, + expected: map[v1.IPFamily]proxyutil.LocalTrafficDetector{ + v1.IPv4Protocol: proxyutil.NewDetectLocalByInterfaceNamePrefix("1234567890123456789"), + v1.IPv6Protocol: proxyutil.NewDetectLocalByInterfaceNamePrefix("1234567890123456789"), }, }, } for _, c := range cases { t.Run(c.name, func(t *testing.T) { logger, _ := ktesting.NewTestContext(t) - r := getDualStackLocalDetectorTuple(logger, c.mode, c.config, c.nodePodCIDRs) + r := getLocalDetectors(logger, c.primaryIPFamily, c.config, c.nodePodCIDRs) if !reflect.DeepEqual(r, c.expected) { t.Errorf("Unexpected detect-local implementation, expected: %q, got: %q", c.expected, r) } diff --git a/pkg/proxy/iptables/proxier.go b/pkg/proxy/iptables/proxier.go index b639a4a1f93..2f3862f5799 100644 --- a/pkg/proxy/iptables/proxier.go +++ b/pkg/proxy/iptables/proxier.go @@ -107,7 +107,7 @@ func NewDualStackProxier( masqueradeAll bool, localhostNodePorts bool, masqueradeBit int, - localDetectors [2]proxyutil.LocalTrafficDetector, + localDetectors map[v1.IPFamily]proxyutil.LocalTrafficDetector, hostname string, nodeIPs map[v1.IPFamily]net.IP, recorder events.EventRecorder, @@ -117,15 +117,17 @@ func NewDualStackProxier( ) (proxy.Provider, error) { // Create an ipv4 instance of the single-stack proxier ipv4Proxier, err := NewProxier(ctx, v1.IPv4Protocol, ipt[0], sysctl, - exec, syncPeriod, minSyncPeriod, masqueradeAll, localhostNodePorts, masqueradeBit, localDetectors[0], hostname, - nodeIPs[v1.IPv4Protocol], recorder, healthzServer, nodePortAddresses, initOnly) + exec, syncPeriod, minSyncPeriod, masqueradeAll, localhostNodePorts, masqueradeBit, + localDetectors[v1.IPv4Protocol], hostname, nodeIPs[v1.IPv4Protocol], + recorder, healthzServer, nodePortAddresses, initOnly) if err != nil { return nil, fmt.Errorf("unable to create ipv4 proxier: %v", err) } ipv6Proxier, err := NewProxier(ctx, v1.IPv6Protocol, ipt[1], sysctl, - exec, syncPeriod, minSyncPeriod, masqueradeAll, false, masqueradeBit, localDetectors[1], hostname, - nodeIPs[v1.IPv6Protocol], recorder, healthzServer, nodePortAddresses, initOnly) + exec, syncPeriod, minSyncPeriod, masqueradeAll, false, masqueradeBit, + localDetectors[v1.IPv6Protocol], hostname, nodeIPs[v1.IPv6Protocol], + recorder, healthzServer, nodePortAddresses, initOnly) if err != nil { return nil, fmt.Errorf("unable to create ipv6 proxier: %v", err) } diff --git a/pkg/proxy/ipvs/proxier.go b/pkg/proxy/ipvs/proxier.go index b1028dd8e51..eece2f0d2ab 100644 --- a/pkg/proxy/ipvs/proxier.go +++ b/pkg/proxy/ipvs/proxier.go @@ -126,7 +126,7 @@ func NewDualStackProxier( udpTimeout time.Duration, masqueradeAll bool, masqueradeBit int, - localDetectors [2]proxyutil.LocalTrafficDetector, + localDetectors map[v1.IPFamily]proxyutil.LocalTrafficDetector, hostname string, nodeIPs map[v1.IPFamily]net.IP, recorder events.EventRecorder, @@ -139,7 +139,7 @@ func NewDualStackProxier( ipv4Proxier, err := NewProxier(ctx, v1.IPv4Protocol, ipt[0], ipvs, ipset, sysctl, exec, syncPeriod, minSyncPeriod, filterCIDRs(false, excludeCIDRs), strictARP, tcpTimeout, tcpFinTimeout, udpTimeout, masqueradeAll, masqueradeBit, - localDetectors[0], hostname, nodeIPs[v1.IPv4Protocol], recorder, + localDetectors[v1.IPv4Protocol], hostname, nodeIPs[v1.IPv4Protocol], recorder, healthzServer, scheduler, nodePortAddresses, initOnly) if err != nil { return nil, fmt.Errorf("unable to create ipv4 proxier: %v", err) @@ -148,7 +148,7 @@ func NewDualStackProxier( ipv6Proxier, err := NewProxier(ctx, v1.IPv6Protocol, ipt[1], ipvs, ipset, sysctl, exec, syncPeriod, minSyncPeriod, filterCIDRs(true, excludeCIDRs), strictARP, tcpTimeout, tcpFinTimeout, udpTimeout, masqueradeAll, masqueradeBit, - localDetectors[1], hostname, nodeIPs[v1.IPv6Protocol], recorder, + localDetectors[v1.IPv6Protocol], hostname, nodeIPs[v1.IPv6Protocol], recorder, healthzServer, scheduler, nodePortAddresses, initOnly) if err != nil { return nil, fmt.Errorf("unable to create ipv6 proxier: %v", err) diff --git a/pkg/proxy/nftables/proxier.go b/pkg/proxy/nftables/proxier.go index 416f6199668..e4740310587 100644 --- a/pkg/proxy/nftables/proxier.go +++ b/pkg/proxy/nftables/proxier.go @@ -110,7 +110,7 @@ func NewDualStackProxier( minSyncPeriod time.Duration, masqueradeAll bool, masqueradeBit int, - localDetectors [2]proxyutil.LocalTrafficDetector, + localDetectors map[v1.IPFamily]proxyutil.LocalTrafficDetector, hostname string, nodeIPs map[v1.IPFamily]net.IP, recorder events.EventRecorder, @@ -120,15 +120,17 @@ func NewDualStackProxier( ) (proxy.Provider, error) { // Create an ipv4 instance of the single-stack proxier ipv4Proxier, err := NewProxier(ctx, v1.IPv4Protocol, sysctl, - syncPeriod, minSyncPeriod, masqueradeAll, masqueradeBit, localDetectors[0], hostname, - nodeIPs[v1.IPv4Protocol], recorder, healthzServer, nodePortAddresses, initOnly) + syncPeriod, minSyncPeriod, masqueradeAll, masqueradeBit, + localDetectors[v1.IPv4Protocol], hostname, nodeIPs[v1.IPv4Protocol], + recorder, healthzServer, nodePortAddresses, initOnly) if err != nil { return nil, fmt.Errorf("unable to create ipv4 proxier: %v", err) } ipv6Proxier, err := NewProxier(ctx, v1.IPv6Protocol, sysctl, - syncPeriod, minSyncPeriod, masqueradeAll, masqueradeBit, localDetectors[1], hostname, - nodeIPs[v1.IPv6Protocol], recorder, healthzServer, nodePortAddresses, initOnly) + syncPeriod, minSyncPeriod, masqueradeAll, masqueradeBit, + localDetectors[v1.IPv6Protocol], hostname, nodeIPs[v1.IPv6Protocol], + recorder, healthzServer, nodePortAddresses, initOnly) if err != nil { return nil, fmt.Errorf("unable to create ipv6 proxier: %v", err) }