Skip to content

Commit 2cbcd79

Browse files
committed
conntrack e2e test debug connections
dump conntrack udp information after each step
1 parent 9fb34ed commit 2cbcd79

File tree

1 file changed

+62
-9
lines changed

1 file changed

+62
-9
lines changed

test/e2e/network/conntrack.go

Lines changed: 62 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ var _ = SIGDescribe("Conntrack", func() {
120120
// TODO(#91236): Remove once the test is debugged and fixed.
121121
// dump conntrack table for debugging
122122
defer dumpConntrack(cs)
123+
defer dumpIptables(cs)
123124

124125
// Create a NodePort service
125126
udpJig := e2eservice.NewTestJig(cs, ns, serviceName)
@@ -139,24 +140,34 @@ var _ = SIGDescribe("Conntrack", func() {
139140
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)
140141
clientPod.Spec.Containers[0].Command = []string{"/bin/sh", "-c", cmd}
141142
clientPod.Spec.Containers[0].Name = podClient
142-
fr.PodClient().CreateSync(clientPod)
143+
pod := fr.PodClient().CreateSync(clientPod)
143144

144145
// Read the client pod logs
145146
logs, err := e2epod.GetPodLogs(cs, ns, podClient, podClient)
146147
framework.ExpectNoError(err)
147148
framework.Logf("Pod client logs: %s", logs)
148149

150+
framework.Logf("Pod client connection %s:%d --> %s:%d", pod.Status.PodIP, srcPort, serverNodeInfo.nodeIP, udpService.Spec.Ports[0].NodePort)
151+
// TODO(#91236): Remove once the test is debugged and fixed.
152+
// dump conntrack table for debugging
153+
dumpConntrack(cs)
154+
149155
// Add a backend pod to the service in the other node
150156
ginkgo.By("creating a backend pod " + podBackend1 + " for the service " + serviceName)
151157
serverPod1 := newAgnhostPod(podBackend1, "netexec", fmt.Sprintf("--udp-port=%d", 80))
152158
serverPod1.Labels = udpJig.Labels
153159
serverPod1.Spec.NodeName = serverNodeInfo.name
154-
fr.PodClient().CreateSync(serverPod1)
160+
pod1 := fr.PodClient().CreateSync(serverPod1)
155161

156162
// Waiting for service to expose endpoint.
157163
err = validateEndpointsPorts(cs, ns, serviceName, portsByPodName{podBackend1: {80}})
158164
framework.ExpectNoError(err, "failed to validate endpoints for service %s in namespace: %s", serviceName, ns)
159165

166+
framework.Logf("Pod client connection to backend1 after NAT %s:%d --> %s:80", pod.Status.PodIP, srcPort, pod1.Status.PodIP)
167+
// TODO(#91236): Remove once the test is debugged and fixed.
168+
// dump conntrack table for debugging
169+
dumpConntrack(cs)
170+
160171
// Note that the fact that Endpoints object already exists, does NOT mean
161172
// that iptables (or whatever else is used) was already programmed.
162173
// Additionally take into account that UDP conntract entries timeout is
@@ -175,7 +186,7 @@ var _ = SIGDescribe("Conntrack", func() {
175186
serverPod2 := newAgnhostPod(podBackend2, "netexec", fmt.Sprintf("--udp-port=%d", 80))
176187
serverPod2.Labels = udpJig.Labels
177188
serverPod2.Spec.NodeName = serverNodeInfo.name
178-
fr.PodClient().CreateSync(serverPod2)
189+
pod2 := fr.PodClient().CreateSync(serverPod2)
179190

180191
// and delete the first pod
181192
framework.Logf("Cleaning up %s pod", podBackend1)
@@ -185,6 +196,11 @@ var _ = SIGDescribe("Conntrack", func() {
185196
err = validateEndpointsPorts(cs, ns, serviceName, portsByPodName{podBackend2: {80}})
186197
framework.ExpectNoError(err, "failed to validate endpoints for service %s in namespace: %s", serviceName, ns)
187198

199+
framework.Logf("Pod client connection to backend2 after NAT %s:%d --> %s:80", pod.Status.PodIP, srcPort, pod2.Status.PodIP)
200+
// TODO(#91236): Remove once the test is debugged and fixed.
201+
// dump conntrack table for debugging
202+
dumpConntrack(cs)
203+
188204
// Check that the second pod keeps receiving traffic
189205
// UDP conntrack entries timeout is 30 sec by default
190206
ginkgo.By("checking client pod connected to the backend 2 on Node IP " + serverNodeInfo.nodeIP)
@@ -200,6 +216,7 @@ var _ = SIGDescribe("Conntrack", func() {
200216
// TODO(#91236): Remove once the test is debugged and fixed.
201217
// dump conntrack table for debugging
202218
defer dumpConntrack(cs)
219+
defer dumpIptables(cs)
203220

204221
// Create a ClusterIP service
205222
udpJig := e2eservice.NewTestJig(cs, ns, serviceName)
@@ -219,24 +236,32 @@ var _ = SIGDescribe("Conntrack", func() {
219236
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)
220237
clientPod.Spec.Containers[0].Command = []string{"/bin/sh", "-c", cmd}
221238
clientPod.Spec.Containers[0].Name = podClient
222-
fr.PodClient().CreateSync(clientPod)
223-
239+
pod := fr.PodClient().CreateSync(clientPod)
224240
// Read the client pod logs
225241
logs, err := e2epod.GetPodLogs(cs, ns, podClient, podClient)
226242
framework.ExpectNoError(err)
227243
framework.Logf("Pod client logs: %s", logs)
228244

245+
framework.Logf("Pod client connection %s:%d --> %s:%d", pod.Status.PodIP, srcPort, udpService.Spec.ClusterIP, udpService.Spec.Ports[0].Port)
246+
// TODO(#91236): Remove once the test is debugged and fixed.
247+
// dump conntrack table for debugging
248+
dumpConntrack(cs)
249+
229250
// Add a backend pod to the service in the other node
230251
ginkgo.By("creating a backend pod " + podBackend1 + " for the service " + serviceName)
231252
serverPod1 := newAgnhostPod(podBackend1, "netexec", fmt.Sprintf("--udp-port=%d", 80))
232253
serverPod1.Labels = udpJig.Labels
233254
serverPod1.Spec.NodeName = serverNodeInfo.name
234-
fr.PodClient().CreateSync(serverPod1)
235-
255+
pod1 := fr.PodClient().CreateSync(serverPod1)
236256
// Waiting for service to expose endpoint.
237257
err = validateEndpointsPorts(cs, ns, serviceName, portsByPodName{podBackend1: {80}})
238258
framework.ExpectNoError(err, "failed to validate endpoints for service %s in namespace: %s", serviceName, ns)
239259

260+
framework.Logf("Pod client connection to backend1 after NAT %s:%d --> %s:80", pod.Status.PodIP, srcPort, pod1.Status.PodIP)
261+
// TODO(#91236): Remove once the test is debugged and fixed.
262+
// dump conntrack table for debugging
263+
dumpConntrack(cs)
264+
240265
// Note that the fact that Endpoints object already exists, does NOT mean
241266
// that iptables (or whatever else is used) was already programmed.
242267
// Additionally take into account that UDP conntract entries timeout is
@@ -255,7 +280,7 @@ var _ = SIGDescribe("Conntrack", func() {
255280
serverPod2 := newAgnhostPod(podBackend2, "netexec", fmt.Sprintf("--udp-port=%d", 80))
256281
serverPod2.Labels = udpJig.Labels
257282
serverPod2.Spec.NodeName = serverNodeInfo.name
258-
fr.PodClient().CreateSync(serverPod2)
283+
pod2 := fr.PodClient().CreateSync(serverPod2)
259284

260285
// and delete the first pod
261286
framework.Logf("Cleaning up %s pod", podBackend1)
@@ -265,6 +290,11 @@ var _ = SIGDescribe("Conntrack", func() {
265290
err = validateEndpointsPorts(cs, ns, serviceName, portsByPodName{podBackend2: {80}})
266291
framework.ExpectNoError(err, "failed to validate endpoints for service %s in namespace: %s", serviceName, ns)
267292

293+
framework.Logf("Pod client connection to backend2 after NAT %s:%d --> %s:80", pod.Status.PodIP, srcPort, pod2.Status.PodIP)
294+
// TODO(#91236): Remove once the test is debugged and fixed.
295+
// dump conntrack table for debugging
296+
dumpConntrack(cs)
297+
268298
// Check that the second pod keeps receiving traffic
269299
// UDP conntrack entries timeout is 30 sec by default
270300
ginkgo.By("checking client pod connected to the backend 2 on Node IP " + serverNodeInfo.nodeIP)
@@ -285,7 +315,8 @@ func dumpConntrack(cs clientset.Interface) {
285315
framework.Logf("failed to list kube-proxy pods in namespace: %s", namespace)
286316
return
287317
}
288-
cmd := "conntrack -L"
318+
// don't print DNS related entries
319+
cmd := `conntrack -L -p udp | grep -v dport=53`
289320
for _, pod := range pods.Items {
290321
if strings.Contains(pod.Name, "kube-proxy") {
291322
stdout, err := framework.RunHostCmd(namespace, pod.Name, cmd)
@@ -297,3 +328,25 @@ func dumpConntrack(cs clientset.Interface) {
297328
}
298329
}
299330
}
331+
332+
func dumpIptables(cs clientset.Interface) {
333+
// Dump iptabes rules of each node for troubleshooting using the kube-proxy pods
334+
namespace := "kube-system"
335+
pods, err := cs.CoreV1().Pods(namespace).List(context.TODO(), metav1.ListOptions{})
336+
if err != nil || len(pods.Items) == 0 {
337+
framework.Logf("failed to list kube-proxy pods in namespace: %s", namespace)
338+
return
339+
}
340+
341+
cmd := "iptables-save"
342+
for _, pod := range pods.Items {
343+
if strings.Contains(pod.Name, "kube-proxy") {
344+
stdout, err := framework.RunHostCmd(namespace, pod.Name, cmd)
345+
if err != nil {
346+
framework.Logf("Failed to dump iptables rules of node %s: %v", pod.Spec.NodeName, err)
347+
continue
348+
}
349+
framework.Logf("iptables rules of node %s: %s", pod.Spec.NodeName, stdout)
350+
}
351+
}
352+
}

0 commit comments

Comments
 (0)