Skip to content

Commit f32648d

Browse files
committed
Attempt to deflake conntract e2e tests
1 parent 2f2923f commit f32648d

File tree

1 file changed

+57
-32
lines changed

1 file changed

+57
-32
lines changed

test/e2e/network/conntrack.go

Lines changed: 57 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import (
2525
v1 "k8s.io/api/core/v1"
2626
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2727
"k8s.io/apimachinery/pkg/util/intstr"
28+
"k8s.io/apimachinery/pkg/util/wait"
2829
clientset "k8s.io/client-go/kubernetes"
2930
"k8s.io/kubernetes/test/e2e/framework"
3031
e2enode "k8s.io/kubernetes/test/e2e/framework/node"
@@ -75,6 +76,20 @@ var _ = SIGDescribe("Conntrack", func() {
7576
clientNodeInfo, serverNodeInfo nodeInfo
7677
)
7778

79+
logContainsFn := func(text string) wait.ConditionFunc {
80+
return func() (bool, error) {
81+
logs, err := e2epod.GetPodLogs(cs, ns, podClient, podClient)
82+
if err != nil {
83+
// Retry the error next time.
84+
return false, nil
85+
}
86+
if !strings.Contains(string(logs), text) {
87+
return false, nil
88+
}
89+
return true, nil
90+
}
91+
}
92+
7893
ginkgo.BeforeEach(func() {
7994
cs = fr.ClientSet
8095
ns = fr.Namespace.Name
@@ -117,7 +132,7 @@ var _ = SIGDescribe("Conntrack", func() {
117132
ginkgo.By("creating a client pod for probing the service " + serviceName)
118133
clientPod := newAgnhostPod(podClient, "")
119134
clientPod.Spec.NodeName = clientNodeInfo.name
120-
cmd := fmt.Sprintf(`date; for i in $(seq 1 300); do echo "$(date) Try: ${i}"; echo hostname | nc -u -w 5 -p %d %s %d; echo; done`, srcPort, serverNodeInfo.nodeIP, udpService.Spec.Ports[0].NodePort)
135+
cmd := fmt.Sprintf(`date; for i in $(seq 1 3000); do echo "$(date) Try: ${i}"; echo hostname | nc -u -w 5 -p %d %s %d; echo; done`, srcPort, serverNodeInfo.nodeIP, udpService.Spec.Ports[0].NodePort)
121136
clientPod.Spec.Containers[0].Command = []string{"/bin/sh", "-c", cmd}
122137
clientPod.Spec.Containers[0].Name = podClient
123138
fr.PodClient().CreateSync(clientPod)
@@ -138,15 +153,17 @@ var _ = SIGDescribe("Conntrack", func() {
138153
err = validateEndpointsPorts(cs, ns, serviceName, portsByPodName{podBackend1: {80}})
139154
framework.ExpectNoError(err, "failed to validate endpoints for service %s in namespace: %s", serviceName, ns)
140155

141-
// Check that the pod receives the traffic
142-
// UDP conntrack entries timeout is 30 sec by default
156+
// Note that the fact that Endpoints object already exists, does NOT mean
157+
// that iptables (or whatever else is used) was already programmed.
158+
// Additionally take into account that UDP conntract entries timeout is
159+
// 30 seconds by default.
160+
// Based on the above check if the pod receives the traffic.
143161
ginkgo.By("checking client pod connected to the backend 1 on Node IP " + serverNodeInfo.nodeIP)
144-
time.Sleep(30 * time.Second)
145-
logs, err = e2epod.GetPodLogs(cs, ns, podClient, podClient)
146-
framework.ExpectNoError(err)
147-
framework.Logf("Pod client logs: %s", logs)
148-
if !strings.Contains(string(logs), podBackend1) {
149-
framework.Failf("Failed to connecto to backend 1")
162+
if err := wait.PollImmediate(5*time.Second, time.Minute, logContainsFn(podBackend1)); err != nil {
163+
logs, err = e2epod.GetPodLogs(cs, ns, podClient, podClient)
164+
framework.ExpectNoError(err)
165+
framework.Logf("Pod client logs: %s", logs)
166+
framework.Failf("Failed to connect to backend 1")
150167
}
151168

152169
// Create a second pod
@@ -160,21 +177,24 @@ var _ = SIGDescribe("Conntrack", func() {
160177
framework.Logf("Cleaning up %s pod", podBackend1)
161178
fr.PodClient().DeleteSync(podBackend1, metav1.DeleteOptions{}, framework.DefaultPodDeletionTimeout)
162179

180+
// Waiting for service to expose endpoint.
181+
err = validateEndpointsPorts(cs, ns, serviceName, portsByPodName{podBackend2: {80}})
182+
framework.ExpectNoError(err, "failed to validate endpoints for service %s in namespace: %s", serviceName, ns)
183+
163184
// Check that the second pod keeps receiving traffic
164185
// UDP conntrack entries timeout is 30 sec by default
165186
ginkgo.By("checking client pod connected to the backend 2 on Node IP " + serverNodeInfo.nodeIP)
166-
time.Sleep(30 * time.Second)
167-
logs, err = e2epod.GetPodLogs(cs, ns, podClient, podClient)
168-
framework.ExpectNoError(err)
169-
framework.Logf("Pod client logs: %s", logs)
170-
if !strings.Contains(string(logs), podBackend2) {
171-
framework.Failf("Failed to connecto to backend 2")
187+
if err := wait.PollImmediate(5*time.Second, time.Minute, logContainsFn(podBackend2)); err != nil {
188+
logs, err = e2epod.GetPodLogs(cs, ns, podClient, podClient)
189+
framework.ExpectNoError(err)
190+
framework.Logf("Pod client logs: %s", logs)
191+
framework.Failf("Failed to connect to backend 2")
172192
}
173193
})
174194

175195
ginkgo.It("should be able to preserve UDP traffic when server pod cycles for a ClusterIP service", func() {
176196

177-
// Create a NodePort service
197+
// Create a ClusterIP service
178198
udpJig := e2eservice.NewTestJig(cs, ns, serviceName)
179199
ginkgo.By("creating a UDP service " + serviceName + " with type=ClusterIP in " + ns)
180200
udpService, err := udpJig.CreateUDPService(func(svc *v1.Service) {
@@ -185,11 +205,11 @@ var _ = SIGDescribe("Conntrack", func() {
185205
})
186206
framework.ExpectNoError(err)
187207

188-
// Create a pod in one node to create the UDP traffic against the NodePort service every 5 seconds
208+
// Create a pod in one node to create the UDP traffic against the ClusterIP service every 5 seconds
189209
ginkgo.By("creating a client pod for probing the service " + serviceName)
190210
clientPod := newAgnhostPod(podClient, "")
191211
clientPod.Spec.NodeName = clientNodeInfo.name
192-
cmd := fmt.Sprintf(`date; for i in $(seq 1 300); do echo "$(date) Try: ${i}"; echo hostname | nc -u -w 5 -p %d %s %d; echo; done`, srcPort, udpService.Spec.ClusterIP, udpService.Spec.Ports[0].Port)
212+
cmd := fmt.Sprintf(`date; for i in $(seq 1 3000); do echo "$(date) Try: ${i}"; echo hostname | nc -u -w 5 -p %d %s %d; echo; done`, srcPort, udpService.Spec.ClusterIP, udpService.Spec.Ports[0].Port)
193213
clientPod.Spec.Containers[0].Command = []string{"/bin/sh", "-c", cmd}
194214
clientPod.Spec.Containers[0].Name = podClient
195215
fr.PodClient().CreateSync(clientPod)
@@ -210,15 +230,17 @@ var _ = SIGDescribe("Conntrack", func() {
210230
err = validateEndpointsPorts(cs, ns, serviceName, portsByPodName{podBackend1: {80}})
211231
framework.ExpectNoError(err, "failed to validate endpoints for service %s in namespace: %s", serviceName, ns)
212232

213-
// Check that the pod receives the traffic
214-
// UDP conntrack entries timeout is 30 sec by default
233+
// Note that the fact that Endpoints object already exists, does NOT mean
234+
// that iptables (or whatever else is used) was already programmed.
235+
// Additionally take into account that UDP conntract entries timeout is
236+
// 30 seconds by default.
237+
// Based on the above check if the pod receives the traffic.
215238
ginkgo.By("checking client pod connected to the backend 1 on Node IP " + serverNodeInfo.nodeIP)
216-
time.Sleep(30 * time.Second)
217-
logs, err = e2epod.GetPodLogs(cs, ns, podClient, podClient)
218-
framework.ExpectNoError(err)
219-
framework.Logf("Pod client logs: %s", logs)
220-
if !strings.Contains(string(logs), podBackend1) {
221-
framework.Failf("Failed to connecto to backend 1")
239+
if err := wait.PollImmediate(5*time.Second, time.Minute, logContainsFn(podBackend1)); err != nil {
240+
logs, err = e2epod.GetPodLogs(cs, ns, podClient, podClient)
241+
framework.ExpectNoError(err)
242+
framework.Logf("Pod client logs: %s", logs)
243+
framework.Failf("Failed to connect to backend 1")
222244
}
223245

224246
// Create a second pod
@@ -232,15 +254,18 @@ var _ = SIGDescribe("Conntrack", func() {
232254
framework.Logf("Cleaning up %s pod", podBackend1)
233255
fr.PodClient().DeleteSync(podBackend1, metav1.DeleteOptions{}, framework.DefaultPodDeletionTimeout)
234256

257+
// Waiting for service to expose endpoint.
258+
err = validateEndpointsPorts(cs, ns, serviceName, portsByPodName{podBackend2: {80}})
259+
framework.ExpectNoError(err, "failed to validate endpoints for service %s in namespace: %s", serviceName, ns)
260+
235261
// Check that the second pod keeps receiving traffic
236262
// UDP conntrack entries timeout is 30 sec by default
237263
ginkgo.By("checking client pod connected to the backend 2 on Node IP " + serverNodeInfo.nodeIP)
238-
time.Sleep(30 * time.Second)
239-
logs, err = e2epod.GetPodLogs(cs, ns, podClient, podClient)
240-
framework.ExpectNoError(err)
241-
framework.Logf("Pod client logs: %s", logs)
242-
if !strings.Contains(string(logs), podBackend2) {
243-
framework.Failf("Failed to connecto to backend 2")
264+
if err := wait.PollImmediate(5*time.Second, time.Minute, logContainsFn(podBackend2)); err != nil {
265+
logs, err = e2epod.GetPodLogs(cs, ns, podClient, podClient)
266+
framework.ExpectNoError(err)
267+
framework.Logf("Pod client logs: %s", logs)
268+
framework.Failf("Failed to connect to backend 2")
244269
}
245270
})
246271
})

0 commit comments

Comments
 (0)