Skip to content

Commit e9a3d99

Browse files
authored
Merge pull request kubernetes#129826 from danwinship/iptables-constructors
fix up iptables construction, kubelet iptables startup messages
2 parents 1177529 + 8c98dee commit e9a3d99

File tree

7 files changed

+370
-109
lines changed

7 files changed

+370
-109
lines changed

cmd/kube-proxy/app/server_linux.go

Lines changed: 10 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,6 @@ import (
5050
"k8s.io/kubernetes/pkg/proxy/nftables"
5151
proxyutil "k8s.io/kubernetes/pkg/proxy/util"
5252
utiliptables "k8s.io/kubernetes/pkg/util/iptables"
53-
"k8s.io/utils/exec"
5453
)
5554

5655
// timeoutForNodePodCIDR is the time to wait for allocators to assign a PodCIDR to the
@@ -105,37 +104,15 @@ func isIPTablesBased(mode proxyconfigapi.ProxyMode) bool {
105104
return mode == proxyconfigapi.ProxyModeIPTables || mode == proxyconfigapi.ProxyModeIPVS
106105
}
107106

108-
// getIPTables returns an array of [IPv4, IPv6] utiliptables.Interfaces. If primaryFamily
109-
// is not v1.IPFamilyUnknown then it will also separately return the interface for just
110-
// that family.
111-
func getIPTables(primaryFamily v1.IPFamily) ([2]utiliptables.Interface, utiliptables.Interface) {
112-
execer := exec.New()
113-
114-
// Create iptables handlers for both families. Always ordered as IPv4, IPv6
115-
ipt := [2]utiliptables.Interface{
116-
utiliptables.New(execer, utiliptables.ProtocolIPv4),
117-
utiliptables.New(execer, utiliptables.ProtocolIPv6),
118-
}
119-
120-
var iptInterface utiliptables.Interface
121-
if primaryFamily == v1.IPv4Protocol {
122-
iptInterface = ipt[0]
123-
} else if primaryFamily == v1.IPv6Protocol {
124-
iptInterface = ipt[1]
125-
}
126-
127-
return ipt, iptInterface
128-
}
129-
130107
// platformCheckSupported is called immediately before creating the Proxier, to check
131108
// what IP families are supported (and whether the configuration is usable at all).
132109
func (s *ProxyServer) platformCheckSupported(ctx context.Context) (ipv4Supported, ipv6Supported, dualStackSupported bool, err error) {
133110
logger := klog.FromContext(ctx)
134111

135112
if isIPTablesBased(s.Config.Mode) {
136-
ipt, _ := getIPTables(v1.IPFamilyUnknown)
137-
ipv4Supported = ipt[0].Present()
138-
ipv6Supported = ipt[1].Present()
113+
ipts := utiliptables.NewDualStack()
114+
ipv4Supported = ipts[v1.IPv4Protocol] != nil
115+
ipv6Supported = ipts[v1.IPv6Protocol] != nil
139116

140117
if !ipv4Supported && !ipv6Supported {
141118
err = fmt.Errorf("iptables is not available on this host")
@@ -166,14 +143,13 @@ func (s *ProxyServer) createProxier(ctx context.Context, config *proxyconfigapi.
166143

167144
if config.Mode == proxyconfigapi.ProxyModeIPTables {
168145
logger.Info("Using iptables Proxier")
146+
ipts := utiliptables.NewDualStack()
169147

170148
if dualStack {
171-
ipt, _ := getIPTables(s.PrimaryIPFamily)
172-
173149
// TODO this has side effects that should only happen when Run() is invoked.
174150
proxier, err = iptables.NewDualStackProxier(
175151
ctx,
176-
ipt,
152+
ipts,
177153
utilsysctl.New(),
178154
config.SyncPeriod.Duration,
179155
config.MinSyncPeriod.Duration,
@@ -190,13 +166,12 @@ func (s *ProxyServer) createProxier(ctx context.Context, config *proxyconfigapi.
190166
)
191167
} else {
192168
// Create a single-stack proxier if and only if the node does not support dual-stack (i.e, no iptables support).
193-
_, iptInterface := getIPTables(s.PrimaryIPFamily)
194169

195170
// TODO this has side effects that should only happen when Run() is invoked.
196171
proxier, err = iptables.NewProxier(
197172
ctx,
198173
s.PrimaryIPFamily,
199-
iptInterface,
174+
ipts[s.PrimaryIPFamily],
200175
utilsysctl.New(),
201176
config.SyncPeriod.Duration,
202177
config.MinSyncPeriod.Duration,
@@ -222,13 +197,13 @@ func (s *ProxyServer) createProxier(ctx context.Context, config *proxyconfigapi.
222197
if err := ipvs.CanUseIPVSProxier(ctx, ipvsInterface, ipsetInterface, config.IPVS.Scheduler); err != nil {
223198
return nil, fmt.Errorf("can't use the IPVS proxier: %v", err)
224199
}
200+
ipts := utiliptables.NewDualStack()
225201

226202
logger.Info("Using ipvs Proxier")
227203
if dualStack {
228-
ipt, _ := getIPTables(s.PrimaryIPFamily)
229204
proxier, err = ipvs.NewDualStackProxier(
230205
ctx,
231-
ipt,
206+
ipts,
232207
ipvsInterface,
233208
ipsetInterface,
234209
utilsysctl.New(),
@@ -251,11 +226,10 @@ func (s *ProxyServer) createProxier(ctx context.Context, config *proxyconfigapi.
251226
initOnly,
252227
)
253228
} else {
254-
_, iptInterface := getIPTables(s.PrimaryIPFamily)
255229
proxier, err = ipvs.NewProxier(
256230
ctx,
257231
s.PrimaryIPFamily,
258-
iptInterface,
232+
ipts[s.PrimaryIPFamily],
259233
ipvsInterface,
260234
ipsetInterface,
261235
utilsysctl.New(),
@@ -509,7 +483,7 @@ func platformCleanup(ctx context.Context, mode proxyconfigapi.ProxyMode, cleanup
509483

510484
// Clean up iptables and ipvs rules if switching to nftables, or if cleanupAndExit
511485
if !isIPTablesBased(mode) || cleanupAndExit {
512-
ipts, _ := getIPTables(v1.IPFamilyUnknown)
486+
ipts := utiliptables.NewDualStack()
513487
ipsetInterface := utilipset.New()
514488
ipvsInterface := utilipvs.New()
515489

pkg/kubelet/kubelet_network_linux.go

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ import (
2525
"k8s.io/apimachinery/pkg/util/wait"
2626
"k8s.io/klog/v2"
2727
utiliptables "k8s.io/kubernetes/pkg/util/iptables"
28-
utilexec "k8s.io/utils/exec"
2928
)
3029

3130
const (
@@ -38,14 +37,14 @@ const (
3837
)
3938

4039
func (kl *Kubelet) initNetworkUtil() {
41-
exec := utilexec.New()
42-
iptClients := []utiliptables.Interface{
43-
utiliptables.New(exec, utiliptables.ProtocolIPv4),
44-
utiliptables.New(exec, utiliptables.ProtocolIPv6),
40+
iptClients := utiliptables.NewDualStack()
41+
if len(iptClients) == 0 {
42+
klog.InfoS("No iptables support on this system; not creating the KUBE-IPTABLES-HINT chain")
43+
return
4544
}
4645

47-
for i := range iptClients {
48-
iptClient := iptClients[i]
46+
for family := range iptClients {
47+
iptClient := iptClients[family]
4948
if kl.syncIPTablesRules(iptClient) {
5049
klog.InfoS("Initialized iptables rules.", "protocol", iptClient.Protocol())
5150
go iptClient.Monitor(

pkg/proxy/iptables/proxier.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ const sysctlNFConntrackTCPBeLiberal = "net/netfilter/nf_conntrack_tcp_be_liberal
9494
// NewDualStackProxier creates a MetaProxier instance, with IPv4 and IPv6 proxies.
9595
func NewDualStackProxier(
9696
ctx context.Context,
97-
ipt [2]utiliptables.Interface,
97+
ipts map[v1.IPFamily]utiliptables.Interface,
9898
sysctl utilsysctl.Interface,
9999
syncPeriod time.Duration,
100100
minSyncPeriod time.Duration,
@@ -110,15 +110,15 @@ func NewDualStackProxier(
110110
initOnly bool,
111111
) (proxy.Provider, error) {
112112
// Create an ipv4 instance of the single-stack proxier
113-
ipv4Proxier, err := NewProxier(ctx, v1.IPv4Protocol, ipt[0], sysctl,
113+
ipv4Proxier, err := NewProxier(ctx, v1.IPv4Protocol, ipts[v1.IPv4Protocol], sysctl,
114114
syncPeriod, minSyncPeriod, masqueradeAll, localhostNodePorts, masqueradeBit,
115115
localDetectors[v1.IPv4Protocol], hostname, nodeIPs[v1.IPv4Protocol],
116116
recorder, healthzServer, nodePortAddresses, initOnly)
117117
if err != nil {
118118
return nil, fmt.Errorf("unable to create ipv4 proxier: %v", err)
119119
}
120120

121-
ipv6Proxier, err := NewProxier(ctx, v1.IPv6Protocol, ipt[1], sysctl,
121+
ipv6Proxier, err := NewProxier(ctx, v1.IPv6Protocol, ipts[v1.IPv6Protocol], sysctl,
122122
syncPeriod, minSyncPeriod, masqueradeAll, false, masqueradeBit,
123123
localDetectors[v1.IPv6Protocol], hostname, nodeIPs[v1.IPv6Protocol],
124124
recorder, healthzServer, nodePortAddresses, initOnly)

pkg/proxy/ipvs/proxier.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ const (
110110
// NewDualStackProxier returns a new Proxier for dual-stack operation
111111
func NewDualStackProxier(
112112
ctx context.Context,
113-
ipt [2]utiliptables.Interface,
113+
ipts map[v1.IPFamily]utiliptables.Interface,
114114
ipvs utilipvs.Interface,
115115
ipset utilipset.Interface,
116116
sysctl utilsysctl.Interface,
@@ -133,7 +133,7 @@ func NewDualStackProxier(
133133
initOnly bool,
134134
) (proxy.Provider, error) {
135135
// Create an ipv4 instance of the single-stack proxier
136-
ipv4Proxier, err := NewProxier(ctx, v1.IPv4Protocol, ipt[0], ipvs, ipset, sysctl,
136+
ipv4Proxier, err := NewProxier(ctx, v1.IPv4Protocol, ipts[v1.IPv4Protocol], ipvs, ipset, sysctl,
137137
syncPeriod, minSyncPeriod, filterCIDRs(false, excludeCIDRs), strictARP,
138138
tcpTimeout, tcpFinTimeout, udpTimeout, masqueradeAll, masqueradeBit,
139139
localDetectors[v1.IPv4Protocol], hostname, nodeIPs[v1.IPv4Protocol], recorder,
@@ -142,7 +142,7 @@ func NewDualStackProxier(
142142
return nil, fmt.Errorf("unable to create ipv4 proxier: %v", err)
143143
}
144144

145-
ipv6Proxier, err := NewProxier(ctx, v1.IPv6Protocol, ipt[1], ipvs, ipset, sysctl,
145+
ipv6Proxier, err := NewProxier(ctx, v1.IPv6Protocol, ipts[v1.IPv6Protocol], ipvs, ipset, sysctl,
146146
syncPeriod, minSyncPeriod, filterCIDRs(true, excludeCIDRs), strictARP,
147147
tcpTimeout, tcpFinTimeout, udpTimeout, masqueradeAll, masqueradeBit,
148148
localDetectors[v1.IPv6Protocol], hostname, nodeIPs[v1.IPv6Protocol], recorder,

pkg/util/iptables/iptables.go

Lines changed: 38 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import (
3030
"sync"
3131
"time"
3232

33+
"k8s.io/api/core/v1"
3334
"k8s.io/apimachinery/pkg/util/sets"
3435
utilversion "k8s.io/apimachinery/pkg/util/version"
3536
utilwait "k8s.io/apimachinery/pkg/util/wait"
@@ -219,12 +220,6 @@ type runner struct {
219220
// newInternal returns a new Interface which will exec iptables, and allows the
220221
// caller to change the iptables-restore lockfile path
221222
func newInternal(exec utilexec.Interface, protocol Protocol, lockfilePath14x, lockfilePath16x string) Interface {
222-
version, err := getIPTablesVersion(exec, protocol)
223-
if err != nil {
224-
klog.InfoS("Error checking iptables version, assuming version at least", "version", MinCheckVersion, "err", err)
225-
version = MinCheckVersion
226-
}
227-
228223
if lockfilePath16x == "" {
229224
lockfilePath16x = LockfilePath16x
230225
}
@@ -235,19 +230,50 @@ func newInternal(exec utilexec.Interface, protocol Protocol, lockfilePath14x, lo
235230
runner := &runner{
236231
exec: exec,
237232
protocol: protocol,
238-
hasCheck: version.AtLeast(MinCheckVersion),
239-
hasRandomFully: version.AtLeast(RandomFullyMinVersion),
240-
waitFlag: getIPTablesWaitFlag(version),
241-
restoreWaitFlag: getIPTablesRestoreWaitFlag(version, exec, protocol),
242233
lockfilePath14x: lockfilePath14x,
243234
lockfilePath16x: lockfilePath16x,
244235
}
236+
237+
version, err := getIPTablesVersion(exec, protocol)
238+
if err != nil {
239+
// The only likely error is "no such file or directory", in which case any
240+
// further commands will fail the same way, so we don't need to do
241+
// anything special here.
242+
return runner
243+
}
244+
245+
runner.hasCheck = version.AtLeast(MinCheckVersion)
246+
runner.hasRandomFully = version.AtLeast(RandomFullyMinVersion)
247+
runner.waitFlag = getIPTablesWaitFlag(version)
248+
runner.restoreWaitFlag = getIPTablesRestoreWaitFlag(version, exec, protocol)
245249
return runner
246250
}
247251

248252
// New returns a new Interface which will exec iptables.
249-
func New(exec utilexec.Interface, protocol Protocol) Interface {
250-
return newInternal(exec, protocol, "", "")
253+
func New(protocol Protocol) Interface {
254+
return newInternal(utilexec.New(), protocol, "", "")
255+
}
256+
257+
func newDualStackInternal(exec utilexec.Interface) map[v1.IPFamily]Interface {
258+
interfaces := map[v1.IPFamily]Interface{}
259+
260+
iptv4 := newInternal(exec, ProtocolIPv4, "", "")
261+
if iptv4.Present() {
262+
interfaces[v1.IPv4Protocol] = iptv4
263+
}
264+
iptv6 := newInternal(exec, ProtocolIPv6, "", "")
265+
if iptv6.Present() {
266+
interfaces[v1.IPv6Protocol] = iptv6
267+
}
268+
269+
return interfaces
270+
}
271+
272+
// NewDualStack returns a map containing an IPv4 Interface (if IPv4 iptables is supported)
273+
// and an IPv6 Interface (if IPv6 iptables is supported). If either family is not
274+
// supported, no Interface will be returned for that family.
275+
func NewDualStack() map[v1.IPFamily]Interface {
276+
return newDualStackInternal(utilexec.New())
251277
}
252278

253279
// EnsureChain is part of Interface.

0 commit comments

Comments
 (0)