Skip to content

Commit f7c7e1f

Browse files
dimsclaude
andcommitted
test: Read /proc/net/nf_conntrack instead of using conntrack binary
The distroless-iptables image no longer includes the conntrack binary as of v0.8.7 (removed in kubernetes/release#4223 since kube-proxy no longer needs it after kubernetes#126847). Update the KubeProxy CLOSE_WAIT timeout test to read /proc/net/nf_conntrack directly instead of using the conntrack command. The file contains the same connection tracking data and is accessible from the privileged host-network pod. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> Signed-off-by: Davanum Srinivas <davanum@gmail.com>
1 parent b78bcfc commit f7c7e1f

File tree

1 file changed

+12
-10
lines changed

1 file changed

+12
-10
lines changed

test/e2e/network/kube_proxy.go

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -218,11 +218,12 @@ var _ = common.SIGDescribe("KubeProxy", func() {
218218
if netutils.IsIPv6String(ip) {
219219
ipFamily = "ipv6"
220220
}
221-
// Obtain the corresponding conntrack entry on the host checking
222-
// the nf_conntrack file from the pod e2e-net-exec.
221+
// Obtain the corresponding conntrack entry on the host by reading
222+
// /proc/net/nf_conntrack directly from the pod e2e-net-exec.
223+
// This avoids dependency on the conntrack binary.
223224
// It retries in a loop if the entry is not found.
224-
cmd := fmt.Sprintf("conntrack -L -f %s -d %v "+
225-
"| grep -m 1 'CLOSE_WAIT.*dport=%v' ",
225+
cmd := fmt.Sprintf("cat /proc/net/nf_conntrack "+
226+
"| grep -m 1 -E '%s.*CLOSE_WAIT.*dst=%v.*dport=%v'",
226227
ipFamily, ip, testDaemonTCPPort)
227228
if err := wait.PollImmediate(2*time.Second, epsilonSeconds*time.Second, func() (bool, error) {
228229
result, err := e2epodoutput.RunHostCmd(fr.Namespace.Name, "e2e-net-exec", cmd)
@@ -232,24 +233,25 @@ var _ = common.SIGDescribe("KubeProxy", func() {
232233
return false, nil
233234
}
234235
framework.Logf("conntrack entry for node %v and port %v: %v", serverNodeInfo.nodeIP, testDaemonTCPPort, result)
235-
// Timeout in seconds is available as the third column of the matched entry
236+
// /proc/net/nf_conntrack format: ipv4 2 tcp 6 <timeout> <state> src=... dst=...
237+
// Timeout in seconds is available as the fifth column (index 4)
236238
line := strings.Fields(result)
237-
if len(line) < 3 {
239+
if len(line) < 5 {
238240
return false, fmt.Errorf("conntrack entry does not have a timeout field: %v", line)
239241
}
240-
timeoutSeconds, err := strconv.Atoi(line[2])
242+
timeoutSeconds, err := strconv.Atoi(line[4])
241243
if err != nil {
242-
return false, fmt.Errorf("failed to convert matched timeout %s to integer: %w", line[2], err)
244+
return false, fmt.Errorf("failed to convert matched timeout %s to integer: %w", line[4], err)
243245
}
244246
if math.Abs(float64(timeoutSeconds-expectedTimeoutSeconds)) < epsilonSeconds {
245247
return true, nil
246248
}
247249
return false, fmt.Errorf("wrong TCP CLOSE_WAIT timeout: %v expected: %v", timeoutSeconds, expectedTimeoutSeconds)
248250
}); err != nil {
249251
// Dump all conntrack entries for debugging
250-
result, err2 := e2epodoutput.RunHostCmd(fr.Namespace.Name, "e2e-net-exec", "conntrack -L")
252+
result, err2 := e2epodoutput.RunHostCmd(fr.Namespace.Name, "e2e-net-exec", "cat /proc/net/nf_conntrack")
251253
if err2 != nil {
252-
framework.Logf("failed to obtain conntrack entry: %v %v", result, err2)
254+
framework.Logf("failed to read /proc/net/nf_conntrack: %v %v", result, err2)
253255
}
254256
framework.Logf("conntrack entries for node %v: %v", serverNodeInfo.nodeIP, result)
255257
framework.Failf("no valid conntrack entry for port %d on node %s: %v", testDaemonTCPPort, serverNodeInfo.nodeIP, err)

0 commit comments

Comments
 (0)