Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
K
k3s
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Jacklull
k3s
Commits
dc2e57ba
Commit
dc2e57ba
authored
Nov 26, 2017
by
m1093782566
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
refactor canUseIPVSMode and test it
parent
e7ad6e60
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
139 additions
and
16 deletions
+139
-16
server_others.go
cmd/kube-proxy/app/server_others.go
+8
-6
server_test.go
cmd/kube-proxy/app/server_test.go
+12
-1
proxier.go
pkg/proxy/ipvs/proxier.go
+35
-9
proxier_test.go
pkg/proxy/ipvs/proxier_test.go
+84
-0
No files found.
cmd/kube-proxy/app/server_others.go
View file @
dc2e57ba
...
@@ -83,6 +83,7 @@ func newProxyServer(
...
@@ -83,6 +83,7 @@ func newProxyServer(
var
iptInterface
utiliptables
.
Interface
var
iptInterface
utiliptables
.
Interface
var
ipvsInterface
utilipvs
.
Interface
var
ipvsInterface
utilipvs
.
Interface
var
kernelHandler
ipvs
.
KernelHandler
var
ipsetInterface
utilipset
.
Interface
var
ipsetInterface
utilipset
.
Interface
var
dbus
utildbus
.
Interface
var
dbus
utildbus
.
Interface
...
@@ -92,6 +93,7 @@ func newProxyServer(
...
@@ -92,6 +93,7 @@ func newProxyServer(
dbus
=
utildbus
.
New
()
dbus
=
utildbus
.
New
()
iptInterface
=
utiliptables
.
New
(
execer
,
dbus
,
protocol
)
iptInterface
=
utiliptables
.
New
(
execer
,
dbus
,
protocol
)
ipvsInterface
=
utilipvs
.
New
(
execer
)
ipvsInterface
=
utilipvs
.
New
(
execer
)
kernelHandler
=
ipvs
.
NewLinuxKernelHandler
()
ipsetInterface
=
utilipset
.
New
(
execer
)
ipsetInterface
=
utilipset
.
New
(
execer
)
// We omit creation of pretty much everything if we run in cleanup mode
// We omit creation of pretty much everything if we run in cleanup mode
...
@@ -133,7 +135,7 @@ func newProxyServer(
...
@@ -133,7 +135,7 @@ func newProxyServer(
var
serviceEventHandler
proxyconfig
.
ServiceHandler
var
serviceEventHandler
proxyconfig
.
ServiceHandler
var
endpointsEventHandler
proxyconfig
.
EndpointsHandler
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
{
if
proxyMode
==
proxyModeIPTables
{
glog
.
V
(
0
)
.
Info
(
"Using iptables Proxier."
)
glog
.
V
(
0
)
.
Info
(
"Using iptables Proxier."
)
nodeIP
:=
net
.
ParseIP
(
config
.
BindAddress
)
nodeIP
:=
net
.
ParseIP
(
config
.
BindAddress
)
...
@@ -269,7 +271,7 @@ func newProxyServer(
...
@@ -269,7 +271,7 @@ func newProxyServer(
},
nil
},
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
{
if
proxyMode
==
proxyModeUserspace
{
return
proxyModeUserspace
return
proxyModeUserspace
}
}
...
@@ -280,7 +282,7 @@ func getProxyMode(proxyMode string, iptver iptables.IPTablesVersioner, ipsetver
...
@@ -280,7 +282,7 @@ func getProxyMode(proxyMode string, iptver iptables.IPTablesVersioner, ipsetver
if
utilfeature
.
DefaultFeatureGate
.
Enabled
(
features
.
SupportIPVSProxyMode
)
{
if
utilfeature
.
DefaultFeatureGate
.
Enabled
(
features
.
SupportIPVSProxyMode
)
{
if
proxyMode
==
proxyModeIPVS
{
if
proxyMode
==
proxyModeIPVS
{
return
tryIPVSProxy
(
iptver
,
ipsetver
,
kcompat
)
return
tryIPVSProxy
(
iptver
,
khandle
,
ipsetver
,
kcompat
)
}
else
{
}
else
{
glog
.
Warningf
(
"Can't use ipvs proxier, trying iptables proxier"
)
glog
.
Warningf
(
"Can't use ipvs proxier, trying iptables proxier"
)
return
tryIPTablesProxy
(
iptver
,
kcompat
)
return
tryIPTablesProxy
(
iptver
,
kcompat
)
...
@@ -290,10 +292,10 @@ func getProxyMode(proxyMode string, iptver iptables.IPTablesVersioner, ipsetver
...
@@ -290,10 +292,10 @@ func getProxyMode(proxyMode string, iptver iptables.IPTablesVersioner, ipsetver
return
tryIPTablesProxy
(
iptver
,
kcompat
)
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
// guaranteed false on error, error only necessary for debugging
// IPVS Proxier relies on ipset
// IPVS Proxier relies on ip
_vs_* kernel modules and ip
set
useIPVSProxy
,
err
:=
ipvs
.
CanUseIPVSProxier
(
ipsetver
)
useIPVSProxy
,
err
:=
ipvs
.
CanUseIPVSProxier
(
khandle
,
ipsetver
)
if
err
!=
nil
{
if
err
!=
nil
{
// Try to fallback to iptables before falling back to userspace
// 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
))
utilruntime
.
HandleError
(
fmt
.
Errorf
(
"can't determine whether to use ipvs proxy, error: %v"
,
err
))
...
...
cmd/kube-proxy/app/server_test.go
View file @
dc2e57ba
...
@@ -72,6 +72,15 @@ func (fake *fakeKernelCompatTester) IsCompatible() error {
...
@@ -72,6 +72,15 @@ func (fake *fakeKernelCompatTester) IsCompatible() error {
return
nil
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
)
{
func
Test_getProxyMode
(
t
*
testing
.
T
)
{
if
runtime
.
GOOS
!=
"linux"
{
if
runtime
.
GOOS
!=
"linux"
{
t
.
Skip
(
"skipping on non-Linux"
)
t
.
Skip
(
"skipping on non-Linux"
)
...
@@ -82,6 +91,7 @@ func Test_getProxyMode(t *testing.T) {
...
@@ -82,6 +91,7 @@ func Test_getProxyMode(t *testing.T) {
annotationVal
string
annotationVal
string
iptablesVersion
string
iptablesVersion
string
ipsetVersion
string
ipsetVersion
string
kmods
[]
string
kernelCompat
bool
kernelCompat
bool
iptablesError
error
iptablesError
error
ipsetError
error
ipsetError
error
...
@@ -140,7 +150,8 @@ func Test_getProxyMode(t *testing.T) {
...
@@ -140,7 +150,8 @@ func Test_getProxyMode(t *testing.T) {
versioner
:=
&
fakeIPTablesVersioner
{
c
.
iptablesVersion
,
c
.
iptablesError
}
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
}
r
:=
getProxyMode
(
c
.
flag
,
versioner
,
ipsetver
,
kcompater
)
khandler
:=
&
fakeKernelHandler
{
c
.
kmods
}
r
:=
getProxyMode
(
c
.
flag
,
versioner
,
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
)
}
}
...
...
pkg/proxy/ipvs/proxier.go
View file @
dc2e57ba
...
@@ -688,14 +688,28 @@ func (em proxyEndpointsMap) unmerge(other proxyEndpointsMap) {
...
@@ -688,14 +688,28 @@ func (em proxyEndpointsMap) unmerge(other proxyEndpointsMap) {
}
}
}
}
// CanUseIPVSProxier returns true if we can use the ipvs Proxier.
// KernelHandler can handle the current installed kernel modules.
// This is determined by checking if all the required kernel modules can be loaded. It may
type
KernelHandler
interface
{
// return an error if it fails to get the kernel modules information without error, in which
GetModules
()
([]
string
,
error
)
// case it will also return false.
}
func
CanUseIPVSProxier
(
ipsetver
IPSetVersioner
)
(
bool
,
error
)
{
// Try to load IPVS required kernel modules using modprobe
// LinuxKernelHandler implements KernelHandler interface.
type
LinuxKernelHandler
struct
{
executor
utilexec
.
Interface
}
// NewLinuxKernelHandler initializes LinuxKernelHandler with exec.
func
NewLinuxKernelHandler
()
*
LinuxKernelHandler
{
return
&
LinuxKernelHandler
{
executor
:
utilexec
.
New
(),
}
}
// GetModules returns all installed kernel modules.
func
(
handle
*
LinuxKernelHandler
)
GetModules
()
([]
string
,
error
)
{
// Try to load IPVS required kernel modules using modprobe first
for
_
,
kmod
:=
range
ipvsModules
{
for
_
,
kmod
:=
range
ipvsModules
{
err
:=
utilexec
.
New
()
.
Command
(
"modprobe"
,
"--"
,
kmod
)
.
Run
()
err
:=
handle
.
executor
.
Command
(
"modprobe"
,
"--"
,
kmod
)
.
Run
()
if
err
!=
nil
{
if
err
!=
nil
{
glog
.
Warningf
(
"Failed to load kernel module %v with modprobe. "
+
glog
.
Warningf
(
"Failed to load kernel module %v with modprobe. "
+
"You can ignore this message when kube-proxy is running inside container without mounting /lib/modules"
,
kmod
)
"You can ignore this message when kube-proxy is running inside container without mounting /lib/modules"
,
kmod
)
...
@@ -703,12 +717,24 @@ func CanUseIPVSProxier(ipsetver IPSetVersioner) (bool, error) {
...
@@ -703,12 +717,24 @@ func CanUseIPVSProxier(ipsetver IPSetVersioner) (bool, error) {
}
}
// Find out loaded kernel modules
// Find out loaded kernel modules
out
,
err
:=
utilexec
.
New
()
.
Command
(
"cut"
,
"-f1"
,
"-d"
,
" "
,
"/proc/modules"
)
.
CombinedOutput
()
out
,
err
:=
handle
.
executor
.
Command
(
"cut"
,
"-f1"
,
"-d"
,
" "
,
"/proc/modules"
)
.
CombinedOutput
()
if
err
!=
nil
{
if
err
!=
nil
{
return
false
,
err
return
nil
,
err
}
}
mods
:=
strings
.
Split
(
string
(
out
),
"
\n
"
)
mods
:=
strings
.
Split
(
string
(
out
),
"
\n
"
)
return
mods
,
nil
}
// CanUseIPVSProxier returns true if we can use the ipvs Proxier.
// This is determined by checking if all the required kernel modules can be loaded. It may
// return an error if it fails to get the kernel modules information without error, in which
// case it will also return false.
func
CanUseIPVSProxier
(
handle
KernelHandler
,
ipsetver
IPSetVersioner
)
(
bool
,
error
)
{
mods
,
err
:=
handle
.
GetModules
()
if
err
!=
nil
{
return
false
,
fmt
.
Errorf
(
"error getting installed ipvs required kernel modules: %v"
,
err
)
}
wantModules
:=
sets
.
NewString
()
wantModules
:=
sets
.
NewString
()
loadModules
:=
sets
.
NewString
()
loadModules
:=
sets
.
NewString
()
wantModules
.
Insert
(
ipvsModules
...
)
wantModules
.
Insert
(
ipvsModules
...
)
...
...
pkg/proxy/ipvs/proxier_test.go
View file @
dc2e57ba
...
@@ -18,6 +18,7 @@ package ipvs
...
@@ -18,6 +18,7 @@ package ipvs
import
(
import
(
"bytes"
"bytes"
"fmt"
"net"
"net"
"reflect"
"reflect"
"testing"
"testing"
...
@@ -87,6 +88,25 @@ func (fake *fakeHealthChecker) SyncEndpoints(newEndpoints map[types.NamespacedNa
...
@@ -87,6 +88,25 @@ func (fake *fakeHealthChecker) SyncEndpoints(newEndpoints map[types.NamespacedNa
return
nil
return
nil
}
}
// fakeKernelHandler implements KernelHandler.
type
fakeKernelHandler
struct
{
modules
[]
string
}
func
(
fake
*
fakeKernelHandler
)
GetModules
()
([]
string
,
error
)
{
return
fake
.
modules
,
nil
}
// fakeKernelHandler implements KernelHandler.
type
fakeIPSetVersioner
struct
{
version
string
err
error
}
func
(
fake
*
fakeIPSetVersioner
)
GetVersion
()
(
string
,
error
)
{
return
fake
.
version
,
fake
.
err
}
func
NewFakeProxier
(
ipt
utiliptables
.
Interface
,
ipvs
utilipvs
.
Interface
,
ipset
utilipset
.
Interface
,
nodeIPs
[]
net
.
IP
)
*
Proxier
{
func
NewFakeProxier
(
ipt
utiliptables
.
Interface
,
ipvs
utilipvs
.
Interface
,
ipset
utilipset
.
Interface
,
nodeIPs
[]
net
.
IP
)
*
Proxier
{
fcmd
:=
fakeexec
.
FakeCmd
{
fcmd
:=
fakeexec
.
FakeCmd
{
CombinedOutputScript
:
[]
fakeexec
.
FakeCombinedOutputAction
{
CombinedOutputScript
:
[]
fakeexec
.
FakeCombinedOutputAction
{
...
@@ -180,6 +200,70 @@ func makeTestEndpoints(namespace, name string, eptFunc func(*api.Endpoints)) *ap
...
@@ -180,6 +200,70 @@ func makeTestEndpoints(namespace, name string, eptFunc func(*api.Endpoints)) *ap
return
ept
return
ept
}
}
func
TestCanUseIPVSProxier
(
t
*
testing
.
T
)
{
testCases
:=
[]
struct
{
mods
[]
string
kernelErr
error
ipsetVersion
string
ipsetErr
error
ok
bool
}{
// case 0, kernel error
{
mods
:
[]
string
{
"foo"
,
"bar"
,
"baz"
},
kernelErr
:
fmt
.
Errorf
(
"oops"
),
ipsetVersion
:
"0.0"
,
ok
:
false
,
},
// case 1, ipset error
{
mods
:
[]
string
{
"foo"
,
"bar"
,
"baz"
},
ipsetVersion
:
MinIPSetCheckVersion
,
ipsetErr
:
fmt
.
Errorf
(
"oops"
),
ok
:
false
,
},
// case 2, missing required kernel modules and ipset version too low
{
mods
:
[]
string
{
"foo"
,
"bar"
,
"baz"
},
ipsetVersion
:
"1.1"
,
ok
:
false
,
},
// case 3, missing required ip_vs_* kernel modules
{
mods
:
[]
string
{
"ip_vs"
,
"a"
,
"bc"
,
"def"
},
ipsetVersion
:
MinIPSetCheckVersion
,
ok
:
false
,
},
// case 4, ipset version too low
{
mods
:
[]
string
{
"ip_vs"
,
"ip_vs_rr"
,
"ip_vs_wrr"
,
"ip_vs_sh"
,
"nf_conntrack_ipv4"
},
ipsetVersion
:
"4.3.0"
,
ok
:
false
,
},
// case 5
{
mods
:
[]
string
{
"ip_vs"
,
"ip_vs_rr"
,
"ip_vs_wrr"
,
"ip_vs_sh"
,
"nf_conntrack_ipv4"
},
ipsetVersion
:
MinIPSetCheckVersion
,
ok
:
true
,
},
// case 6
{
mods
:
[]
string
{
"ip_vs"
,
"ip_vs_rr"
,
"ip_vs_wrr"
,
"ip_vs_sh"
,
"nf_conntrack_ipv4"
,
"foo"
,
"bar"
},
ipsetVersion
:
"6.19"
,
ok
:
true
,
},
}
for
i
:=
range
testCases
{
handle
:=
&
fakeKernelHandler
{
modules
:
testCases
[
i
]
.
mods
}
versioner
:=
&
fakeIPSetVersioner
{
version
:
testCases
[
i
]
.
ipsetVersion
,
err
:
testCases
[
i
]
.
ipsetErr
}
ok
,
_
:=
CanUseIPVSProxier
(
handle
,
versioner
)
if
ok
!=
testCases
[
i
]
.
ok
{
t
.
Errorf
(
"Case [%d], expect %v, got %v"
,
i
,
testCases
[
i
]
.
ok
,
ok
)
}
}
}
func
TestNodePort
(
t
*
testing
.
T
)
{
func
TestNodePort
(
t
*
testing
.
T
)
{
ipt
:=
iptablestest
.
NewFake
()
ipt
:=
iptablestest
.
NewFake
()
ipvs
:=
ipvstest
.
NewFake
()
ipvs
:=
ipvstest
.
NewFake
()
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment