Skip to content

Commit 1ade4ce

Browse files
authored
Merge pull request kubernetes#82091 from khenidak/ipvs-dualstack
dualstack: IPVS proxier
2 parents f442b6e + ef75723 commit 1ade4ce

File tree

8 files changed

+527
-24
lines changed

8 files changed

+527
-24
lines changed

cmd/kube-proxy/app/BUILD

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,69 +79,79 @@ go_library(
7979
"//pkg/util/node:go_default_library",
8080
"//staging/src/k8s.io/apimachinery/pkg/types:go_default_library",
8181
"//staging/src/k8s.io/apimachinery/pkg/util/net:go_default_library",
82+
"//vendor/k8s.io/utils/net:go_default_library",
8283
],
8384
"@io_bazel_rules_go//go/platform:darwin": [
8485
"//pkg/proxy/metrics:go_default_library",
8586
"//pkg/util/dbus:go_default_library",
8687
"//pkg/util/node:go_default_library",
8788
"//staging/src/k8s.io/apimachinery/pkg/types:go_default_library",
8889
"//staging/src/k8s.io/apimachinery/pkg/util/net:go_default_library",
90+
"//vendor/k8s.io/utils/net:go_default_library",
8991
],
9092
"@io_bazel_rules_go//go/platform:dragonfly": [
9193
"//pkg/proxy/metrics:go_default_library",
9294
"//pkg/util/dbus:go_default_library",
9395
"//pkg/util/node:go_default_library",
9496
"//staging/src/k8s.io/apimachinery/pkg/types:go_default_library",
9597
"//staging/src/k8s.io/apimachinery/pkg/util/net:go_default_library",
98+
"//vendor/k8s.io/utils/net:go_default_library",
9699
],
97100
"@io_bazel_rules_go//go/platform:freebsd": [
98101
"//pkg/proxy/metrics:go_default_library",
99102
"//pkg/util/dbus:go_default_library",
100103
"//pkg/util/node:go_default_library",
101104
"//staging/src/k8s.io/apimachinery/pkg/types:go_default_library",
102105
"//staging/src/k8s.io/apimachinery/pkg/util/net:go_default_library",
106+
"//vendor/k8s.io/utils/net:go_default_library",
103107
],
104108
"@io_bazel_rules_go//go/platform:linux": [
105109
"//pkg/proxy/metrics:go_default_library",
106110
"//pkg/util/dbus:go_default_library",
107111
"//pkg/util/node:go_default_library",
108112
"//staging/src/k8s.io/apimachinery/pkg/types:go_default_library",
109113
"//staging/src/k8s.io/apimachinery/pkg/util/net:go_default_library",
114+
"//vendor/k8s.io/utils/net:go_default_library",
110115
],
111116
"@io_bazel_rules_go//go/platform:nacl": [
112117
"//pkg/proxy/metrics:go_default_library",
113118
"//pkg/util/dbus:go_default_library",
114119
"//pkg/util/node:go_default_library",
115120
"//staging/src/k8s.io/apimachinery/pkg/types:go_default_library",
116121
"//staging/src/k8s.io/apimachinery/pkg/util/net:go_default_library",
122+
"//vendor/k8s.io/utils/net:go_default_library",
117123
],
118124
"@io_bazel_rules_go//go/platform:netbsd": [
119125
"//pkg/proxy/metrics:go_default_library",
120126
"//pkg/util/dbus:go_default_library",
121127
"//pkg/util/node:go_default_library",
122128
"//staging/src/k8s.io/apimachinery/pkg/types:go_default_library",
123129
"//staging/src/k8s.io/apimachinery/pkg/util/net:go_default_library",
130+
"//vendor/k8s.io/utils/net:go_default_library",
124131
],
125132
"@io_bazel_rules_go//go/platform:openbsd": [
126133
"//pkg/proxy/metrics:go_default_library",
127134
"//pkg/util/dbus:go_default_library",
128135
"//pkg/util/node:go_default_library",
129136
"//staging/src/k8s.io/apimachinery/pkg/types:go_default_library",
130137
"//staging/src/k8s.io/apimachinery/pkg/util/net:go_default_library",
138+
"//vendor/k8s.io/utils/net:go_default_library",
131139
],
132140
"@io_bazel_rules_go//go/platform:plan9": [
133141
"//pkg/proxy/metrics:go_default_library",
134142
"//pkg/util/dbus:go_default_library",
135143
"//pkg/util/node:go_default_library",
136144
"//staging/src/k8s.io/apimachinery/pkg/types:go_default_library",
137145
"//staging/src/k8s.io/apimachinery/pkg/util/net:go_default_library",
146+
"//vendor/k8s.io/utils/net:go_default_library",
138147
],
139148
"@io_bazel_rules_go//go/platform:solaris": [
140149
"//pkg/proxy/metrics:go_default_library",
141150
"//pkg/util/dbus:go_default_library",
142151
"//pkg/util/node:go_default_library",
143152
"//staging/src/k8s.io/apimachinery/pkg/types:go_default_library",
144153
"//staging/src/k8s.io/apimachinery/pkg/util/net:go_default_library",
154+
"//vendor/k8s.io/utils/net:go_default_library",
145155
],
146156
"@io_bazel_rules_go//go/platform:windows": [
147157
"//pkg/proxy/winkernel:go_default_library",

cmd/kube-proxy/app/server_others.go

Lines changed: 99 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,15 @@ import (
2424
"errors"
2525
"fmt"
2626
"net"
27+
"strings"
2728

2829
"k8s.io/api/core/v1"
2930
"k8s.io/apimachinery/pkg/types"
3031
utilnet "k8s.io/apimachinery/pkg/util/net"
3132
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
33+
utilfeature "k8s.io/apiserver/pkg/util/feature"
3234
"k8s.io/client-go/tools/record"
35+
"k8s.io/kubernetes/pkg/features"
3336
"k8s.io/kubernetes/pkg/proxy"
3437
proxyconfigapi "k8s.io/kubernetes/pkg/proxy/apis/config"
3538
proxyconfigscheme "k8s.io/kubernetes/pkg/proxy/apis/config/scheme"
@@ -46,6 +49,7 @@ import (
4649
utilnode "k8s.io/kubernetes/pkg/util/node"
4750
utilsysctl "k8s.io/kubernetes/pkg/util/sysctl"
4851
"k8s.io/utils/exec"
52+
utilsnet "k8s.io/utils/net"
4953

5054
"k8s.io/klog"
5155
)
@@ -170,26 +174,61 @@ func newProxyServer(
170174
metrics.RegisterMetrics()
171175
} else if proxyMode == proxyModeIPVS {
172176
klog.V(0).Info("Using ipvs Proxier.")
173-
proxier, err = ipvs.NewProxier(
174-
iptInterface,
175-
ipvsInterface,
176-
ipsetInterface,
177-
utilsysctl.New(),
178-
execer,
179-
config.IPVS.SyncPeriod.Duration,
180-
config.IPVS.MinSyncPeriod.Duration,
181-
config.IPVS.ExcludeCIDRs,
182-
config.IPVS.StrictARP,
183-
config.IPTables.MasqueradeAll,
184-
int(*config.IPTables.MasqueradeBit),
185-
config.ClusterCIDR,
186-
hostname,
187-
nodeIP,
188-
recorder,
189-
healthzServer,
190-
config.IPVS.Scheduler,
191-
config.NodePortAddresses,
192-
)
177+
if utilfeature.DefaultFeatureGate.Enabled(features.IPv6DualStack) {
178+
klog.V(0).Info("creating dualStackProxier for ipvs.")
179+
180+
// Create iptables handlers for both families, one is already created
181+
var ipt [2]utiliptables.Interface
182+
if iptInterface.IsIpv6() {
183+
ipt[1] = iptInterface
184+
ipt[0] = utiliptables.New(execer, dbus, utiliptables.ProtocolIpv4)
185+
} else {
186+
ipt[0] = iptInterface
187+
ipt[1] = utiliptables.New(execer, dbus, utiliptables.ProtocolIpv6)
188+
}
189+
190+
proxier, err = ipvs.NewDualStackProxier(
191+
ipt,
192+
ipvsInterface,
193+
ipsetInterface,
194+
utilsysctl.New(),
195+
execer,
196+
config.IPVS.SyncPeriod.Duration,
197+
config.IPVS.MinSyncPeriod.Duration,
198+
config.IPVS.ExcludeCIDRs,
199+
config.IPVS.StrictARP,
200+
config.IPTables.MasqueradeAll,
201+
int(*config.IPTables.MasqueradeBit),
202+
cidrTuple(config.ClusterCIDR),
203+
hostname,
204+
nodeIPTuple(config.BindAddress),
205+
recorder,
206+
healthzServer,
207+
config.IPVS.Scheduler,
208+
config.NodePortAddresses,
209+
)
210+
} else {
211+
proxier, err = ipvs.NewProxier(
212+
iptInterface,
213+
ipvsInterface,
214+
ipsetInterface,
215+
utilsysctl.New(),
216+
execer,
217+
config.IPVS.SyncPeriod.Duration,
218+
config.IPVS.MinSyncPeriod.Duration,
219+
config.IPVS.ExcludeCIDRs,
220+
config.IPVS.StrictARP,
221+
config.IPTables.MasqueradeAll,
222+
int(*config.IPTables.MasqueradeBit),
223+
config.ClusterCIDR,
224+
hostname,
225+
nodeIP,
226+
recorder,
227+
healthzServer,
228+
config.IPVS.Scheduler,
229+
config.NodePortAddresses,
230+
)
231+
}
193232
if err != nil {
194233
return nil, fmt.Errorf("unable to create proxier: %v", err)
195234
}
@@ -238,6 +277,46 @@ func newProxyServer(
238277
}, nil
239278
}
240279

280+
// cidrTuple takes a comma separated list of CIDRs and return a tuple (ipv4cidr,ipv6cidr)
281+
// The returned tuple is guaranteed to have the order (ipv4,ipv6) and if no cidr from a family is found an
282+
// empty string "" is inserted.
283+
func cidrTuple(cidrList string) [2]string {
284+
cidrs := [2]string{"", ""}
285+
foundIPv4 := false
286+
foundIPv6 := false
287+
288+
for _, cidr := range strings.Split(cidrList, ",") {
289+
if utilsnet.IsIPv6CIDRString(cidr) && !foundIPv6 {
290+
cidrs[1] = cidr
291+
foundIPv6 = true
292+
} else if !foundIPv4 {
293+
cidrs[0] = cidr
294+
foundIPv4 = true
295+
}
296+
if foundIPv6 && foundIPv4 {
297+
break
298+
}
299+
}
300+
301+
return cidrs
302+
}
303+
304+
// nodeIPTuple takes an addresses and return a tuple (ipv4,ipv6)
305+
// The returned tuple is guaranteed to have the order (ipv4,ipv6). The address NOT of the passed address
306+
// will have "any" address (0.0.0.0 or ::) inserted.
307+
func nodeIPTuple(bindAddress string) [2]net.IP {
308+
nodes := [2]net.IP{net.IPv4zero, net.IPv6zero}
309+
310+
adr := net.ParseIP(bindAddress)
311+
if utilsnet.IsIPv6(adr) {
312+
nodes[1] = adr
313+
} else {
314+
nodes[0] = adr
315+
}
316+
317+
return nodes
318+
}
319+
241320
func getProxyMode(proxyMode string, khandle ipvs.KernelHandler, ipsetver ipvs.IPSetVersioner, kcompat iptables.KernelCompatTester) string {
242321
switch proxyMode {
243322
case proxyModeUserspace:

pkg/proxy/ipvs/BUILD

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,12 @@ go_library(
4343
srcs = [
4444
"graceful_termination.go",
4545
"ipset.go",
46+
"meta_proxier.go",
4647
"netlink.go",
4748
"netlink_linux.go",
4849
"netlink_unsupported.go",
4950
"proxier.go",
51+
"safe_ipset.go",
5052
],
5153
importpath = "k8s.io/kubernetes/pkg/proxy/ipvs",
5254
deps = [

pkg/proxy/ipvs/ipset.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323

2424
"fmt"
2525
"k8s.io/klog"
26+
"strings"
2627
)
2728

2829
const (
@@ -102,6 +103,20 @@ func NewIPSet(handle utilipset.Interface, name string, setType utilipset.Type, i
102103
hashFamily := utilipset.ProtocolFamilyIPV4
103104
if isIPv6 {
104105
hashFamily = utilipset.ProtocolFamilyIPV6
106+
// In dual-stack both ipv4 and ipv6 ipset's can co-exist. To
107+
// ensure unique names the prefix for ipv6 is changed from
108+
// "KUBE-" to "KUBE-6-". The "KUBE-" prefix is kept for
109+
// backward compatibility. The maximum name length of an ipset
110+
// is 31 characters which must be taken into account. The
111+
// ipv4 names are not altered to minimize the risk for
112+
// problems on upgrades.
113+
if strings.HasPrefix(name, "KUBE-") {
114+
name = strings.Replace(name, "KUBE-", "KUBE-6-", 1)
115+
if len(name) > 31 {
116+
klog.Warningf("ipset name truncated; [%s] -> [%s]", name, name[:31])
117+
name = name[:31]
118+
}
119+
}
105120
}
106121
set := &IPSet{
107122
IPSet: utilipset.IPSet{

0 commit comments

Comments
 (0)