Skip to content

Commit 8bced9b

Browse files
committed
iptables: don't do feature detection on the iptables-restore binary
The iptables code was doing version detection on the iptables binary but feature detection on the iptables-restore binary, to try to support the version of iptables in RHEL 7, which claims to be 1.4.21 but has certain features from iptables 1.6. The problem is that this particular set of versions and checks resulted in the code passing "-w" ("wait forever for the lock") to iptables, but "-w 5" ("wait at most 5 seconds for the lock") to iptables-restore. On systems with very very many iptables rules, this could result in the kubelet periodic resyncs (which use "iptables") blocking kube-proxy (which uses "iptables-restore") and causing it to time out. We already have code to grab the lock file by hand when using a version of iptables-restore that doesn't support "-w", and it works fine. So just use that instead, and only pass "-w 5" to iptables-restore when iptables reports a version that actually supports it.
1 parent 9c22ff1 commit 8bced9b

File tree

2 files changed

+93
-200
lines changed

2 files changed

+93
-200
lines changed

pkg/util/iptables/iptables.go

Lines changed: 12 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ const MinCheckVersion = "1.4.11"
126126
// Minimum iptables versions supporting the -w and -w<seconds> flags
127127
const WaitMinVersion = "1.4.20"
128128
const WaitSecondsMinVersion = "1.4.22"
129+
const WaitRestoreMinVersion = "1.6.2"
129130
const WaitString = "-w"
130131
const WaitSecondsValue = "5"
131132

@@ -167,7 +168,7 @@ func newInternal(exec utilexec.Interface, dbus utildbus.Interface, protocol Prot
167168
hasCheck: getIPTablesHasCheckCommand(vstring),
168169
hasListener: false,
169170
waitFlag: getIPTablesWaitFlag(vstring),
170-
restoreWaitFlag: getIPTablesRestoreWaitFlag(exec, protocol),
171+
restoreWaitFlag: getIPTablesRestoreWaitFlag(vstring),
171172
lockfilePath: lockfilePath,
172173
}
173174
return runner
@@ -580,7 +581,6 @@ func getIPTablesWaitFlag(vstring string) []string {
580581
return []string{WaitString}
581582
}
582583
return []string{WaitString, WaitSecondsValue}
583-
584584
}
585585

586586
// getIPTablesVersionString runs "iptables --version" to get the version string
@@ -601,44 +601,22 @@ func getIPTablesVersionString(exec utilexec.Interface, protocol Protocol) (strin
601601
}
602602

603603
// Checks if iptables-restore has a "wait" flag
604-
// --wait support landed in v1.6.1+ right before --version support, so
605-
// any version of iptables-restore that supports --version will also
606-
// support --wait
607-
func getIPTablesRestoreWaitFlag(exec utilexec.Interface, protocol Protocol) []string {
608-
vstring, err := getIPTablesRestoreVersionString(exec, protocol)
609-
if err != nil || vstring == "" {
610-
klog.V(3).Infof("couldn't get iptables-restore version; assuming it doesn't support --wait")
611-
return nil
612-
}
613-
if _, err := utilversion.ParseGeneric(vstring); err != nil {
614-
klog.V(3).Infof("couldn't parse iptables-restore version; assuming it doesn't support --wait")
604+
func getIPTablesRestoreWaitFlag(vstring string) []string {
605+
version, err := utilversion.ParseGeneric(vstring)
606+
if err != nil {
607+
klog.Errorf("vstring (%s) is not a valid version string: %v", vstring, err)
615608
return nil
616609
}
617610

618-
return []string{WaitString, WaitSecondsValue}
619-
}
620-
621-
// getIPTablesRestoreVersionString runs "iptables-restore --version" to get the version string
622-
// in the form "X.X.X"
623-
func getIPTablesRestoreVersionString(exec utilexec.Interface, protocol Protocol) (string, error) {
624-
// this doesn't access mutable state so we don't need to use the interface / runner
625-
626-
// iptables-restore hasn't always had --version, and worse complains
627-
// about unrecognized commands but doesn't exit when it gets them.
628-
// Work around that by setting stdin to nothing so it exits immediately.
629-
iptablesRestoreCmd := iptablesRestoreCommand(protocol)
630-
cmd := exec.Command(iptablesRestoreCmd, "--version")
631-
cmd.SetStdin(bytes.NewReader([]byte{}))
632-
bytes, err := cmd.CombinedOutput()
611+
minVersion, err := utilversion.ParseGeneric(WaitRestoreMinVersion)
633612
if err != nil {
634-
return "", err
613+
klog.Errorf("WaitRestoreMinVersion (%s) is not a valid version string: %v", WaitRestoreMinVersion, err)
614+
return nil
635615
}
636-
versionMatcher := regexp.MustCompile("v([0-9]+(\\.[0-9]+)+)")
637-
match := versionMatcher.FindStringSubmatch(string(bytes))
638-
if match == nil {
639-
return "", fmt.Errorf("no iptables version found in string: %s", bytes)
616+
if version.LessThan(minVersion) {
617+
return nil
640618
}
641-
return match[1], nil
619+
return []string{WaitString, WaitSecondsValue}
642620
}
643621

644622
// goroutine to listen for D-Bus signals

0 commit comments

Comments
 (0)