mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-09-15 14:14:39 +00:00
Merge pull request #56390 from m1093782566/test-mode
Automatic merge from submit-queue. If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>. Test Proxy Mode **What this PR does / why we need it**: Currently, IPVS-based kube-proxy is protected by feature gateway and there is no UT for it. We should test ipvs proxy mode when feature gateway is set. **Which issue(s) this PR fixes**: Fixes #56404 **Special notes for your reviewer**: **Release note**: ```release-note NONE ```
This commit is contained in:
@@ -92,12 +92,14 @@ go_test(
|
||||
deps = [
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//pkg/proxy/apis/kubeproxyconfig:go_default_library",
|
||||
"//pkg/proxy/ipvs:go_default_library",
|
||||
"//pkg/util/configz:go_default_library",
|
||||
"//pkg/util/iptables:go_default_library",
|
||||
"//pkg/util/pointer:go_default_library",
|
||||
"//vendor/github.com/stretchr/testify/assert:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/diff:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
|
@@ -83,6 +83,7 @@ func newProxyServer(
|
||||
|
||||
var iptInterface utiliptables.Interface
|
||||
var ipvsInterface utilipvs.Interface
|
||||
var kernelHandler ipvs.KernelHandler
|
||||
var ipsetInterface utilipset.Interface
|
||||
var dbus utildbus.Interface
|
||||
|
||||
@@ -92,6 +93,7 @@ func newProxyServer(
|
||||
dbus = utildbus.New()
|
||||
iptInterface = utiliptables.New(execer, dbus, protocol)
|
||||
ipvsInterface = utilipvs.New(execer)
|
||||
kernelHandler = ipvs.NewLinuxKernelHandler()
|
||||
ipsetInterface = utilipset.New(execer)
|
||||
|
||||
// We omit creation of pretty much everything if we run in cleanup mode
|
||||
@@ -133,7 +135,7 @@ func newProxyServer(
|
||||
var serviceEventHandler proxyconfig.ServiceHandler
|
||||
var endpointsEventHandler proxyconfig.EndpointsHandler
|
||||
|
||||
proxyMode := getProxyMode(string(config.Mode), iptInterface, ipsetInterface, iptables.LinuxKernelCompatTester{})
|
||||
proxyMode := getProxyMode(string(config.Mode), iptInterface, kernelHandler, ipsetInterface, iptables.LinuxKernelCompatTester{})
|
||||
if proxyMode == proxyModeIPTables {
|
||||
glog.V(0).Info("Using iptables Proxier.")
|
||||
nodeIP := net.ParseIP(config.BindAddress)
|
||||
@@ -269,7 +271,7 @@ func newProxyServer(
|
||||
}, nil
|
||||
}
|
||||
|
||||
func getProxyMode(proxyMode string, iptver iptables.IPTablesVersioner, ipsetver ipvs.IPSetVersioner, kcompat iptables.KernelCompatTester) string {
|
||||
func getProxyMode(proxyMode string, iptver iptables.IPTablesVersioner, khandle ipvs.KernelHandler, ipsetver ipvs.IPSetVersioner, kcompat iptables.KernelCompatTester) string {
|
||||
if proxyMode == proxyModeUserspace {
|
||||
return proxyModeUserspace
|
||||
}
|
||||
@@ -280,7 +282,7 @@ func getProxyMode(proxyMode string, iptver iptables.IPTablesVersioner, ipsetver
|
||||
|
||||
if utilfeature.DefaultFeatureGate.Enabled(features.SupportIPVSProxyMode) {
|
||||
if proxyMode == proxyModeIPVS {
|
||||
return tryIPVSProxy(iptver, ipsetver, kcompat)
|
||||
return tryIPVSProxy(iptver, khandle, ipsetver, kcompat)
|
||||
} else {
|
||||
glog.Warningf("Can't use ipvs proxier, trying iptables proxier")
|
||||
return tryIPTablesProxy(iptver, kcompat)
|
||||
@@ -290,10 +292,10 @@ func getProxyMode(proxyMode string, iptver iptables.IPTablesVersioner, ipsetver
|
||||
return tryIPTablesProxy(iptver, kcompat)
|
||||
}
|
||||
|
||||
func tryIPVSProxy(iptver iptables.IPTablesVersioner, ipsetver ipvs.IPSetVersioner, kcompat iptables.KernelCompatTester) string {
|
||||
func tryIPVSProxy(iptver iptables.IPTablesVersioner, khandle ipvs.KernelHandler, ipsetver ipvs.IPSetVersioner, kcompat iptables.KernelCompatTester) string {
|
||||
// guaranteed false on error, error only necessary for debugging
|
||||
// IPVS Proxier relies on ipset
|
||||
useIPVSProxy, err := ipvs.CanUseIPVSProxier(ipsetver)
|
||||
// IPVS Proxier relies on ip_vs_* kernel modules and ipset
|
||||
useIPVSProxy, err := ipvs.CanUseIPVSProxier(khandle, ipsetver)
|
||||
if err != nil {
|
||||
// Try to fallback to iptables before falling back to userspace
|
||||
utilruntime.HandleError(fmt.Errorf("can't determine whether to use ipvs proxy, error: %v", err))
|
||||
|
@@ -28,8 +28,10 @@ import (
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/util/diff"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
"k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig"
|
||||
"k8s.io/kubernetes/pkg/proxy/ipvs"
|
||||
"k8s.io/kubernetes/pkg/util/configz"
|
||||
"k8s.io/kubernetes/pkg/util/iptables"
|
||||
utilpointer "k8s.io/kubernetes/pkg/util/pointer"
|
||||
@@ -72,6 +74,15 @@ func (fake *fakeKernelCompatTester) IsCompatible() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// fakeKernelHandler implements KernelHandler.
|
||||
type fakeKernelHandler struct {
|
||||
modules []string
|
||||
}
|
||||
|
||||
func (fake *fakeKernelHandler) GetModules() ([]string, error) {
|
||||
return fake.modules, nil
|
||||
}
|
||||
|
||||
func Test_getProxyMode(t *testing.T) {
|
||||
if runtime.GOOS != "linux" {
|
||||
t.Skip("skipping on non-Linux")
|
||||
@@ -82,6 +93,7 @@ func Test_getProxyMode(t *testing.T) {
|
||||
annotationVal string
|
||||
iptablesVersion string
|
||||
ipsetVersion string
|
||||
kmods []string
|
||||
kernelCompat bool
|
||||
iptablesError error
|
||||
ipsetError error
|
||||
@@ -135,12 +147,162 @@ func Test_getProxyMode(t *testing.T) {
|
||||
kernelCompat: true,
|
||||
expected: proxyModeIPTables,
|
||||
},
|
||||
{ // specify ipvs, feature gateway disabled, iptables version ok, kernel is compatible
|
||||
flag: "ipvs",
|
||||
iptablesVersion: iptables.MinCheckVersion,
|
||||
kernelCompat: true,
|
||||
expected: proxyModeIPTables,
|
||||
},
|
||||
{ // specify ipvs, feature gateway disabled, iptables version too low
|
||||
flag: "ipvs",
|
||||
iptablesVersion: "0.0.0",
|
||||
expected: proxyModeUserspace,
|
||||
},
|
||||
{ // specify ipvs, feature gateway disabled, iptables version ok, kernel is not compatible
|
||||
flag: "ipvs",
|
||||
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}
|
||||
r := getProxyMode(c.flag, versioner, ipsetver, kcompater)
|
||||
khandler := &fakeKernelHandler{c.kmods}
|
||||
r := getProxyMode(c.flag, versioner, khandler, ipsetver, kcompater)
|
||||
if r != c.expected {
|
||||
t.Errorf("Case[%d] Expected %q, got %q", i, c.expected, r)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This is a coarse test, but it offers some modicum of confidence as the code is evolved.
|
||||
func Test_getProxyModeEnableFeatureGateway(t *testing.T) {
|
||||
if runtime.GOOS != "linux" {
|
||||
t.Skip("skipping on non-Linux")
|
||||
}
|
||||
|
||||
// enable IPVS feature gateway
|
||||
utilfeature.DefaultFeatureGate.Set("SupportIPVSProxyMode=true")
|
||||
|
||||
var cases = []struct {
|
||||
flag string
|
||||
iptablesVersion string
|
||||
ipsetVersion string
|
||||
kernelCompat bool
|
||||
iptablesError error
|
||||
ipsetError error
|
||||
mods []string
|
||||
expected string
|
||||
}{
|
||||
{ // flag says userspace
|
||||
flag: "userspace",
|
||||
expected: proxyModeUserspace,
|
||||
},
|
||||
{ // flag says iptables, error detecting version
|
||||
flag: "iptables",
|
||||
iptablesError: fmt.Errorf("oops!"),
|
||||
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: "iptables",
|
||||
iptablesVersion: iptables.MinCheckVersion,
|
||||
kernelCompat: true,
|
||||
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,
|
||||
},
|
||||
{ // detect, version ok, kernel is compatible
|
||||
flag: "",
|
||||
iptablesVersion: iptables.MinCheckVersion,
|
||||
kernelCompat: true,
|
||||
expected: proxyModeIPTables,
|
||||
},
|
||||
{ // flag says ipvs, ipset version ok, kernel modules installed
|
||||
flag: "ipvs",
|
||||
mods: []string{"ip_vs", "ip_vs_rr", "ip_vs_wrr", "ip_vs_sh", "nf_conntrack_ipv4"},
|
||||
ipsetVersion: ipvs.MinIPSetCheckVersion,
|
||||
expected: proxyModeIPVS,
|
||||
},
|
||||
{ // flag says ipvs, ipset version too low, fallback on iptables mode
|
||||
flag: "ipvs",
|
||||
mods: []string{"ip_vs", "ip_vs_rr", "ip_vs_wrr", "ip_vs_sh", "nf_conntrack_ipv4"},
|
||||
ipsetVersion: "0.0",
|
||||
iptablesVersion: iptables.MinCheckVersion,
|
||||
kernelCompat: true,
|
||||
expected: proxyModeIPTables,
|
||||
},
|
||||
{ // flag says ipvs, bad ipset version, fallback on iptables mode
|
||||
flag: "ipvs",
|
||||
mods: []string{"ip_vs", "ip_vs_rr", "ip_vs_wrr", "ip_vs_sh", "nf_conntrack_ipv4"},
|
||||
ipsetVersion: "a.b.c",
|
||||
iptablesVersion: iptables.MinCheckVersion,
|
||||
kernelCompat: true,
|
||||
expected: proxyModeIPTables,
|
||||
},
|
||||
{ // flag says ipvs, required kernel modules are not installed, fallback on iptables mode
|
||||
flag: "ipvs",
|
||||
mods: []string{"foo", "bar", "baz"},
|
||||
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",
|
||||
mods: []string{"foo", "bar", "baz"},
|
||||
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",
|
||||
mods: []string{"ip_vs", "ip_vs_rr", "ip_vs_wrr", "ip_vs_sh", "nf_conntrack_ipv4"},
|
||||
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}
|
||||
khandle := &fakeKernelHandler{c.mods}
|
||||
r := getProxyMode(c.flag, versioner, khandle, ipsetver, kcompater)
|
||||
if r != c.expected {
|
||||
t.Errorf("Case[%d] Expected %q, got %q", i, c.expected, r)
|
||||
}
|
||||
|
Reference in New Issue
Block a user