Change:
<!-- Please only use this template for submitting reports about continuously failing tests or jobs in Kubernetes CI --Which jobs are failing: n/a Which test(s) are failing: "should resolve connection reset issue [Slow]" Since when has it been failing: it never worked Testgrid link: n/a Reason for failure: The image used for the test is using only IPv4 Anything else we need to know: We should: [x] refactor the code to support IPv6 [ ] ~consolidate the image in agnhost~ [x] configure an IPv6 job to test network https://k8s-,%20IPv6,%20master
/assign /sig-network
GitHub didn't allow me to assign the following users: Billy99. Note that only , repo collaborators and people who have commented on this issue/PR can be assigned. Additionally, issues/PRs can only have 10 assignees at the same time. For more information please see <detailsIn response to : /assign /sig-network Instructions for interacting with me using PR comments are available . If you have questions or suggestions related to my behavior, please file an issue against the repository. </details
/sig network
/triage unresolved Comment when the issue is assessed and confirmed. I am a bot run by vllry. ‍
/remove-triage unresolved
Those labels are not set on the issue: <detailsIn response to : /remove-triage unresolved Instructions for interacting with me using PR comments are available . If you have questions or suggestions related to my behavior, please file an issue against the repository. </details
/help wanted
/help wanted /good-first-issue
/remove-good-first-issue the agnhost promotion process is not something easy for new contributors
Hi, I would like to contribute to this.
good, thanks
sorry , I needed to fix it and I took over, thanks for stepping up /assign /remove help-wanted
OK.Yesterday I have refactor the code to support IPv6, but I understand wrong about consolidate the image in agnhost. I'm sorry for not being able to help.
no worries, it was trickier than I thought, thanks again for your help
Issues go stale after 90d of inactivity. Mark the issue as fresh with . Stale issues rot after an additional 30d of inactivity and eventually close. If this issue is safe to close now please do so with . Send feedback to sig-testing, kubernetes/test-infra and/or . /lifecycle stale
/remove-lifecycle stale

Discussion:
package network import ( <ins> "context" </ins> "fmt" "strings" "time"

e2epod "k8s.io/kubernetes/test/e2e/framework/pod" e2eservice "k8s.io/kubernetes/test/e2e/framework/service" e2eskipper "k8s.io/kubernetes/test/e2e/framework/skipper" <ins> imageutils "k8s.io/kubernetes/test/utils/image" </ins> ) const (

clientNodeInfo, serverNodeInfo nodeInfo ) <del> logContainsFn := func(text string) wait.ConditionFunc { </del> <ins> logContainsFn := func(text, podName string) wait.ConditionFunc { </ins> return func() (bool, error) { <del> logs, err := e2epod.GetPodLogs(cs, ns, podClient, podClient) </del> <ins> logs, err := e2epod.GetPodLogs(cs, ns, podName, podName) </ins> if err != nil { // Retry the error next time. return false, nil

// Check that the second pod keeps receiving traffic // UDP conntrack entries timeout is 30 sec by default ginkgo.By("checking client pod connected to the backend 2 on Node IP " + serverNodeInfo.nodeIP) <del> if err := wait.PollImmediate(5*time.Second, time.Minute, logContainsFn(podBackend2)); err != nil { </del> <ins> if err := wait.PollImmediate(5*time.Second, time.Minute, logContainsFn(podBackend2, podClient)); err != nil { </ins> logs, err = e2epod.GetPodLogs(cs, ns, podClient, podClient) framework.ExpectNoError(err) framework.Logf("Pod client logs: %s", logs)

// 30 seconds by default. // Based on the above check if the pod receives the traffic. ginkgo.By("checking client pod connected to the backend 1 on Node IP " + serverNodeInfo.nodeIP) <del> if err := wait.PollImmediate(5*time.Second, time.Minute, logContainsFn(podBackend1)); err != nil { </del> <ins> if err := wait.PollImmediate(5*time.Second, time.Minute, logContainsFn(podBackend1, podClient)); err != nil { </ins> logs, err = e2epod.GetPodLogs(cs, ns, podClient, podClient) framework.ExpectNoError(err) framework.Logf("Pod client logs: %s", logs)

// Check that the second pod keeps receiving traffic // UDP conntrack entries timeout is 30 sec by default ginkgo.By("checking client pod connected to the backend 2 on Node IP " + serverNodeInfo.nodeIP) <del> if err := wait.PollImmediate(5*time.Second, time.Minute, logContainsFn(podBackend2)); err != nil { </del> <ins> if err := wait.PollImmediate(5*time.Second, time.Minute, logContainsFn(podBackend2, podClient)); err != nil { </ins> logs, err = e2epod.GetPodLogs(cs, ns, podClient, podClient) framework.ExpectNoError(err) framework.Logf("Pod client logs: %s", logs) framework.Failf("Failed to connect to backend 2") } }) <ins> // Regression test for #74839, where: // Packets considered INVALID by conntrack are now dropped. In particular, this fixes // a problem where spurious retransmits in a long-running TCP connection to a service // IP could result in the connection being closed with the error "Connection reset by // peer" // xref: https://kubernetes.io/blog/2019/03/29/kube-proxy-subtleties-debugging-an-intermittent-connection-reset/ ginkgo.It("should drop INVALID conntrack entries", func() { serverLabel := map[string]string{ "app": "boom-server", } serverPod := &v1.Pod{ ObjectMeta: metav1.ObjectMeta{ Name:   "boom-server", Labels: serverLabel, }, Spec: v1.PodSpec{ NodeName: serverNodeInfo.name, Containers: []v1.Container{ { Name:  "boom-server", Image: imageutils.GetE2EImage(imageutils.RegressionIssue74839), Ports: []v1.ContainerPort{ { ContainerPort: 9000, // Default port exposed by boom-server }, }, Env: []v1.EnvVar{ { Name: "POD_IP", ValueFrom: &v1.EnvVarSource{ FieldRef: &v1.ObjectFieldSelector{ APIVersion: "v1", FieldPath:  "status.podIP", }, }, }, { Name: "POD_IPS", ValueFrom: &v1.EnvVarSource{ FieldRef: &v1.ObjectFieldSelector{ APIVersion: "v1", FieldPath:  "status.podIPs", }, }, }, }, }, }, }, } _, err := fr.ClientSet.CoreV1().Pods(fr.Namespace.Name).Create(context.TODO(), serverPod, metav1.CreateOptions{}) framework.ExpectNoError(err) err = e2epod.WaitForPodsRunningReady(fr.ClientSet, fr.Namespace.Name, 1, 0, framework.PodReadyBeforeTimeout, map[string]string{}) framework.ExpectNoError(err) ginkgo.By("Server pod created on node " + serverNodeInfo.name) svc := &v1.Service{ ObjectMeta: metav1.ObjectMeta{ Name: "boom-server", }, Spec: v1.ServiceSpec{ Selector: serverLabel, Ports: []v1.ServicePort{ { Protocol: v1.ProtocolTCP, Port:     9000, }, }, }, } _, err = fr.ClientSet.CoreV1().Services(fr.Namespace.Name).Create(context.TODO(), svc, metav1.CreateOptions{}) framework.ExpectNoError(err) ginkgo.By("Server service created") pod := &v1.Pod{ ObjectMeta: metav1.ObjectMeta{ Name: "startup-script", }, Spec: v1.PodSpec{ NodeName: clientNodeInfo.name, Containers: []v1.Container{ { Name:  "startup-script", Image: imageutils.GetE2EImage(imageutils.BusyBox), Command: []string{ "sh", "-c", "while true; do sleep 2; nc boom-server 9000& done", }, }, }, RestartPolicy: v1.RestartPolicyNever, }, } _, err = fr.ClientSet.CoreV1().Pods(fr.Namespace.Name).Create(context.TODO(), pod, metav1.CreateOptions{}) framework.ExpectNoError(err) ginkgo.By("Client pod created") // The client will open connections against the server // The server will inject invalid packets // if conntrack does not drop the invalid packets it will go through without NAT // so the client will receive an unexpected TCP connection and RST the connection // the server will log ERROR if that happens ginkgo.By("checking client pod does not RST the TCP connection because it receives and INVALID packet") if err := wait.PollImmediate(5*time.Second, time.Minute, logContainsFn("ERROR", "boom-server")); err == nil { logs, err := e2epod.GetPodLogs(cs, ns, "boom-server", "boom-server") framework.ExpectNoError(err) framework.Logf("boom-server pod logs: %s", logs) framework.Failf("Boom server pod received a RST from the client") } logs, err := e2epod.GetPodLogs(cs, ns, "boom-server", "boom-server") framework.ExpectNoError(err) if !strings.Contains(string(logs), "connection established") { framework.Failf("Boom server pod did not sent any bad packet to the client") } framework.Logf("boom-server pod logs: %s", logs) framework.Logf("boom-server did not receive any RST packet") }) </ins> })

package network import ( <del> "context" </del> "fmt" "math" "net"

netutils "k8s.io/utils/net" "github.com/onsi/ginkgo" <del> "github.com/onsi/gomega" </del> ) var kubeProxyE2eImage = imageutils.GetE2EImage(imageutils.Agnhost)

} }) <del> // Regression test for #74839, where: // Packets considered INVALID by conntrack are now dropped. In particular, this fixes // a problem where spurious retransmits in a long-running TCP connection to a service // IP could result in the connection being closed with the error "Connection reset by // peer" ginkgo.It("should resolve connection reset issue #74839 [Slow]", func() { serverLabel := map[string]string{ "app": "boom-server", } clientLabel := map[string]string{ "app": "client", } serverPod := &v1.Pod{ ObjectMeta: metav1.ObjectMeta{ Name:   "boom-server", Labels: serverLabel, }, Spec: v1.PodSpec{ Containers: []v1.Container{ { Name:  "boom-server", Image: imageutils.GetE2EImage(imageutils.RegressionIssue74839), Ports: []v1.ContainerPort{ { ContainerPort: 9000, // Default port exposed by boom-server }, }, }, }, Affinity: &v1.Affinity{ PodAntiAffinity: &v1.PodAntiAffinity{ RequiredDuringSchedulingIgnoredDuringExecution: []v1.PodAffinityTerm{ { LabelSelector: &metav1.LabelSelector{ MatchLabels: clientLabel, }, TopologyKey: "kubernetes.io/hostname", }, }, }, }, }, } _, err := fr.ClientSet.CoreV1().Pods(fr.Namespace.Name).Create(context.TODO(), serverPod, metav1.CreateOptions{}) framework.ExpectNoError(err) err = e2epod.WaitForPodsRunningReady(fr.ClientSet, fr.Namespace.Name, 1, 0, framework.PodReadyBeforeTimeout, map[string]string{}) framework.ExpectNoError(err) ginkgo.By("Server pod created") svc := &v1.Service{ ObjectMeta: metav1.ObjectMeta{ Name: "boom-server", }, Spec: v1.ServiceSpec{ Selector: serverLabel, Ports: []v1.ServicePort{ { Protocol: v1.ProtocolTCP, Port:     9000, }, }, }, } _, err = fr.ClientSet.CoreV1().Services(fr.Namespace.Name).Create(context.TODO(), svc, metav1.CreateOptions{}) framework.ExpectNoError(err) ginkgo.By("Server service created") pod := &v1.Pod{ ObjectMeta: metav1.ObjectMeta{ Name:   "startup-script", Labels: clientLabel, }, Spec: v1.PodSpec{ Containers: []v1.Container{ { Name:  "startup-script", Image: imageutils.GetE2EImage(imageutils.BusyBox), Command: []string{ "sh", "-c", "while true; do sleep 2; nc boom-server 9000& done", }, }, }, Affinity: &v1.Affinity{ PodAntiAffinity: &v1.PodAntiAffinity{ RequiredDuringSchedulingIgnoredDuringExecution: []v1.PodAffinityTerm{ { LabelSelector: &metav1.LabelSelector{ MatchLabels: serverLabel, }, TopologyKey: "kubernetes.io/hostname", }, }, }, }, RestartPolicy: v1.RestartPolicyNever, }, } _, err = fr.ClientSet.CoreV1().Pods(fr.Namespace.Name).Create(context.TODO(), pod, metav1.CreateOptions{}) framework.ExpectNoError(err) ginkgo.By("Client pod created") for i := 0; i < 20; i++ { time.Sleep(3 * time.Second) resultPod, err := fr.ClientSet.CoreV1().Pods(fr.Namespace.Name).Get(context.TODO(), serverPod.Name, metav1.GetOptions{}) framework.ExpectNoError(err) gomega.Expect(resultPod.Status.ContainerStatuses[0].LastTerminationState.Terminated).Should(gomega.BeNil()) } }) </del> })

configs[PrometheusDummyExporter] = Config{gcRegistry, "prometheus-dummy-exporter", "v0.1.0"} configs[PrometheusToSd] = Config{gcRegistry, "prometheus-to-sd", "v0.5.0"} configs[Redis] = Config{dockerLibraryRegistry, "redis", "5.0.5-alpine"} <del> configs[RegressionIssue74839] = Config{e2eRegistry, "regression-issue-74839-amd64", "1.0"} </del> <ins> configs[RegressionIssue74839] = Config{promoterE2eRegistry, "regression-issue-74839", "1.2"} </ins> configs[ResourceConsumer] = Config{e2eRegistry, "resource-consumer", "1.5"} configs[SdDummyExporter] = Config{gcRegistry, "sd-dummy-exporter", "v0.2.0"} configs[VolumeNFSServer] = Config{e2eVolumeRegistry, "nfs", "1.0"}