Skip to content
Permalink
Browse files

Merge pull request #80368 from danwinship/iptables-checks

iptables feature detection improvements
  • Loading branch information
k8s-ci-robot committed Aug 22, 2019
2 parents 5713c22 + 81cd27a commit 37651f1cef5ec5c7286ba409ee0fe298c4605d66
@@ -171,43 +171,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": [],
}),
@@ -133,7 +133,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)
@@ -238,20 +238,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)
@@ -265,12 +265,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
@@ -23,68 +23,75 @@ 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
flag string
ipsetVersion string
kmods []string
kernelVersion string
kernelCompat bool
ipsetError error
expected string
}{
{ // flag says userspace
flag: "userspace",
expected: proxyModeUserspace,
},
{ // flag says iptables, error detecting version
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, kernel not compatible
flag: "iptables",
kernelCompat: false,
expected: proxyModeUserspace,
},
{ // flag says iptables, version ok, kernel not compatible
flag: "iptables",
iptablesVersion: iptables.MinCheckVersion,
kernelCompat: false,
expected: proxyModeUserspace,
{ // flag says iptables, kernel is compatible
flag: "iptables",
kernelCompat: true,
expected: proxyModeIPTables,
},
{ // flag says iptables, version ok, kernel is compatible
flag: "iptables",
iptablesVersion: iptables.MinCheckVersion,
kernelCompat: true,
expected: proxyModeIPTables,
{ // detect, kernel not compatible
flag: "",
kernelCompat: false,
expected: proxyModeUserspace,
},
{ // 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,
{ // detect, kernel is compatible
flag: "",
kernelCompat: true,
expected: proxyModeIPTables,
},
{ // flag says ipvs, ipset version ok, kernel modules installed for linux kernel before 4.19
flag: "ipvs",
@@ -101,69 +108,38 @@ func Test_getProxyMode(t *testing.T) {
expected: proxyModeIPVS,
},
{ // flag says ipvs, ipset version too low, fallback on iptables 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: true,
expected: proxyModeIPTables,
flag: "ipvs",
kmods: []string{"ip_vs", "ip_vs_rr", "ip_vs_wrr", "ip_vs_sh", "nf_conntrack"},
kernelVersion: "4.19",
ipsetVersion: "0.0",
kernelCompat: true,
expected: proxyModeIPTables,
},
{ // flag says ipvs, bad ipset version, fallback on iptables mode
flag: "ipvs",
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,
flag: "ipvs",
kmods: []string{"ip_vs", "ip_vs_rr", "ip_vs_wrr", "ip_vs_sh", "nf_conntrack"},
kernelVersion: "4.19",
ipsetVersion: "a.b.c",
kernelCompat: true,
expected: proxyModeIPTables,
},
{ // flag says ipvs, required kernel modules are not installed, fallback on iptables mode
flag: "ipvs",
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,
flag: "ipvs",
kmods: []string{"foo", "bar", "baz"},
kernelVersion: "4.19",
ipsetVersion: ipvs.MinIPSetCheckVersion,
kernelCompat: true,
expected: proxyModeIPTables,
},
}
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)
}
@@ -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
@@ -52,10 +52,6 @@ func NewFakeIPTables() *fakeIPTables {
}
}

func (f *fakeIPTables) GetVersion() (string, error) {
return "1.4.21", nil
}

func (f *fakeIPTables) getTable(tableName utiliptables.Table) (*fakeTable, error) {
table, ok := f.tables[string(tableName)]
if !ok {
@@ -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",

0 comments on commit 37651f1

Please sign in to comment.
You can’t perform that action at this time.