diff --git a/cmd/kube-proxy/app/server_others.go b/cmd/kube-proxy/app/server_others.go index 026b2585fb9..9c1cf2295fc 100644 --- a/cmd/kube-proxy/app/server_others.go +++ b/cmd/kube-proxy/app/server_others.go @@ -302,6 +302,7 @@ func newProxyServer( healthzServer, config.IPVS.Scheduler, config.NodePortAddresses, + kernelHandler, ) } else { var localDetector proxyutiliptables.LocalTrafficDetector @@ -332,6 +333,7 @@ func newProxyServer( healthzServer, config.IPVS.Scheduler, config.NodePortAddresses, + kernelHandler, ) } if err != nil { diff --git a/pkg/proxy/ipvs/proxier.go b/pkg/proxy/ipvs/proxier.go index cbe0545d493..d678caecbfb 100644 --- a/pkg/proxy/ipvs/proxier.go +++ b/pkg/proxy/ipvs/proxier.go @@ -88,6 +88,8 @@ const ( // DefaultDummyDevice is the default dummy interface which ipvs service address will bind to it. DefaultDummyDevice = "kube-ipvs0" + + connReuseMinSupportedKernelVersion = "4.1" ) // iptablesJumpChain is tables of iptables chains that ipvs proxier used to install iptables or cleanup iptables. @@ -342,6 +344,7 @@ func NewProxier(ipt utiliptables.Interface, healthzServer healthcheck.ProxierHealthUpdater, scheduler string, nodePortAddresses []string, + kernelHandler KernelHandler, ) (*Proxier, error) { // Set the route_localnet sysctl we need for if val, _ := sysctl.GetSysctl(sysctlRouteLocalnet); val != 1 { @@ -364,10 +367,22 @@ func NewProxier(ipt utiliptables.Interface, } } - // Set the connection reuse mode - if val, _ := sysctl.GetSysctl(sysctlConnReuse); val != 0 { - if err := sysctl.SetSysctl(sysctlConnReuse, 0); err != nil { - return nil, fmt.Errorf("can't set sysctl %s: %v", sysctlConnReuse, err) + kernelVersionStr, err := kernelHandler.GetKernelVersion() + if err != nil { + return nil, fmt.Errorf("error determining kernel version to find required kernel modules for ipvs support: %v", err) + } + kernelVersion, err := version.ParseGeneric(kernelVersionStr) + if err != nil { + return nil, fmt.Errorf("error parsing kernel version %q: %v", kernelVersionStr, err) + } + if kernelVersion.LessThan(version.MustParseGeneric(connReuseMinSupportedKernelVersion)) { + klog.Errorf("can't set sysctl %s, kernel version must be at least %s", sysctlConnReuse, connReuseMinSupportedKernelVersion) + } else { + // Set the connection reuse mode + if val, _ := sysctl.GetSysctl(sysctlConnReuse); val != 0 { + if err := sysctl.SetSysctl(sysctlConnReuse, 0); err != nil { + return nil, fmt.Errorf("can't set sysctl %s: %v", sysctlConnReuse, err) + } } } @@ -504,6 +519,7 @@ func NewDualStackProxier( healthzServer healthcheck.ProxierHealthUpdater, scheduler string, nodePortAddresses []string, + kernelHandler KernelHandler, ) (proxy.Provider, error) { safeIpset := newSafeIpset(ipset) @@ -513,7 +529,7 @@ func NewDualStackProxier( exec, syncPeriod, minSyncPeriod, filterCIDRs(false, excludeCIDRs), strictARP, tcpTimeout, tcpFinTimeout, udpTimeout, masqueradeAll, masqueradeBit, localDetectors[0], hostname, nodeIP[0], - recorder, healthzServer, scheduler, nodePortAddresses) + recorder, healthzServer, scheduler, nodePortAddresses, kernelHandler) if err != nil { return nil, fmt.Errorf("unable to create ipv4 proxier: %v", err) } @@ -522,7 +538,7 @@ func NewDualStackProxier( exec, syncPeriod, minSyncPeriod, filterCIDRs(true, excludeCIDRs), strictARP, tcpTimeout, tcpFinTimeout, udpTimeout, masqueradeAll, masqueradeBit, localDetectors[1], hostname, nodeIP[1], - nil, nil, scheduler, nodePortAddresses) + nil, nil, scheduler, nodePortAddresses, kernelHandler) if err != nil { return nil, fmt.Errorf("unable to create ipv6 proxier: %v", err) }