Skip to content

Commit 7937aa6

Browse files
authored
Merge pull request kubernetes#90687 from aojea/connt
use conntrack instead of the /proc file for the e2e test TCP CLOSE_WAIT
2 parents 3c159bb + 6f9c0f9 commit 7937aa6

File tree

3 files changed

+24
-62
lines changed

3 files changed

+24
-62
lines changed

build/dependencies.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,8 @@ dependencies:
116116
match: debian_iptables_version=
117117
- path: build/workspace.bzl
118118
match: tag =
119+
- path: test/utils/image/manifest.go
120+
match: configs\[DebianIptables\] = Config{buildImageRegistry, "debian-iptables", "v\d+\.\d+.\d+"}
119121

120122
- name: "k8s.gcr.io/go-runner"
121123
version: 0.1.1

test/e2e/network/kube_proxy.go

Lines changed: 16 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ package network
1818

1919
import (
2020
"context"
21-
"encoding/hex"
2221
"fmt"
2322
"math"
2423
"net"
@@ -35,6 +34,7 @@ import (
3534
e2epod "k8s.io/kubernetes/test/e2e/framework/pod"
3635
e2eskipper "k8s.io/kubernetes/test/e2e/framework/skipper"
3736
imageutils "k8s.io/kubernetes/test/utils/image"
37+
netutils "k8s.io/utils/net"
3838

3939
"github.com/onsi/ginkgo"
4040
"github.com/onsi/gomega"
@@ -81,8 +81,6 @@ var _ = SIGDescribe("Network", func() {
8181
}
8282

8383
// Create a pod to check the conntrack entries on the host node
84-
// It mounts the host /proc/net folder to be able to access
85-
// the nf_conntrack file with the host conntrack entries
8684
privileged := true
8785

8886
hostExecPod := &v1.Pod{
@@ -97,43 +95,17 @@ var _ = SIGDescribe("Network", func() {
9795
Containers: []v1.Container{
9896
{
9997
Name: "e2e-net-exec",
100-
Image: kubeProxyE2eImage,
98+
Image: imageutils.GetE2EImage(imageutils.DebianIptables),
10199
ImagePullPolicy: v1.PullIfNotPresent,
102-
Args: []string{"pause"},
103-
VolumeMounts: []v1.VolumeMount{
104-
{
105-
Name: "proc-net",
106-
MountPath: "/rootfs/proc/net",
107-
ReadOnly: true,
108-
},
109-
},
100+
Command: []string{"sleep", "600"},
110101
SecurityContext: &v1.SecurityContext{
111102
Privileged: &privileged,
112103
},
113104
},
114105
},
115-
Volumes: []v1.Volume{
116-
{
117-
Name: "proc-net",
118-
VolumeSource: v1.VolumeSource{
119-
HostPath: &v1.HostPathVolumeSource{
120-
Path: "/proc/net",
121-
},
122-
},
123-
},
124-
},
125106
},
126107
}
127108
fr.PodClient().CreateSync(hostExecPod)
128-
defer fr.PodClient().DeleteSync(hostExecPod.Name, metav1.DeleteOptions{}, framework.DefaultPodDeletionTimeout)
129-
130-
// Some distributions (Ubuntu 16.04 etc.) don't support the proc file.
131-
_, err = framework.RunHostCmd(fr.Namespace.Name, "e2e-net-exec",
132-
"ls /rootfs/proc/net/nf_conntrack")
133-
if err != nil && strings.Contains(err.Error(), "No such file or directory") {
134-
e2eskipper.Skipf("The node %s does not support /proc/net/nf_conntrack", clientNodeInfo.name)
135-
}
136-
framework.ExpectNoError(err)
137109

138110
// Create the client and server pods
139111
clientPodSpec := &v1.Pod{
@@ -202,7 +174,6 @@ var _ = SIGDescribe("Network", func() {
202174
serverNodeInfo.nodeIP,
203175
kubeProxyE2eImage))
204176
fr.PodClient().CreateSync(serverPodSpec)
205-
defer fr.PodClient().DeleteSync(serverPodSpec.Name, metav1.DeleteOptions{}, framework.DefaultPodDeletionTimeout)
206177

207178
// The server should be listening before spawning the client pod
208179
if readyErr := e2epod.WaitForPodsReady(fr.ClientSet, fr.Namespace.Name, serverPodSpec.Name, 0); readyErr != nil {
@@ -215,22 +186,25 @@ var _ = SIGDescribe("Network", func() {
215186
clientNodeInfo.nodeIP,
216187
kubeProxyE2eImage))
217188
fr.PodClient().CreateSync(clientPodSpec)
218-
defer fr.PodClient().DeleteSync(clientPodSpec.Name, metav1.DeleteOptions{}, framework.DefaultPodDeletionTimeout)
219189

220-
ginkgo.By("Checking /proc/net/nf_conntrack for the timeout")
190+
ginkgo.By("Checking conntrack entries for the timeout")
221191
// These must be synchronized from the default values set in
222192
// pkg/apis/../defaults.go ConntrackTCPCloseWaitTimeout. The
223193
// current defaults are hidden in the initialization code.
224194
const epsilonSeconds = 60
225195
const expectedTimeoutSeconds = 60 * 60
226196
// the conntrack file uses the IPv6 expanded format
227-
ip := fullIPv6(net.ParseIP(serverNodeInfo.nodeIP))
197+
ip := serverNodeInfo.nodeIP
198+
ipFamily := "ipv4"
199+
if netutils.IsIPv6String(ip) {
200+
ipFamily = "ipv6"
201+
}
228202
// Obtain the corresponding conntrack entry on the host checking
229203
// the nf_conntrack file from the pod e2e-net-exec.
230204
// It retries in a loop if the entry is not found.
231-
cmd := fmt.Sprintf("cat /rootfs/proc/net/nf_conntrack "+
232-
"| grep -m 1 'CLOSE_WAIT.*dst=%v.*dport=%v' ",
233-
ip, testDaemonTCPPort)
205+
cmd := fmt.Sprintf("conntrack -L -f %s -d %v"+
206+
"| grep -m 1 'CLOSE_WAIT.*dport=%v' ",
207+
ipFamily, ip, testDaemonTCPPort)
234208
if err := wait.PollImmediate(1*time.Second, postFinTimeoutSeconds, func() (bool, error) {
235209
result, err := framework.RunHostCmd(fr.Namespace.Name, "e2e-net-exec", cmd)
236210
// retry if we can't obtain the conntrack entry
@@ -239,15 +213,14 @@ var _ = SIGDescribe("Network", func() {
239213
return false, nil
240214
}
241215
framework.Logf("conntrack entry for node %v and port %v: %v", serverNodeInfo.nodeIP, testDaemonTCPPort, result)
242-
// Timeout in seconds is available as the fifth column of
243-
// the matched entry in /proc/net/nf_conntrack.
216+
// Timeout in seconds is available as the third column of the matched entry
244217
line := strings.Fields(result)
245-
if len(line) < 5 {
218+
if len(line) < 3 {
246219
return false, fmt.Errorf("conntrack entry does not have a timeout field: %v", line)
247220
}
248-
timeoutSeconds, err := strconv.Atoi(line[4])
221+
timeoutSeconds, err := strconv.Atoi(line[2])
249222
if err != nil {
250-
return false, fmt.Errorf("failed to convert matched timeout %s to integer: %v", line[4], err)
223+
return false, fmt.Errorf("failed to convert matched timeout %s to integer: %v", line[2], err)
251224
}
252225
if math.Abs(float64(timeoutSeconds-expectedTimeoutSeconds)) < epsilonSeconds {
253226
return true, nil
@@ -372,22 +345,3 @@ var _ = SIGDescribe("Network", func() {
372345
}
373346
})
374347
})
375-
376-
// fullIPv6 returns a string with the IP representation
377-
// if IPv6 it returns the expanded address format
378-
// credit https://stackoverflow.com/a/52003106/4532704
379-
func fullIPv6(ip net.IP) string {
380-
if ip.To4() == nil {
381-
dst := make([]byte, hex.EncodedLen(len(ip)))
382-
_ = hex.Encode(dst, ip)
383-
return string(dst[0:4]) + ":" +
384-
string(dst[4:8]) + ":" +
385-
string(dst[8:12]) + ":" +
386-
string(dst[12:16]) + ":" +
387-
string(dst[16:20]) + ":" +
388-
string(dst[20:24]) + ":" +
389-
string(dst[24:28]) + ":" +
390-
string(dst[28:])
391-
}
392-
return ip.String()
393-
}

test/utils/image/manifest.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ type RegistryList struct {
3232
DockerGluster string `yaml:"dockerGluster"`
3333
E2eRegistry string `yaml:"e2eRegistry"`
3434
PromoterE2eRegistry string `yaml:"promoterE2eRegistry"`
35+
BuildImageRegistry string `yaml:"buildImageRegistry"`
3536
InvalidRegistry string `yaml:"invalidRegistry"`
3637
GcRegistry string `yaml:"gcRegistry"`
3738
GcrReleaseRegistry string `yaml:"gcrReleaseRegistry"`
@@ -73,6 +74,7 @@ func initReg() RegistryList {
7374
E2eRegistry: "gcr.io/kubernetes-e2e-test-images",
7475
// TODO: After the domain flip, this should instead be k8s.gcr.io/k8s-artifacts-prod/e2e-test-images
7576
PromoterE2eRegistry: "us.gcr.io/k8s-artifacts-prod/e2e-test-images",
77+
BuildImageRegistry: "us.gcr.io/k8s-artifacts-prod/build-image",
7678
InvalidRegistry: "invalid.com/invalid",
7779
GcRegistry: "k8s.gcr.io",
7880
GcrReleaseRegistry: "gcr.io/gke-release",
@@ -106,6 +108,7 @@ var (
106108
dockerGluster = registry.DockerGluster
107109
e2eRegistry = registry.E2eRegistry
108110
promoterE2eRegistry = registry.PromoterE2eRegistry
111+
buildImageRegistry = registry.BuildImageRegistry
109112
gcAuthenticatedRegistry = registry.GcAuthenticatedRegistry
110113
gcRegistry = registry.GcRegistry
111114
gcrReleaseRegistry = registry.GcrReleaseRegistry
@@ -141,6 +144,8 @@ const (
141144
CudaVectorAdd
142145
// CudaVectorAdd2 image
143146
CudaVectorAdd2
147+
// DebianIptables Image
148+
DebianIptables
144149
// EchoServer image
145150
EchoServer
146151
// Etcd image
@@ -210,6 +215,7 @@ func initImageConfigs() map[int]Config {
210215
configs[CheckMetadataConcealment] = Config{e2eRegistry, "metadata-concealment", "1.2"}
211216
configs[CudaVectorAdd] = Config{e2eRegistry, "cuda-vector-add", "1.0"}
212217
configs[CudaVectorAdd2] = Config{e2eRegistry, "cuda-vector-add", "2.0"}
218+
configs[DebianIptables] = Config{buildImageRegistry, "debian-iptables", "v12.1.0"}
213219
configs[EchoServer] = Config{e2eRegistry, "echoserver", "2.2"}
214220
configs[Etcd] = Config{gcRegistry, "etcd", "3.4.7"}
215221
configs[GlusterDynamicProvisioner] = Config{dockerGluster, "glusterdynamic-provisioner", "v1.0"}

0 commit comments

Comments
 (0)