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({ ] + select({
"@io_bazel_rules_go//go/platform:android": [ "@io_bazel_rules_go//go/platform:android": [
"//pkg/proxy/ipvs:go_default_library", "//pkg/proxy/ipvs:go_default_library",
"//pkg/util/iptables:go_default_library",
], ],
"@io_bazel_rules_go//go/platform:darwin": [ "@io_bazel_rules_go//go/platform:darwin": [
"//pkg/proxy/ipvs:go_default_library", "//pkg/proxy/ipvs:go_default_library",
"//pkg/util/iptables:go_default_library",
], ],
"@io_bazel_rules_go//go/platform:dragonfly": [ "@io_bazel_rules_go//go/platform:dragonfly": [
"//pkg/proxy/ipvs:go_default_library", "//pkg/proxy/ipvs:go_default_library",
"//pkg/util/iptables:go_default_library",
], ],
"@io_bazel_rules_go//go/platform:freebsd": [ "@io_bazel_rules_go//go/platform:freebsd": [
"//pkg/proxy/ipvs:go_default_library", "//pkg/proxy/ipvs:go_default_library",
"//pkg/util/iptables:go_default_library",
], ],
"@io_bazel_rules_go//go/platform:linux": [ "@io_bazel_rules_go//go/platform:linux": [
"//pkg/proxy/ipvs:go_default_library", "//pkg/proxy/ipvs:go_default_library",
"//pkg/util/iptables:go_default_library",
], ],
"@io_bazel_rules_go//go/platform:nacl": [ "@io_bazel_rules_go//go/platform:nacl": [
"//pkg/proxy/ipvs:go_default_library", "//pkg/proxy/ipvs:go_default_library",
"//pkg/util/iptables:go_default_library",
], ],
"@io_bazel_rules_go//go/platform:netbsd": [ "@io_bazel_rules_go//go/platform:netbsd": [
"//pkg/proxy/ipvs:go_default_library", "//pkg/proxy/ipvs:go_default_library",
"//pkg/util/iptables:go_default_library",
], ],
"@io_bazel_rules_go//go/platform:openbsd": [ "@io_bazel_rules_go//go/platform:openbsd": [
"//pkg/proxy/ipvs:go_default_library", "//pkg/proxy/ipvs:go_default_library",
"//pkg/util/iptables:go_default_library",
], ],
"@io_bazel_rules_go//go/platform:plan9": [ "@io_bazel_rules_go//go/platform:plan9": [
"//pkg/proxy/ipvs:go_default_library", "//pkg/proxy/ipvs:go_default_library",
"//pkg/util/iptables:go_default_library",
], ],
"@io_bazel_rules_go//go/platform:solaris": [ "@io_bazel_rules_go//go/platform:solaris": [
"//pkg/proxy/ipvs:go_default_library", "//pkg/proxy/ipvs:go_default_library",
"//pkg/util/iptables:go_default_library",
], ],
"//conditions:default": [], "//conditions:default": [],
}), }),

View File

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

View File

@ -23,68 +23,75 @@ import (
"testing" "testing"
"k8s.io/kubernetes/pkg/proxy/ipvs" "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) { func Test_getProxyMode(t *testing.T) {
var cases = []struct { var cases = []struct {
flag string flag string
iptablesVersion string ipsetVersion string
ipsetVersion string kmods []string
kmods []string kernelVersion string
kernelVersion string kernelCompat bool
kernelCompat bool ipsetError error
iptablesError error expected string
ipsetError error
expected string
}{ }{
{ // flag says userspace { // flag says userspace
flag: "userspace", flag: "userspace",
expected: proxyModeUserspace, expected: proxyModeUserspace,
}, },
{ // flag says iptables, error detecting version { // flag says iptables, kernel not compatible
flag: "iptables", flag: "iptables",
iptablesError: fmt.Errorf("flag says iptables, error detecting version"), kernelCompat: false,
expected: proxyModeUserspace, expected: proxyModeUserspace,
}, },
{ // flag says iptables, version too low { // flag says iptables, kernel is compatible
flag: "iptables", flag: "iptables",
iptablesVersion: "0.0.0", kernelCompat: true,
expected: proxyModeUserspace, expected: proxyModeIPTables,
}, },
{ // flag says iptables, version ok, kernel not compatible { // detect, kernel not compatible
flag: "iptables", flag: "",
iptablesVersion: iptables.MinCheckVersion, kernelCompat: false,
kernelCompat: false, expected: proxyModeUserspace,
expected: proxyModeUserspace,
}, },
{ // flag says iptables, version ok, kernel is compatible { // detect, kernel is compatible
flag: "iptables", flag: "",
iptablesVersion: iptables.MinCheckVersion, kernelCompat: true,
kernelCompat: true, expected: proxyModeIPTables,
expected: proxyModeIPTables,
},
{ // detect, error
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
flag: "",
iptablesVersion: iptables.MinCheckVersion,
kernelCompat: true,
expected: proxyModeIPTables,
}, },
{ // flag says ipvs, ipset version ok, kernel modules installed for linux kernel before 4.19 { // flag says ipvs, ipset version ok, kernel modules installed for linux kernel before 4.19
flag: "ipvs", flag: "ipvs",
@ -101,69 +108,38 @@ func Test_getProxyMode(t *testing.T) {
expected: proxyModeIPVS, expected: proxyModeIPVS,
}, },
{ // flag says ipvs, ipset version too low, fallback on iptables mode { // flag says ipvs, ipset version too low, fallback on iptables mode
flag: "ipvs", flag: "ipvs",
kmods: []string{"ip_vs", "ip_vs_rr", "ip_vs_wrr", "ip_vs_sh", "nf_conntrack"}, kmods: []string{"ip_vs", "ip_vs_rr", "ip_vs_wrr", "ip_vs_sh", "nf_conntrack"},
kernelVersion: "4.19", kernelVersion: "4.19",
ipsetVersion: "0.0", ipsetVersion: "0.0",
iptablesVersion: iptables.MinCheckVersion, kernelCompat: true,
kernelCompat: true, expected: proxyModeIPTables,
expected: proxyModeIPTables,
}, },
{ // flag says ipvs, bad ipset version, fallback on iptables mode { // flag says ipvs, bad ipset version, fallback on iptables mode
flag: "ipvs", flag: "ipvs",
kmods: []string{"ip_vs", "ip_vs_rr", "ip_vs_wrr", "ip_vs_sh", "nf_conntrack"}, kmods: []string{"ip_vs", "ip_vs_rr", "ip_vs_wrr", "ip_vs_sh", "nf_conntrack"},
kernelVersion: "4.19", kernelVersion: "4.19",
ipsetVersion: "a.b.c", ipsetVersion: "a.b.c",
iptablesVersion: iptables.MinCheckVersion, kernelCompat: true,
kernelCompat: true, expected: proxyModeIPTables,
expected: proxyModeIPTables,
}, },
{ // flag says ipvs, required kernel modules are not installed, fallback on iptables mode { // flag says ipvs, required kernel modules are not installed, fallback on iptables mode
flag: "ipvs", flag: "ipvs",
kmods: []string{"foo", "bar", "baz"}, kmods: []string{"foo", "bar", "baz"},
kernelVersion: "4.19", kernelVersion: "4.19",
ipsetVersion: ipvs.MinIPSetCheckVersion, ipsetVersion: ipvs.MinIPSetCheckVersion,
iptablesVersion: iptables.MinCheckVersion, kernelCompat: true,
kernelCompat: true, expected: proxyModeIPTables,
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 { for i, c := range cases {
versioner := &fakeIPTablesVersioner{c.iptablesVersion, c.iptablesError}
kcompater := &fakeKernelCompatTester{c.kernelCompat} kcompater := &fakeKernelCompatTester{c.kernelCompat}
ipsetver := &fakeIPSetVersioner{c.ipsetVersion, c.ipsetError} ipsetver := &fakeIPSetVersioner{c.ipsetVersion, c.ipsetError}
khandler := &fakeKernelHandler{ khandler := &fakeKernelHandler{
modules: c.kmods, modules: c.kmods,
kernelVersion: c.kernelVersion, kernelVersion: c.kernelVersion,
} }
r := getProxyMode(c.flag, versioner, khandler, ipsetver, kcompater) r := getProxyMode(c.flag, khandler, ipsetver, kcompater)
if r != c.expected { if r != c.expected {
t.Errorf("Case[%d] Expected %q, got %q", i, c.expected, r) t.Errorf("Case[%d] Expected %q, got %q", i, c.expected, r)
} }

View File

@ -38,53 +38,6 @@ import (
utilpointer "k8s.io/utils/pointer" 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. // This test verifies that NewProxyServer does not crash when CleanupAndExit is true.
func TestProxyServerWithCleanupAndExit(t *testing.T) { func TestProxyServerWithCleanupAndExit(t *testing.T) {
// Each bind address below is a separate test case // Each bind address below is a separate test case

View File

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

View File

@ -36,7 +36,6 @@ import (
v1 "k8s.io/api/core/v1" v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/types"
utilversion "k8s.io/apimachinery/pkg/util/version"
"k8s.io/apimachinery/pkg/util/wait" "k8s.io/apimachinery/pkg/util/wait"
"k8s.io/client-go/tools/record" "k8s.io/client-go/tools/record"
"k8s.io/kubernetes/pkg/proxy" "k8s.io/kubernetes/pkg/proxy"
@ -52,15 +51,6 @@ import (
) )
const ( 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 // the services chain
kubeServicesChain utiliptables.Chain = "KUBE-SERVICES" kubeServicesChain utiliptables.Chain = "KUBE-SERVICES"
@ -83,12 +73,6 @@ const (
kubeForwardChain utiliptables.Chain = "KUBE-FORWARD" 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 // KernelCompatTester tests whether the required kernel capabilities are
// present to run the iptables proxier. // present to run the iptables proxier.
type KernelCompatTester interface { type KernelCompatTester interface {
@ -96,28 +80,8 @@ type KernelCompatTester interface {
} }
// CanUseIPTablesProxier returns true if we should use the iptables Proxier // CanUseIPTablesProxier returns true if we should use the iptables Proxier
// instead of the "classic" userspace Proxier. This is determined by checking // instead of the "classic" userspace Proxier.
// the iptables version and for the existence of kernel features. It may return func CanUseIPTablesProxier(kcompat KernelCompatTester) (bool, error) {
// 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.
if err := kcompat.IsCompatible(); err != nil { if err := kcompat.IsCompatible(); err != nil {
return false, err return false, err
} }
@ -131,7 +95,6 @@ type LinuxKernelCompatTester struct{}
// that it exists. If this Proxier is chosen, we'll initialize it as we // that it exists. If this Proxier is chosen, we'll initialize it as we
// need. // need.
func (lkct LinuxKernelCompatTester) IsCompatible() error { func (lkct LinuxKernelCompatTester) IsCompatible() error {
_, err := utilsysctl.New().GetSysctl(sysctlRouteLocalnet) _, err := utilsysctl.New().GetSysctl(sysctlRouteLocalnet)
return err return err
} }