Skip to content

Commit

Permalink
Merge pull request kubernetes#95400 from tssurya/detect-local-traffic…
Browse files Browse the repository at this point in the history
…-using-interface

Detect local traffic using interface
  • Loading branch information
k8s-ci-robot authored and wedaly committed Mar 28, 2022
1 parent c285e78 commit b1ee49c
Show file tree
Hide file tree
Showing 15 changed files with 536 additions and 5 deletions.
4 changes: 3 additions & 1 deletion cmd/kube-proxy/app/server.go
Expand Up @@ -206,7 +206,9 @@ func (o *Options) AddFlags(fs *pflag.FlagSet) {
fs.BoolVar(&o.config.EnableProfiling, "profiling", o.config.EnableProfiling, "If true enables profiling via web interface on /debug/pprof handler.")

fs.Float32Var(&o.config.ClientConnection.QPS, "kube-api-qps", o.config.ClientConnection.QPS, "QPS to use while talking with kubernetes apiserver")
fs.Var(&o.config.DetectLocalMode, "detect-local-mode", "Mode to use to detect local traffic")
fs.Var(&o.config.DetectLocalMode, "detect-local-mode", "Mode to use to detect local traffic. This parameter is ignored if a config file is specified by --config.")
fs.StringVar(&o.config.DetectLocal.BridgeInterface, "pod-bridge-interface", o.config.DetectLocal.BridgeInterface, "A bridge interface name in the cluster. Kube-proxy considers traffic as local if originating from an interface which matches the value. This argument should be set if DetectLocalMode is set to BridgeInterface.")
fs.StringVar(&o.config.DetectLocal.InterfaceNamePrefix, "pod-interface-name-prefix", o.config.DetectLocal.InterfaceNamePrefix, "An interface prefix in the cluster. Kube-proxy considers traffic as local if originating from interfaces that match the given prefix. This argument should be set if DetectLocalMode is set to InterfaceNamePrefix.")
}

// NewOptions returns initialized Options
Expand Down
19 changes: 18 additions & 1 deletion cmd/kube-proxy/app/server_others.go
Expand Up @@ -436,7 +436,7 @@ func detectNumCPU() int {
func getDetectLocalMode(config *proxyconfigapi.KubeProxyConfiguration) (proxyconfigapi.LocalMode, error) {
mode := config.DetectLocalMode
switch mode {
case proxyconfigapi.LocalModeClusterCIDR, proxyconfigapi.LocalModeNodeCIDR:
case proxyconfigapi.LocalModeClusterCIDR, proxyconfigapi.LocalModeNodeCIDR, proxyconfigapi.LocalModeBridgeInterface, proxyconfigapi.LocalModeInterfaceNamePrefix:
return mode, nil
default:
if strings.TrimSpace(mode.String()) != "" {
Expand All @@ -461,6 +461,16 @@ func getLocalDetector(mode proxyconfigapi.LocalMode, config *proxyconfigapi.Kube
break
}
return proxyutiliptables.NewDetectLocalByCIDR(nodeInfo.Spec.PodCIDR, ipt)
case proxyconfigapi.LocalModeBridgeInterface:
if len(strings.TrimSpace(config.DetectLocal.BridgeInterface)) == 0 {
return nil, fmt.Errorf("Detect-local-mode set to BridgeInterface, but no bridge-interface-name %s is defined", config.DetectLocal.BridgeInterface)
}
return proxyutiliptables.NewDetectLocalByBridgeInterface(config.DetectLocal.BridgeInterface)
case proxyconfigapi.LocalModeInterfaceNamePrefix:
if len(strings.TrimSpace(config.DetectLocal.InterfaceNamePrefix)) == 0 {
return nil, fmt.Errorf("Detect-local-mode set to InterfaceNamePrefix, but no interface-prefix %s is defined", config.DetectLocal.InterfaceNamePrefix)
}
return proxyutiliptables.NewDetectLocalByInterfaceNamePrefix(config.DetectLocal.InterfaceNamePrefix)
}
klog.V(0).InfoS("Defaulting to no-op detect-local", "detect-local-mode", string(mode))
return proxyutiliptables.NewNoOpLocalDetector(), nil
Expand Down Expand Up @@ -518,6 +528,13 @@ func getDualStackLocalDetectorTuple(mode proxyconfigapi.LocalMode, config *proxy
}
}
return localDetectors, err
case proxyconfigapi.LocalModeBridgeInterface, proxyconfigapi.LocalModeInterfaceNamePrefix:
localDetector, err := getLocalDetector(mode, config, ipt[0], nodeInfo)
if err == nil {
localDetectors[0] = localDetector
localDetectors[1] = localDetector
}
return localDetectors, err
default:
klog.InfoS("Unknown detect-local-mode", "detect-local-mode", mode)
}
Expand Down
94 changes: 94 additions & 0 deletions cmd/kube-proxy/app/server_others_test.go
Expand Up @@ -196,6 +196,16 @@ func Test_getDetectLocalMode(t *testing.T) {
expected: proxyconfigapi.LocalModeClusterCIDR,
errExpected: false,
},
{
detectLocal: string(proxyconfigapi.LocalModeInterfaceNamePrefix),
expected: proxyconfigapi.LocalModeInterfaceNamePrefix,
errExpected: false,
},
{
detectLocal: string(proxyconfigapi.LocalModeBridgeInterface),
expected: proxyconfigapi.LocalModeBridgeInterface,
errExpected: false,
},
{
detectLocal: "abcd",
expected: proxyconfigapi.LocalMode("abcd"),
Expand Down Expand Up @@ -450,6 +460,54 @@ func Test_getLocalDetector(t *testing.T) {
expected: proxyutiliptables.NewNoOpLocalDetector(),
errExpected: false,
},
// LocalModeBridgeInterface, nodeInfo and ipt are not needed for these cases
{
mode: proxyconfigapi.LocalModeBridgeInterface,
config: &proxyconfigapi.KubeProxyConfiguration{
DetectLocal: proxyconfigapi.DetectLocalConfiguration{BridgeInterface: "eth"},
},
expected: resolveLocalDetector(t)(proxyutiliptables.NewDetectLocalByBridgeInterface("eth")),
errExpected: false,
},
{
mode: proxyconfigapi.LocalModeBridgeInterface,
config: &proxyconfigapi.KubeProxyConfiguration{
DetectLocal: proxyconfigapi.DetectLocalConfiguration{BridgeInterface: ""},
},
errExpected: true,
},
{
mode: proxyconfigapi.LocalModeBridgeInterface,
config: &proxyconfigapi.KubeProxyConfiguration{
DetectLocal: proxyconfigapi.DetectLocalConfiguration{BridgeInterface: "1234567890123456789"},
},
expected: resolveLocalDetector(t)(proxyutiliptables.NewDetectLocalByBridgeInterface("1234567890123456789")),
errExpected: false,
},
// LocalModeInterfaceNamePrefix, nodeInfo and ipt are not needed for these cases
{
mode: proxyconfigapi.LocalModeInterfaceNamePrefix,
config: &proxyconfigapi.KubeProxyConfiguration{
DetectLocal: proxyconfigapi.DetectLocalConfiguration{InterfaceNamePrefix: "eth"},
},
expected: resolveLocalDetector(t)(proxyutiliptables.NewDetectLocalByInterfaceNamePrefix("eth")),
errExpected: false,
},
{
mode: proxyconfigapi.LocalModeInterfaceNamePrefix,
config: &proxyconfigapi.KubeProxyConfiguration{
DetectLocal: proxyconfigapi.DetectLocalConfiguration{InterfaceNamePrefix: ""},
},
errExpected: true,
},
{
mode: proxyconfigapi.LocalModeInterfaceNamePrefix,
config: &proxyconfigapi.KubeProxyConfiguration{
DetectLocal: proxyconfigapi.DetectLocalConfiguration{InterfaceNamePrefix: "1234567890123456789"},
},
expected: resolveLocalDetector(t)(proxyutiliptables.NewDetectLocalByInterfaceNamePrefix("1234567890123456789")),
errExpected: false,
},
}
for i, c := range cases {
r, err := getLocalDetector(c.mode, c.config, c.ipt, c.nodeInfo)
Expand Down Expand Up @@ -587,6 +645,42 @@ func Test_getDualStackLocalDetectorTuple(t *testing.T) {
expected: [2]proxyutiliptables.LocalTrafficDetector{proxyutiliptables.NewNoOpLocalDetector(), proxyutiliptables.NewNoOpLocalDetector()},
errExpected: false,
},
// LocalModeBridgeInterface, nodeInfo and ipt are not needed for these cases
{
mode: proxyconfigapi.LocalModeBridgeInterface,
config: &proxyconfigapi.KubeProxyConfiguration{
DetectLocal: proxyconfigapi.DetectLocalConfiguration{BridgeInterface: "eth"},
},
expected: resolveDualStackLocalDetectors(t)(
proxyutiliptables.NewDetectLocalByBridgeInterface("eth"))(
proxyutiliptables.NewDetectLocalByBridgeInterface("eth")),
errExpected: false,
},
{
mode: proxyconfigapi.LocalModeBridgeInterface,
config: &proxyconfigapi.KubeProxyConfiguration{
DetectLocal: proxyconfigapi.DetectLocalConfiguration{BridgeInterface: ""},
},
errExpected: true,
},
// LocalModeInterfaceNamePrefix, nodeInfo and ipt are not needed for these cases
{
mode: proxyconfigapi.LocalModeInterfaceNamePrefix,
config: &proxyconfigapi.KubeProxyConfiguration{
DetectLocal: proxyconfigapi.DetectLocalConfiguration{InterfaceNamePrefix: "veth"},
},
expected: resolveDualStackLocalDetectors(t)(
proxyutiliptables.NewDetectLocalByInterfaceNamePrefix("veth"))(
proxyutiliptables.NewDetectLocalByInterfaceNamePrefix("veth")),
errExpected: false,
},
{
mode: proxyconfigapi.LocalModeInterfaceNamePrefix,
config: &proxyconfigapi.KubeProxyConfiguration{
DetectLocal: proxyconfigapi.DetectLocalConfiguration{InterfaceNamePrefix: ""},
},
errExpected: true,
},
}
for i, c := range cases {
r, err := getDualStackLocalDetectorTuple(c.mode, c.config, c.ipt, c.nodeInfo)
Expand Down
9 changes: 8 additions & 1 deletion cmd/kube-proxy/app/server_test.go
Expand Up @@ -123,6 +123,9 @@ oomScoreAdj: 17
portRange: "2-7"
udpIdleTimeout: 123ms
detectLocalMode: "ClusterCIDR"
detectLocal:
bridgeInterface: "cbr0"
interfaceNamePrefix: "veth"
nodePortAddresses:
- "10.20.30.40/16"
- "fd00:1::0/64"
Expand Down Expand Up @@ -264,6 +267,10 @@ nodePortAddresses:
UDPIdleTimeout: metav1.Duration{Duration: 123 * time.Millisecond},
NodePortAddresses: []string{"10.20.30.40/16", "fd00:1::0/64"},
DetectLocalMode: kubeproxyconfig.LocalModeClusterCIDR,
DetectLocal: kubeproxyconfig.DetectLocalConfiguration{
BridgeInterface: string("cbr0"),
InterfaceNamePrefix: string("veth"),
},
}

options := NewOptions()
Expand Down Expand Up @@ -451,7 +458,7 @@ mode: ""
nodePortAddresses: null
oomScoreAdj: -999
portRange: ""
detectLocalMode: "ClusterCIDR"
detectLocalMode: "BridgeInterface"
udpIdleTimeout: 250ms`)
if err != nil {
return nil, "", fmt.Errorf("unexpected error when writing content to temp kube-proxy config file: %v", err)
Expand Down
Expand Up @@ -14,6 +14,9 @@ conntrack:
min: 131072
tcpCloseWaitTimeout: 1h0m0s
tcpEstablishedTimeout: 24h0m0s
detectLocal:
bridgeInterface: ""
interfaceNamePrefix: ""
detectLocalMode: ""
enableProfiling: false
healthzBindAddress: 0.0.0.0:10256
Expand Down
Expand Up @@ -14,6 +14,9 @@ conntrack:
min: 131072
tcpCloseWaitTimeout: 1h0m0s
tcpEstablishedTimeout: 24h0m0s
detectLocal:
bridgeInterface: ""
interfaceNamePrefix: ""
detectLocalMode: ""
enableProfiling: false
healthzBindAddress: 0.0.0.0:10256
Expand Down
20 changes: 18 additions & 2 deletions pkg/proxy/apis/config/types.go
Expand Up @@ -101,6 +101,18 @@ type KubeProxyWinkernelConfiguration struct {
EnableDSR bool
}

// DetectLocalConfiguration contains optional settings related to DetectLocalMode option
type DetectLocalConfiguration struct {
// BridgeInterface is a string argument which represents a single bridge interface name.
// Kube-proxy considers traffic as local if originating from this given bridge.
// This argument should be set if DetectLocalMode is set to BridgeInterface.
BridgeInterface string
// InterfaceNamePrefix is a string argument which represents a single interface prefix name.
// Kube-proxy considers traffic as local if originating from one or more interfaces which match
// the given prefix. This argument should be set if DetectLocalMode is set to InterfaceNamePrefix.
InterfaceNamePrefix string
}

// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object

// KubeProxyConfiguration contains everything necessary to configure the
Expand Down Expand Up @@ -168,6 +180,8 @@ type KubeProxyConfiguration struct {
ShowHiddenMetricsForVersion string
// DetectLocalMode determines mode to use for detecting local traffic, defaults to LocalModeClusterCIDR
DetectLocalMode LocalMode
// DetectLocal contains optional configuration settings related to DetectLocalMode.
DetectLocal DetectLocalConfiguration
}

// ProxyMode represents modes used by the Kubernetes proxy server. Currently, three modes of proxy are available in
Expand Down Expand Up @@ -198,8 +212,10 @@ type LocalMode string

// Currently supported modes for LocalMode
const (
LocalModeClusterCIDR LocalMode = "ClusterCIDR"
LocalModeNodeCIDR LocalMode = "NodeCIDR"
LocalModeClusterCIDR LocalMode = "ClusterCIDR"
LocalModeNodeCIDR LocalMode = "NodeCIDR"
LocalModeBridgeInterface LocalMode = "BridgeInterface"
LocalModeInterfaceNamePrefix LocalMode = "InterfaceNamePrefix"
)

// IPVSSchedulerMethod is the algorithm for allocating TCP connections and
Expand Down
38 changes: 38 additions & 0 deletions pkg/proxy/apis/config/v1alpha1/zz_generated.conversion.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 14 additions & 0 deletions pkg/proxy/apis/config/validation/validation.go
Expand Up @@ -102,6 +102,12 @@ func Validate(config *kubeproxyconfig.KubeProxyConfiguration) field.ErrorList {

allErrs = append(allErrs, validateKubeProxyNodePortAddress(config.NodePortAddresses, newPath.Child("NodePortAddresses"))...)
allErrs = append(allErrs, validateShowHiddenMetricsVersion(config.ShowHiddenMetricsForVersion, newPath.Child("ShowHiddenMetricsForVersion"))...)
if config.DetectLocalMode == kubeproxyconfig.LocalModeBridgeInterface {
allErrs = append(allErrs, validateInterface(config.DetectLocal.BridgeInterface, newPath.Child("InterfaceName"))...)
}
if config.DetectLocalMode == kubeproxyconfig.LocalModeInterfaceNamePrefix {
allErrs = append(allErrs, validateInterface(config.DetectLocal.InterfaceNamePrefix, newPath.Child("InterfacePrefix"))...)
}

return allErrs
}
Expand Down Expand Up @@ -317,3 +323,11 @@ func validateShowHiddenMetricsVersion(version string, fldPath *field.Path) field

return allErrs
}

func validateInterface(iface string, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
if len(iface) == 0 {
allErrs = append(allErrs, field.Invalid(fldPath, iface, "must not be empty"))
}
return allErrs
}

0 comments on commit b1ee49c

Please sign in to comment.