kube-proxy: drop iptables version check

Kube-proxy's iptables mode used to care whether utiliptables's
EnsureRule was able to use "iptables -C" or if it had to implement it
hackily using "iptables-save". But that became irrelevant when
kube-proxy was reimplemented using "iptables-restore", and no one ever
noticed. So remove that check.
This commit is contained in:
Dan Winship 2019-07-19 12:08:20 -04:00
parent 8bced9b130
commit a735c97356
6 changed files with 87 additions and 206 deletions

View File

@ -172,43 +172,33 @@ go_test(
] + select({
"@io_bazel_rules_go//go/platform:android": [
"//pkg/proxy/ipvs:go_default_library",
"//pkg/util/iptables:go_default_library",
],
"@io_bazel_rules_go//go/platform:darwin": [
"//pkg/proxy/ipvs:go_default_library",
"//pkg/util/iptables:go_default_library",
],
"@io_bazel_rules_go//go/platform:dragonfly": [
"//pkg/proxy/ipvs:go_default_library",
"//pkg/util/iptables:go_default_library",
],
"@io_bazel_rules_go//go/platform:freebsd": [
"//pkg/proxy/ipvs:go_default_library",
"//pkg/util/iptables:go_default_library",
],
"@io_bazel_rules_go//go/platform:linux": [
"//pkg/proxy/ipvs:go_default_library",
"//pkg/util/iptables:go_default_library",
],
"@io_bazel_rules_go//go/platform:nacl": [
"//pkg/proxy/ipvs:go_default_library",
"//pkg/util/iptables:go_default_library",
],
"@io_bazel_rules_go//go/platform:netbsd": [
"//pkg/proxy/ipvs:go_default_library",
"//pkg/util/iptables:go_default_library",
],
"@io_bazel_rules_go//go/platform:openbsd": [
"//pkg/proxy/ipvs:go_default_library",
"//pkg/util/iptables:go_default_library",
],
"@io_bazel_rules_go//go/platform:plan9": [
"//pkg/proxy/ipvs:go_default_library",
"//pkg/util/iptables:go_default_library",
],
"@io_bazel_rules_go//go/platform:solaris": [
"//pkg/proxy/ipvs:go_default_library",
"//pkg/util/iptables:go_default_library",
],
"//conditions:default": [],
}),

View File

@ -134,7 +134,7 @@ func newProxyServer(
var proxier proxy.ProxyProvider
proxyMode := getProxyMode(string(config.Mode), iptInterface, kernelHandler, ipsetInterface, iptables.LinuxKernelCompatTester{})
proxyMode := getProxyMode(string(config.Mode), kernelHandler, ipsetInterface, iptables.LinuxKernelCompatTester{})
nodeIP := net.ParseIP(config.BindAddress)
if nodeIP.IsUnspecified() {
nodeIP = utilnode.GetNodeIP(client, hostname)
@ -236,20 +236,20 @@ func newProxyServer(
}, nil
}
func getProxyMode(proxyMode string, iptver iptables.Versioner, khandle ipvs.KernelHandler, ipsetver ipvs.IPSetVersioner, kcompat iptables.KernelCompatTester) string {
func getProxyMode(proxyMode string, khandle ipvs.KernelHandler, ipsetver ipvs.IPSetVersioner, kcompat iptables.KernelCompatTester) string {
switch proxyMode {
case proxyModeUserspace:
return proxyModeUserspace
case proxyModeIPTables:
return tryIPTablesProxy(iptver, kcompat)
return tryIPTablesProxy(kcompat)
case proxyModeIPVS:
return tryIPVSProxy(iptver, khandle, ipsetver, kcompat)
return tryIPVSProxy(khandle, ipsetver, kcompat)
}
klog.Warningf("Flag proxy-mode=%q unknown, assuming iptables proxy", proxyMode)
return tryIPTablesProxy(iptver, kcompat)
return tryIPTablesProxy(kcompat)
}
func tryIPVSProxy(iptver iptables.Versioner, khandle ipvs.KernelHandler, ipsetver ipvs.IPSetVersioner, kcompat iptables.KernelCompatTester) string {
func tryIPVSProxy(khandle ipvs.KernelHandler, ipsetver ipvs.IPSetVersioner, kcompat iptables.KernelCompatTester) string {
// guaranteed false on error, error only necessary for debugging
// IPVS Proxier relies on ip_vs_* kernel modules and ipset
useIPVSProxy, err := ipvs.CanUseIPVSProxier(khandle, ipsetver)
@ -263,12 +263,12 @@ func tryIPVSProxy(iptver iptables.Versioner, khandle ipvs.KernelHandler, ipsetve
// Try to fallback to iptables before falling back to userspace
klog.V(1).Infof("Can't use ipvs proxier, trying iptables proxier")
return tryIPTablesProxy(iptver, kcompat)
return tryIPTablesProxy(kcompat)
}
func tryIPTablesProxy(iptver iptables.Versioner, kcompat iptables.KernelCompatTester) string {
func tryIPTablesProxy(kcompat iptables.KernelCompatTester) string {
// guaranteed false on error, error only necessary for debugging
useIPTablesProxy, err := iptables.CanUseIPTablesProxier(iptver, kcompat)
useIPTablesProxy, err := iptables.CanUseIPTablesProxier(kcompat)
if err != nil {
utilruntime.HandleError(fmt.Errorf("can't determine whether to use iptables proxy, using userspace proxier: %v", err))
return proxyModeUserspace

View File

@ -23,18 +23,49 @@ import (
"testing"
"k8s.io/kubernetes/pkg/proxy/ipvs"
"k8s.io/kubernetes/pkg/util/iptables"
)
type fakeIPSetVersioner struct {
version string // what to return
err error // what to return
}
func (fake *fakeIPSetVersioner) GetVersion() (string, error) {
return fake.version, fake.err
}
type fakeKernelCompatTester struct {
ok bool
}
func (fake *fakeKernelCompatTester) IsCompatible() error {
if !fake.ok {
return fmt.Errorf("error")
}
return nil
}
// fakeKernelHandler implements KernelHandler.
type fakeKernelHandler struct {
modules []string
kernelVersion string
}
func (fake *fakeKernelHandler) GetModules() ([]string, error) {
return fake.modules, nil
}
func (fake *fakeKernelHandler) GetKernelVersion() (string, error) {
return fake.kernelVersion, nil
}
func Test_getProxyMode(t *testing.T) {
var cases = []struct {
flag string
iptablesVersion string
ipsetVersion string
kmods []string
kernelVersion string
kernelCompat bool
iptablesError error
ipsetError error
expected string
}{
@ -42,47 +73,23 @@ func Test_getProxyMode(t *testing.T) {
flag: "userspace",
expected: proxyModeUserspace,
},
{ // flag says iptables, error detecting version
{ // flag says iptables, kernel not compatible
flag: "iptables",
iptablesError: fmt.Errorf("flag says iptables, error detecting version"),
expected: proxyModeUserspace,
},
{ // flag says iptables, version too low
flag: "iptables",
iptablesVersion: "0.0.0",
expected: proxyModeUserspace,
},
{ // flag says iptables, version ok, kernel not compatible
flag: "iptables",
iptablesVersion: iptables.MinCheckVersion,
kernelCompat: false,
expected: proxyModeUserspace,
},
{ // flag says iptables, version ok, kernel is compatible
{ // flag says iptables, kernel is compatible
flag: "iptables",
iptablesVersion: iptables.MinCheckVersion,
kernelCompat: true,
expected: proxyModeIPTables,
},
{ // detect, error
{ // detect, kernel not compatible
flag: "",
iptablesError: fmt.Errorf("oops"),
expected: proxyModeUserspace,
},
{ // detect, version too low
flag: "",
iptablesVersion: "0.0.0",
expected: proxyModeUserspace,
},
{ // detect, version ok, kernel not compatible
flag: "",
iptablesVersion: iptables.MinCheckVersion,
kernelCompat: false,
expected: proxyModeUserspace,
},
{ // detect, version ok, kernel is compatible
{ // detect, kernel is compatible
flag: "",
iptablesVersion: iptables.MinCheckVersion,
kernelCompat: true,
expected: proxyModeIPTables,
},
@ -105,7 +112,6 @@ func Test_getProxyMode(t *testing.T) {
kmods: []string{"ip_vs", "ip_vs_rr", "ip_vs_wrr", "ip_vs_sh", "nf_conntrack"},
kernelVersion: "4.19",
ipsetVersion: "0.0",
iptablesVersion: iptables.MinCheckVersion,
kernelCompat: true,
expected: proxyModeIPTables,
},
@ -114,7 +120,6 @@ func Test_getProxyMode(t *testing.T) {
kmods: []string{"ip_vs", "ip_vs_rr", "ip_vs_wrr", "ip_vs_sh", "nf_conntrack"},
kernelVersion: "4.19",
ipsetVersion: "a.b.c",
iptablesVersion: iptables.MinCheckVersion,
kernelCompat: true,
expected: proxyModeIPTables,
},
@ -123,47 +128,18 @@ func Test_getProxyMode(t *testing.T) {
kmods: []string{"foo", "bar", "baz"},
kernelVersion: "4.19",
ipsetVersion: ipvs.MinIPSetCheckVersion,
iptablesVersion: iptables.MinCheckVersion,
kernelCompat: true,
expected: proxyModeIPTables,
},
{ // flag says ipvs, required kernel modules are not installed, iptables version too old, fallback on userspace mode
flag: "ipvs",
kmods: []string{"foo", "bar", "baz"},
kernelVersion: "4.19",
ipsetVersion: ipvs.MinIPSetCheckVersion,
iptablesVersion: "0.0.0",
kernelCompat: true,
expected: proxyModeUserspace,
},
{ // flag says ipvs, required kernel modules are not installed, iptables version too old, fallback on userspace mode
flag: "ipvs",
kmods: []string{"foo", "bar", "baz"},
kernelVersion: "4.19",
ipsetVersion: ipvs.MinIPSetCheckVersion,
iptablesVersion: "0.0.0",
kernelCompat: true,
expected: proxyModeUserspace,
},
{ // flag says ipvs, ipset version too low, iptables version too old, kernel not compatible, fallback on userspace mode
flag: "ipvs",
kmods: []string{"ip_vs", "ip_vs_rr", "ip_vs_wrr", "ip_vs_sh", "nf_conntrack"},
kernelVersion: "4.19",
ipsetVersion: "0.0",
iptablesVersion: iptables.MinCheckVersion,
kernelCompat: false,
expected: proxyModeUserspace,
},
}
for i, c := range cases {
versioner := &fakeIPTablesVersioner{c.iptablesVersion, c.iptablesError}
kcompater := &fakeKernelCompatTester{c.kernelCompat}
ipsetver := &fakeIPSetVersioner{c.ipsetVersion, c.ipsetError}
khandler := &fakeKernelHandler{
modules: c.kmods,
kernelVersion: c.kernelVersion,
}
r := getProxyMode(c.flag, versioner, khandler, ipsetver, kcompater)
r := getProxyMode(c.flag, khandler, ipsetver, kcompater)
if r != c.expected {
t.Errorf("Case[%d] Expected %q, got %q", i, c.expected, r)
}

View File

@ -38,53 +38,6 @@ import (
utilpointer "k8s.io/utils/pointer"
)
type fakeIPTablesVersioner struct {
version string // what to return
err error // what to return
}
func (fake *fakeIPTablesVersioner) GetVersion() (string, error) {
return fake.version, fake.err
}
func (fake *fakeIPTablesVersioner) IsCompatible() error {
return fake.err
}
type fakeIPSetVersioner struct {
version string // what to return
err error // what to return
}
func (fake *fakeIPSetVersioner) GetVersion() (string, error) {
return fake.version, fake.err
}
type fakeKernelCompatTester struct {
ok bool
}
func (fake *fakeKernelCompatTester) IsCompatible() error {
if !fake.ok {
return fmt.Errorf("error")
}
return nil
}
// fakeKernelHandler implements KernelHandler.
type fakeKernelHandler struct {
modules []string
kernelVersion string
}
func (fake *fakeKernelHandler) GetModules() ([]string, error) {
return fake.modules, nil
}
func (fake *fakeKernelHandler) GetKernelVersion() (string, error) {
return fake.kernelVersion, nil
}
// This test verifies that NewProxyServer does not crash when CleanupAndExit is true.
func TestProxyServerWithCleanupAndExit(t *testing.T) {
// Each bind address below is a separate test case

View File

@ -21,7 +21,6 @@ go_library(
"//pkg/util/sysctl:go_default_library",
"//staging/src/k8s.io/api/core/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/types:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/version:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library",
"//staging/src/k8s.io/client-go/tools/record:go_default_library",
"//vendor/k8s.io/klog:go_default_library",

View File

@ -36,7 +36,6 @@ import (
v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/types"
utilversion "k8s.io/apimachinery/pkg/util/version"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/client-go/tools/record"
"k8s.io/kubernetes/pkg/proxy"
@ -52,15 +51,6 @@ import (
)
const (
// iptablesMinVersion is the minimum version of iptables for which we will use the Proxier
// from this package instead of the userspace Proxier. While most of the
// features we need were available earlier, the '-C' flag was added more
// recently. We use that indirectly in Ensure* functions, and if we don't
// have it, we have to be extra careful about the exact args we feed in being
// the same as the args we read back (iptables itself normalizes some args).
// This is the "new" Proxier, so we require "new" versions of tools.
iptablesMinVersion = utiliptables.MinCheckVersion
// the services chain
kubeServicesChain utiliptables.Chain = "KUBE-SERVICES"
@ -83,12 +73,6 @@ const (
kubeForwardChain utiliptables.Chain = "KUBE-FORWARD"
)
// Versioner can query the current iptables version.
type Versioner interface {
// returns "X.Y.Z"
GetVersion() (string, error)
}
// KernelCompatTester tests whether the required kernel capabilities are
// present to run the iptables proxier.
type KernelCompatTester interface {
@ -96,28 +80,8 @@ type KernelCompatTester interface {
}
// CanUseIPTablesProxier returns true if we should use the iptables Proxier
// instead of the "classic" userspace Proxier. This is determined by checking
// the iptables version and for the existence of kernel features. It may return
// an error if it fails to get the iptables version without error, in which
// case it will also return false.
func CanUseIPTablesProxier(iptver Versioner, kcompat KernelCompatTester) (bool, error) {
minVersion, err := utilversion.ParseGeneric(iptablesMinVersion)
if err != nil {
return false, err
}
versionString, err := iptver.GetVersion()
if err != nil {
return false, err
}
version, err := utilversion.ParseGeneric(versionString)
if err != nil {
return false, err
}
if version.LessThan(minVersion) {
return false, nil
}
// Check that the kernel supports what we need.
// instead of the "classic" userspace Proxier.
func CanUseIPTablesProxier(kcompat KernelCompatTester) (bool, error) {
if err := kcompat.IsCompatible(); err != nil {
return false, err
}
@ -131,7 +95,6 @@ type LinuxKernelCompatTester struct{}
// that it exists. If this Proxier is chosen, we'll initialize it as we
// need.
func (lkct LinuxKernelCompatTester) IsCompatible() error {
_, err := utilsysctl.New().GetSysctl(sysctlRouteLocalnet)
return err
}