@@ -26,11 +26,11 @@ import (
26
26
27
27
v1 "k8s.io/api/core/v1"
28
28
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
29
- "k8s.io/apimachinery/pkg/util/wait"
30
29
31
30
"k8s.io/kubernetes/test/e2e/framework"
32
31
e2enode "k8s.io/kubernetes/test/e2e/framework/node"
33
32
e2epod "k8s.io/kubernetes/test/e2e/framework/pod"
33
+ e2essh "k8s.io/kubernetes/test/e2e/framework/ssh"
34
34
"k8s.io/kubernetes/test/images/agnhost/net/nat"
35
35
imageutils "k8s.io/kubernetes/test/utils/image"
36
36
@@ -42,10 +42,10 @@ var kubeProxyE2eImage = imageutils.GetE2EImage(imageutils.Agnhost)
42
42
43
43
var _ = SIGDescribe ("Network" , func () {
44
44
const (
45
- testDaemonHTTPPort = 11301
46
- testDaemonTCPPort = 11302
47
- deadlineTimeoutSeconds = 10
48
- postFinTimeoutSeconds = 30
45
+ testDaemonHTTPPort = 11301
46
+ testDaemonTCPPort = 11302
47
+ timeoutSeconds = 10
48
+ postFinTimeoutSeconds = 5
49
49
)
50
50
51
51
fr := framework .NewDefaultFramework ("network" )
@@ -81,63 +81,16 @@ var _ = SIGDescribe("Network", func() {
81
81
82
82
zero := int64 (0 )
83
83
84
- // Create a pod to check the conntrack entries on the host node
85
- // It mounts the host /proc/net folder to be able to access
86
- // the nf_conntrack file with the host conntrack entries
87
- privileged := true
88
-
89
- hostExecPod := & v1.Pod {
90
- ObjectMeta : metav1.ObjectMeta {
91
- Name : "e2e-net-exec" ,
92
- Namespace : fr .Namespace .Name ,
93
- Labels : map [string ]string {"app" : "e2e-net-exec" },
94
- },
95
- Spec : v1.PodSpec {
96
- HostNetwork : true ,
97
- NodeName : clientNodeInfo .name ,
98
- Containers : []v1.Container {
99
- {
100
- Name : "e2e-net-exec" ,
101
- Image : kubeProxyE2eImage ,
102
- ImagePullPolicy : "Always" ,
103
- Args : []string {"pause" },
104
- VolumeMounts : []v1.VolumeMount {
105
- {
106
- Name : "proc-net" ,
107
- MountPath : "/rootfs/proc/net" ,
108
- ReadOnly : true ,
109
- },
110
- },
111
- SecurityContext : & v1.SecurityContext {
112
- Privileged : & privileged ,
113
- },
114
- },
115
- },
116
- Volumes : []v1.Volume {
117
- {
118
- Name : "proc-net" ,
119
- VolumeSource : v1.VolumeSource {
120
- HostPath : & v1.HostPathVolumeSource {
121
- Path : "/proc/net" ,
122
- },
123
- },
124
- },
125
- },
126
- TerminationGracePeriodSeconds : & zero ,
127
- },
128
- }
129
- fr .PodClient ().CreateSync (hostExecPod )
130
-
131
84
// Some distributions (Ubuntu 16.04 etc.) don't support the proc file.
132
- _ , err = framework .RunHostCmd (fr .Namespace .Name , "e2e-net-exec" ,
133
- "ls /rootfs/proc/net/nf_conntrack" )
85
+ _ , err = e2essh .IssueSSHCommandWithResult (
86
+ "ls /proc/net/nf_conntrack" ,
87
+ framework .TestContext .Provider ,
88
+ clientNodeInfo .node )
134
89
if err != nil && strings .Contains (err .Error (), "No such file or directory" ) {
135
- framework .Skipf ("The node %s does not support /proc/net/nf_conntrack" ,
136
- clientNodeInfo .name )
90
+ framework .Skipf ("The node %s does not support /proc/net/nf_conntrack" , clientNodeInfo .name )
137
91
}
138
92
framework .ExpectNoError (err )
139
93
140
- // Create the client and server pods
141
94
clientPodSpec := & v1.Pod {
142
95
ObjectMeta : metav1.ObjectMeta {
143
96
Name : "e2e-net-client" ,
@@ -152,7 +105,7 @@ var _ = SIGDescribe("Network", func() {
152
105
Image : kubeProxyE2eImage ,
153
106
ImagePullPolicy : "Always" ,
154
107
Args : []string {
155
- "net" , "--serve" , fmt .Sprintf (":%d" , testDaemonHTTPPort ),
108
+ "net" , "--serve" , fmt .Sprintf ("0.0.0.0 :%d" , testDaemonHTTPPort ),
156
109
},
157
110
},
158
111
},
@@ -177,7 +130,7 @@ var _ = SIGDescribe("Network", func() {
177
130
"net" ,
178
131
"--runner" , "nat-closewait-server" ,
179
132
"--options" ,
180
- fmt .Sprintf (`{"LocalAddr":":%v", "PostFinTimeoutSeconds ":%v}` ,
133
+ fmt .Sprintf (`{"LocalAddr":"0.0.0.0 :%v", "PostFindTimeoutSeconds ":%v}` ,
181
134
testDaemonTCPPort ,
182
135
postFinTimeoutSeconds ),
183
136
},
@@ -213,8 +166,8 @@ var _ = SIGDescribe("Network", func() {
213
166
options := nat.CloseWaitClientOptions {
214
167
RemoteAddr : fmt .Sprintf ("%v:%v" ,
215
168
serverNodeInfo .nodeIP , testDaemonTCPPort ),
216
- TimeoutSeconds : deadlineTimeoutSeconds ,
217
- PostFinTimeoutSeconds : postFinTimeoutSeconds ,
169
+ TimeoutSeconds : timeoutSeconds ,
170
+ PostFinTimeoutSeconds : 0 ,
218
171
LeakConnection : true ,
219
172
}
220
173
@@ -226,52 +179,47 @@ var _ = SIGDescribe("Network", func() {
226
179
`'%v' 2>/dev/null` ,
227
180
testDaemonHTTPPort ,
228
181
string (jsonBytes ))
229
- // Run the closewait command in a subroutine so it keeps waiting during postFinTimeoutSeconds
230
- // otherwise the pod is deleted and the connection is closed loosing the conntrack entry
231
- go func () {
232
- framework .RunHostCmdOrDie (fr .Namespace .Name , "e2e-net-client" , cmd )
233
- }()
182
+ framework .RunHostCmdOrDie (fr .Namespace .Name , "e2e-net-client" , cmd )
234
183
235
184
<- time .After (time .Duration (1 ) * time .Second )
236
185
237
186
ginkgo .By ("Checking /proc/net/nf_conntrack for the timeout" )
187
+ // If test flakes occur here, then this check should be performed
188
+ // in a loop as there may be a race with the client connecting.
189
+ e2essh .IssueSSHCommandWithResult (
190
+ fmt .Sprintf ("sudo cat /proc/net/nf_conntrack | grep 'dport=%v'" ,
191
+ testDaemonTCPPort ),
192
+ framework .TestContext .Provider ,
193
+ clientNodeInfo .node )
194
+
195
+ // Timeout in seconds is available as the fifth column from
196
+ // /proc/net/nf_conntrack.
197
+ result , err := e2essh .IssueSSHCommandWithResult (
198
+ fmt .Sprintf (
199
+ "sudo cat /proc/net/nf_conntrack " +
200
+ "| grep 'CLOSE_WAIT.*dst=%v.*dport=%v' " +
201
+ "| tail -n 1" +
202
+ "| awk '{print $5}' " ,
203
+ serverNodeInfo .nodeIP ,
204
+ testDaemonTCPPort ),
205
+ framework .TestContext .Provider ,
206
+ clientNodeInfo .node )
207
+ framework .ExpectNoError (err )
208
+
209
+ timeoutSeconds , err := strconv .Atoi (strings .TrimSpace (result .Stdout ))
210
+ framework .ExpectNoError (err )
211
+
238
212
// These must be synchronized from the default values set in
239
213
// pkg/apis/../defaults.go ConntrackTCPCloseWaitTimeout. The
240
214
// current defaults are hidden in the initialization code.
241
215
const epsilonSeconds = 60
242
216
const expectedTimeoutSeconds = 60 * 60
243
- // Obtain the corresponding conntrack entry on the host checking
244
- // the nf_conntrack file from the pod e2e-net-exec.
245
- // It retries in a loop if the entry is not found.
246
- cmd = fmt .Sprintf ("cat /rootfs/proc/net/nf_conntrack " +
247
- "| grep -m 1 'CLOSE_WAIT.*dst=%v.*dport=%v' " ,
248
- serverNodeInfo .nodeIP ,
249
- testDaemonTCPPort )
250
- if err := wait .PollImmediate (5 * time .Second , 30 * time .Second , func () (bool , error ) {
251
- result , err := framework .RunHostCmd (fr .Namespace .Name , "e2e-net-exec" , cmd )
252
- // retry if we can't obtain the conntrack entry
253
- if err != nil {
254
- framework .Logf ("failed to obtain conntrack entry: %v %v" , result , err )
255
- return false , nil
256
- }
257
- framework .Logf ("conntrack entry for node %v and port %v: %v" , serverNodeInfo .nodeIP , testDaemonTCPPort , result )
258
- // Timeout in seconds is available as the fifth column of
259
- // the matched entry in /proc/net/nf_conntrack.
260
- line := strings .Fields (result )
261
- if len (line ) < 5 {
262
- return false , fmt .Errorf ("conntrack entry does not have a timeout field: %v" , line )
263
- }
264
- timeoutSeconds , err := strconv .Atoi (line [4 ])
265
- if err != nil {
266
- return false , fmt .Errorf ("failed to convert matched timeout %s to integer: %v" , line [4 ], err )
267
- }
268
- if math .Abs (float64 (timeoutSeconds - expectedTimeoutSeconds )) < epsilonSeconds {
269
- return true , nil
270
- }
271
- return false , fmt .Errorf ("wrong TCP CLOSE_WAIT timeout: %v expected: %v" , timeoutSeconds , expectedTimeoutSeconds )
272
- }); err != nil {
273
- framework .Failf ("no conntrack entry for port %d on node %s" , testDaemonTCPPort , serverNodeInfo .nodeIP )
274
- }
217
+
218
+ framework .Logf ("conntrack entry timeout was: %v, expected: %v" ,
219
+ timeoutSeconds , expectedTimeoutSeconds )
220
+
221
+ gomega .Expect (math .Abs (float64 (timeoutSeconds - expectedTimeoutSeconds ))).Should (
222
+ gomega .BeNumerically ("<" , (epsilonSeconds )))
275
223
})
276
224
277
225
// Regression test for #74839, where:
0 commit comments