Skip to content

Commit

Permalink
Merge pull request kubernetes#120995 from aroradaman/move-get-kernel-…
Browse files Browse the repository at this point in the history
…version

move GetKernelVersion out of pkg/proxy/ipvs
  • Loading branch information
k8s-ci-robot committed Oct 31, 2023
2 parents 07d2da7 + a375aa2 commit 0c93f40
Show file tree
Hide file tree
Showing 7 changed files with 204 additions and 80 deletions.
3 changes: 0 additions & 3 deletions cmd/kube-proxy/app/server_others.go
Expand Up @@ -210,7 +210,6 @@ func (s *ProxyServer) createProxier(config *proxyconfigapi.KubeProxyConfiguratio
return nil, fmt.Errorf("unable to create proxier: %v", err)
}
} else if config.Mode == proxyconfigapi.ProxyModeIPVS {
kernelHandler := ipvs.NewLinuxKernelHandler()
ipsetInterface := utilipset.New(execer)
ipvsInterface := utilipvs.New()
if err := ipvs.CanUseIPVSProxier(ipvsInterface, ipsetInterface, config.IPVS.Scheduler); err != nil {
Expand Down Expand Up @@ -248,7 +247,6 @@ func (s *ProxyServer) createProxier(config *proxyconfigapi.KubeProxyConfiguratio
s.HealthzServer,
config.IPVS.Scheduler,
config.NodePortAddresses,
kernelHandler,
initOnly,
)
} else {
Expand Down Expand Up @@ -281,7 +279,6 @@ func (s *ProxyServer) createProxier(config *proxyconfigapi.KubeProxyConfiguratio
s.HealthzServer,
config.IPVS.Scheduler,
config.NodePortAddresses,
kernelHandler,
initOnly,
)
}
Expand Down
38 changes: 10 additions & 28 deletions pkg/kubelet/sysctl/safe_sysctls.go
Expand Up @@ -17,12 +17,11 @@ limitations under the License.
package sysctl

import (
"fmt"
goruntime "runtime"

"k8s.io/apimachinery/pkg/util/version"
"k8s.io/klog/v2"
"k8s.io/kubernetes/pkg/proxy/ipvs"
utilkernel "k8s.io/kubernetes/pkg/util/kernel"
)

type sysctl struct {
Expand All @@ -44,27 +43,22 @@ var safeSysctls = []sysctl{
}, {
name: "net.ipv4.ip_unprivileged_port_start",
}, {
name: "net.ipv4.ip_local_reserved_ports",
// refer to https://github.com/torvalds/linux/commit/122ff243f5f104194750ecbc76d5946dd1eec934.
kernel: "3.16",
name: "net.ipv4.ip_local_reserved_ports",
kernel: utilkernel.IPLocalReservedPortsNamespacedKernelVersion,
}, {
name: "net.ipv4.tcp_keepalive_time",
// refer to https://github.com/torvalds/linux/commit/13b287e8d1cad951634389f85b8c9b816bd3bb1e.
kernel: "4.5",
name: "net.ipv4.tcp_keepalive_time",
kernel: utilkernel.TCPKeepAliveTimeNamespacedKernelVersion,
}, {
// refer to https://github.com/torvalds/linux/commit/1e579caa18b96f9eb18f4f5416658cd15f37c062.
name: "net.ipv4.tcp_fin_timeout",
kernel: "4.6",
kernel: utilkernel.TCPFinTimeoutNamespacedKernelVersion,
},
{
// refer to https://github.com/torvalds/linux/commit/b840d15d39128d08ed4486085e5507d2617b9ae1.
name: "net.ipv4.tcp_keepalive_intvl",
kernel: "4.5",
kernel: utilkernel.TCPKeepAliveIntervalNamespacedKernelVersion,
},
{
// refer to https://github.com/torvalds/linux/commit/9bd6861bd4326e3afd3f14a9ec8a723771fb20bb.
name: "net.ipv4.tcp_keepalive_probes",
kernel: "4.5",
kernel: utilkernel.TCPKeepAliveProbesNamespacedKernelVersion,
},
}

Expand All @@ -77,7 +71,8 @@ func SafeSysctlAllowlist() []string {
if goruntime.GOOS != "linux" {
return nil
}
return getSafeSysctlAllowlist(getKernelVersion)

return getSafeSysctlAllowlist(utilkernel.GetVersion)
}

func getSafeSysctlAllowlist(getVersion func() (*version.Version, error)) []string {
Expand All @@ -101,16 +96,3 @@ func getSafeSysctlAllowlist(getVersion func() (*version.Version, error)) []strin
}
return safeSysctlAllowlist
}

func getKernelVersion() (*version.Version, error) {
kernelVersionStr, err := ipvs.NewLinuxKernelHandler().GetKernelVersion()
if err != nil {
return nil, fmt.Errorf("failed to get kernel version: %w", err)
}

kernelVersion, err := version.ParseGeneric(kernelVersionStr)
if err != nil {
return nil, fmt.Errorf("failed to parse kernel version: %w", err)
}
return kernelVersion, nil
}
60 changes: 11 additions & 49 deletions pkg/proxy/ipvs/proxier.go
Expand Up @@ -22,7 +22,6 @@ import (
"fmt"
"io"
"net"
"os"
"reflect"
"strconv"
"strings"
Expand Down Expand Up @@ -53,6 +52,7 @@ import (
proxyutiliptables "k8s.io/kubernetes/pkg/proxy/util/iptables"
"k8s.io/kubernetes/pkg/util/async"
utiliptables "k8s.io/kubernetes/pkg/util/iptables"
utilkernel "k8s.io/kubernetes/pkg/util/kernel"
)

const (
Expand Down Expand Up @@ -93,11 +93,6 @@ const (

// defaultDummyDevice is the default dummy interface which ipvs service address will bind to it.
defaultDummyDevice = "kube-ipvs0"

connReuseMinSupportedKernelVersion = "4.1"

// https://github.com/torvalds/linux/commit/35dfb013149f74c2be1ff9c78f14e6a3cd1539d1
connReuseFixedKernelVersion = "5.9"
)

// iptablesJumpChain is tables of iptables chains that ipvs proxier used to install iptables or cleanup iptables.
Expand Down Expand Up @@ -339,25 +334,21 @@ func NewProxier(ipFamily v1.IPFamily,
healthzServer *healthcheck.ProxierHealthServer,
scheduler string,
nodePortAddressStrings []string,
kernelHandler KernelHandler,
initOnly bool,
) (*Proxier, error) {
// Set the conntrack sysctl we need for
if err := proxyutil.EnsureSysctl(sysctl, sysctlVSConnTrack, 1); err != nil {
return nil, err
}

kernelVersionStr, err := kernelHandler.GetKernelVersion()
kernelVersion, err := utilkernel.GetVersion()
if err != nil {
return nil, fmt.Errorf("error determining kernel version to find required kernel modules for ipvs support: %v", err)
return nil, fmt.Errorf("failed to get kernel version: %w", 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.ErrorS(nil, "Can't set sysctl, kernel version doesn't satisfy minimum version requirements", "sysctl", sysctlConnReuse, "minimumKernelVersion", connReuseMinSupportedKernelVersion)
} else if kernelVersion.AtLeast(version.MustParseGeneric(connReuseFixedKernelVersion)) {

if kernelVersion.LessThan(version.MustParseGeneric(utilkernel.IPVSConnReuseModeMinSupportedKernelVersion)) {
klog.ErrorS(nil, "Can't set sysctl, kernel version doesn't satisfy minimum version requirements", "sysctl", sysctlConnReuse, "minimumKernelVersion", utilkernel.IPVSConnReuseModeMinSupportedKernelVersion)
} else if kernelVersion.AtLeast(version.MustParseGeneric(utilkernel.IPVSConnReuseModeFixedKernelVersion)) {
// https://github.com/kubernetes/kubernetes/issues/93297
klog.V(2).InfoS("Left as-is", "sysctl", sysctlConnReuse)
} else {
Expand Down Expand Up @@ -495,7 +486,6 @@ func NewDualStackProxier(
healthzServer *healthcheck.ProxierHealthServer,
scheduler string,
nodePortAddresses []string,
kernelHandler KernelHandler,
initOnly bool,
) (proxy.Provider, error) {

Expand All @@ -505,17 +495,17 @@ func NewDualStackProxier(
ipv4Proxier, err := NewProxier(v1.IPv4Protocol, ipt[0], ipvs, safeIpset, sysctl,
exec, syncPeriod, minSyncPeriod, filterCIDRs(false, excludeCIDRs), strictARP,
tcpTimeout, tcpFinTimeout, udpTimeout, masqueradeAll, masqueradeBit,
localDetectors[0], hostname, nodeIPs[v1.IPv4Protocol],
recorder, healthzServer, scheduler, nodePortAddresses, kernelHandler, initOnly)
localDetectors[0], hostname, nodeIPs[v1.IPv4Protocol], recorder,
healthzServer, scheduler, nodePortAddresses, initOnly)
if err != nil {
return nil, fmt.Errorf("unable to create ipv4 proxier: %v", err)
}

ipv6Proxier, err := NewProxier(v1.IPv6Protocol, ipt[1], ipvs, safeIpset, sysctl,
exec, syncPeriod, minSyncPeriod, filterCIDRs(true, excludeCIDRs), strictARP,
tcpTimeout, tcpFinTimeout, udpTimeout, masqueradeAll, masqueradeBit,
localDetectors[1], hostname, nodeIPs[v1.IPv6Protocol],
recorder, healthzServer, scheduler, nodePortAddresses, kernelHandler, initOnly)
localDetectors[1], hostname, nodeIPs[v1.IPv6Protocol], recorder,
healthzServer, scheduler, nodePortAddresses, initOnly)
if err != nil {
return nil, fmt.Errorf("unable to create ipv6 proxier: %v", err)
}
Expand Down Expand Up @@ -557,23 +547,6 @@ func newServiceInfo(port *v1.ServicePort, service *v1.Service, bsvcPortInfo *pro
return svcPort
}

// KernelHandler can handle the current installed kernel modules.
type KernelHandler interface {
GetKernelVersion() (string, error)
}

// LinuxKernelHandler implements KernelHandler interface.
type LinuxKernelHandler struct {
executor utilexec.Interface
}

// NewLinuxKernelHandler initializes LinuxKernelHandler with exec.
func NewLinuxKernelHandler() *LinuxKernelHandler {
return &LinuxKernelHandler{
executor: utilexec.New(),
}
}

// getFirstColumn reads all the content from r into memory and return a
// slice which consists of the first word from each line.
func getFirstColumn(r io.Reader) ([]string, error) {
Expand All @@ -593,17 +566,6 @@ func getFirstColumn(r io.Reader) ([]string, error) {
return words, nil
}

// GetKernelVersion returns currently running kernel version.
func (handle *LinuxKernelHandler) GetKernelVersion() (string, error) {
kernelVersionFile := "/proc/sys/kernel/osrelease"
fileContent, err := os.ReadFile(kernelVersionFile)
if err != nil {
return "", fmt.Errorf("error reading osrelease file %q: %v", kernelVersionFile, err)
}

return strings.TrimSpace(string(fileContent)), nil
}

// CanUseIPVSProxier checks if we can use the ipvs Proxier.
// The ipset version and the scheduler are checked. If any virtual servers (VS)
// already exist with the configured scheduler, we just return. Otherwise
Expand Down
8 changes: 8 additions & 0 deletions pkg/util/kernel/OWNERS
@@ -0,0 +1,8 @@
# See the OWNERS docs at https://go.k8s.io/owners

reviewers:
- sig-network-reviewers
- sig-node-reviewers
approvers:
- sig-network-approvers
- sig-node-approvers
45 changes: 45 additions & 0 deletions pkg/util/kernel/constants.go
@@ -0,0 +1,45 @@
/*
Copyright 2023 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package kernel

// IPLocalReservedPortsNamespacedKernelVersion is the kernel version in which net.ipv4.ip_local_reserved_ports was namespaced(netns).
// (ref: https://github.com/torvalds/linux/commit/122ff243f5f104194750ecbc76d5946dd1eec934)
const IPLocalReservedPortsNamespacedKernelVersion = "3.16"

// IPVSConnReuseModeMinSupportedKernelVersion is the minium kernel version supporting net.ipv4.vs.conn_reuse_mode.
// (ref: https://github.com/torvalds/linux/commit/d752c364571743d696c2a54a449ce77550c35ac5)
const IPVSConnReuseModeMinSupportedKernelVersion = "4.1"

// TCPKeepAliveTimeNamespacedKernelVersion is the kernel version in which net.ipv4.tcp_keepalive_time was namespaced(netns).
// (ref: https://github.com/torvalds/linux/commit/13b287e8d1cad951634389f85b8c9b816bd3bb1e)
const TCPKeepAliveTimeNamespacedKernelVersion = "4.5"

// TCPKeepAliveIntervalNamespacedKernelVersion is the kernel version in which net.ipv4.tcp_keepalive_intvl was namespaced(netns).
// (ref: https://github.com/torvalds/linux/commit/b840d15d39128d08ed4486085e5507d2617b9ae1)
const TCPKeepAliveIntervalNamespacedKernelVersion = "4.5"

// TCPKeepAliveProbesNamespacedKernelVersion is the kernel version in which net.ipv4.tcp_keepalive_probes was namespaced(netns).
// (ref: https://github.com/torvalds/linux/commit/9bd6861bd4326e3afd3f14a9ec8a723771fb20bb)
const TCPKeepAliveProbesNamespacedKernelVersion = "4.5"

// TCPFinTimeoutNamespacedKernelVersion is the kernel version in which net.ipv4.tcp_fin_timeout was namespaced(netns).
// (ref: https://github.com/torvalds/linux/commit/1e579caa18b96f9eb18f4f5416658cd15f37c062)
const TCPFinTimeoutNamespacedKernelVersion = "4.6"

// IPVSConnReuseModeFixedKernelVersion is the kernel version in which net.ipv4.vs.conn_reuse_mode was fixed.
// (ref: https://github.com/torvalds/linux/commit/35dfb013149f74c2be1ff9c78f14e6a3cd1539d1)
const IPVSConnReuseModeFixedKernelVersion = "5.9"
48 changes: 48 additions & 0 deletions pkg/util/kernel/version.go
@@ -0,0 +1,48 @@
/*
Copyright 2023 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package kernel

import (
"fmt"
"os"
"strings"

"k8s.io/apimachinery/pkg/util/version"
)

type readFileFunc func(string) ([]byte, error)

// GetVersion returns currently running kernel version.
func GetVersion() (*version.Version, error) {
return getVersion(os.ReadFile)
}

// getVersion reads os release file from the give readFile function.
func getVersion(readFile readFileFunc) (*version.Version, error) {
kernelVersionFile := "/proc/sys/kernel/osrelease"
fileContent, err := readFile(kernelVersionFile)
if err != nil {
return nil, fmt.Errorf("failed to read os-release file: %s", err.Error())
}

kernelVersion, err := version.ParseGeneric(strings.TrimSpace(string(fileContent)))
if err != nil {
return nil, fmt.Errorf("failed to parse kernel version: %s", err.Error())
}

return kernelVersion, nil
}

0 comments on commit 0c93f40

Please sign in to comment.