Skip to content

Commit

Permalink
EIP e2e: check EIP when pods from different ns connect to same net
Browse files Browse the repository at this point in the history
Signed-off-by: Martin Kennelly <mkennell@redhat.com>
  • Loading branch information
martinkennelly committed Dec 9, 2024
1 parent 0e0b6ac commit 1e550f4
Showing 1 changed file with 116 additions and 0 deletions.
116 changes: 116 additions & 0 deletions test/e2e/egressip.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (
"k8s.io/kubernetes/test/e2e/framework"
e2ekubectl "k8s.io/kubernetes/test/e2e/framework/kubectl"
e2enode "k8s.io/kubernetes/test/e2e/framework/node"
"k8s.io/kubernetes/test/e2e/framework/pod"
e2epodoutput "k8s.io/kubernetes/test/e2e/framework/pod/output"
utilnet "k8s.io/utils/net"
)
Expand Down Expand Up @@ -2712,6 +2713,121 @@ spec:
"and verify the expected IP, failed for EgressIP %s: %v", egressIPName, err)
})

// two pods attached to different namespaces but the same role primary user defined network
// One pod is deleted and ensure connectivity for the other pod is ok
// The previous pod namespace is deleted and again, ensure connectivity for the other pod is ok
ginkgo.It("[OVN network] multiple namespaces sharing a primary networks", func() {
if !isNetworkSegmentationEnabled() || netConfigParams.role != "primary" {
ginkgo.Skip("Network segmentation is disabled or network isn't a role primary UDN")
}
ginkgo.By(fmt.Sprintf("Building another namespace api object, basename %s", f.BaseName))
otherNetworkNamespace, err := f.CreateNamespace(context.Background(), f.BaseName, map[string]string{
"e2e-framework": f.BaseName,
})
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())

ginkgo.By("namespace is connected to UDN, create a namespace attached to this primary as a layer3 UDN")
nadClient, err := nadclient.NewForConfig(f.ClientConfig())
gomega.Expect(err).NotTo(gomega.HaveOccurred())
netConfig := newNetworkAttachmentConfig(netConfigParams)
netConfig.namespace = otherNetworkNamespace.Name
_, err = nadClient.NetworkAttachmentDefinitions(otherNetworkNamespace.Name).Create(
context.Background(),
generateNAD(netConfig),
metav1.CreateOptions{},
)
gomega.Expect(err).NotTo(gomega.HaveOccurred())
egressNodeAvailabilityHandler := egressNodeAvailabilityHandlerViaLabel{f}
ginkgo.By("1. Set one node as available for egress")
egressNodeAvailabilityHandler.Enable(egress1Node.name)
defer egressNodeAvailabilityHandler.Restore(egress1Node.name)

selectedByEIPLabels := map[string]string{
"wants": "egress",
}
pod1Namespace := f.Namespace
pod1Namespace.Labels = selectedByEIPLabels
updateNamespace(f, pod1Namespace)
pod2OtherNetworkNamespace := otherNetworkNamespace.Name
otherNetworkNamespace.Labels = selectedByEIPLabels
updateNamespace(f, otherNetworkNamespace)

ginkgo.By("3. Create an EgressIP object with one egress IP defined")
// Assign the egress IP without conflicting with any node IP,
// the kind subnet is /16 or /64 so the following should be fine.
egressNodeIP := net.ParseIP(egress1Node.nodeIP)
egressIP1 := dupIP(egressNodeIP)
egressIP1[len(egressIP1)-2]++

var egressIPConfig = fmt.Sprintf(`apiVersion: k8s.ovn.org/v1
kind: EgressIP
metadata:
name: ` + egressIPName + `
spec:
egressIPs:
- ` + egressIP1.String() + `
podSelector:
matchLabels:
wants: egress
namespaceSelector:
matchLabels:
wants: egress
`)
if err := os.WriteFile(egressIPYaml, []byte(egressIPConfig), 0644); err != nil {
framework.Failf("Unable to write CRD config to disk: %v", err)
}
defer func() {
if err := os.Remove(egressIPYaml); err != nil {
framework.Logf("Unable to remove the CRD config from disk: %v", err)
}
}()

framework.Logf("Create the EgressIP configuration")
e2ekubectl.RunKubectlOrDie("default", "create", "-f", egressIPYaml)

ginkgo.By("4. Check that the status is of length one and that it is assigned to egress1Node")
statuses := verifyEgressIPStatusLengthEquals(1, nil)
if statuses[0].Node != egress1Node.name {
framework.Failf("Step 4. Check that the status is of length one and that it is assigned to egress1Node, failed")
}

ginkgo.By("5. Create two pods matching the EgressIP with each connected to the same network")
pod1, err := createGenericPodWithLabel(f, pod1Name, pod1Node.name, f.Namespace.Name, command, podEgressLabel)
framework.ExpectNoError(err, "5. Create one pod matching the EgressIP: running on egress1Node, failed: %v", err)
pod2, err := createGenericPodWithLabel(f, pod2Name, pod2Node.name, otherNetworkNamespace.Name, command, podEgressLabel)
framework.ExpectNoError(err, "5. Create one pod matching the EgressIP: running on egress2Node, failed: %v", err)

gomega.Expect(pod.WaitForPodRunningInNamespace(context.TODO(), f.ClientSet, pod1)).Should(gomega.Succeed())
gomega.Expect(pod.WaitForPodRunningInNamespace(context.TODO(), f.ClientSet, pod2)).Should(gomega.Succeed())

framework.ExpectNoError(err, "Step 5. Create one pod matching the EgressIP: running on egress1Node, failed, err: %v", err)
framework.Logf("Created pod %s on node %s", pod1Name, pod1Node.name)
framework.ExpectNoError(err, "Step 5. Create one pod matching the EgressIP: running on egress2Node, failed, err: %v", err)
framework.Logf("Created pod %s on node %s", pod2Name, pod2Node.name)

ginkgo.By("6. Check connectivity from pod to an external node and verify that the srcIP is the expected egressIP")
err = wait.PollImmediate(retryInterval, retryTimeout, targetExternalContainerAndTest(targetNode, pod1Name, pod1Namespace.Name, true, []string{egressIP1.String()}))
framework.ExpectNoError(err, "Step 6. Check connectivity from pod to an external node and verify that the srcIP is the expected egressIP, failed: %v", err)

ginkgo.By("7. Check connectivity from pod connected to the same network and verify that the srcIP is the expected egressIP")
err = wait.PollImmediate(retryInterval, retryTimeout, targetExternalContainerAndTest(targetNode, pod2Name, pod2OtherNetworkNamespace, true, []string{egressIP1.String()}))
framework.ExpectNoError(err, "Step 7. Check connectivity from pod connected to the same network and verify that the srcIP is the expected nodeIP, failed: %v", err)

ginkgo.By("8. Delete pod in one namespace")
framework.ExpectNoError(pod.DeletePodWithWait(context.TODO(), f.ClientSet, pod1), "pod %s/%s deletion failed", pod1.Namespace, pod1.Name)

ginkgo.By("9. Check connectivity from other pod and verify that the srcIP is the expected egressIP")
err = wait.PollImmediate(retryInterval, retryTimeout, targetExternalContainerAndTest(targetNode, pod2Name, pod2OtherNetworkNamespace, true, []string{egressIP1.String()}))
framework.ExpectNoError(err, "Step 9. Check connectivity from other pod and verify that the srcIP is the expected egressIP, failed: %v", err)

ginkgo.By("10. Delete namespace with zero pods")
gomega.Expect(f.ClientSet.CoreV1().Namespaces().Delete(context.TODO(), pod1.Namespace, metav1.DeleteOptions{})).To(gomega.Succeed())

ginkgo.By("11. Check connectivity from other pod and verify that the srcIP is the expected egressIP")
err = wait.PollImmediate(retryInterval, retryTimeout, targetExternalContainerAndTest(targetNode, pod2Name, pod2OtherNetworkNamespace, true, []string{egressIP1.String()}))
framework.ExpectNoError(err, "Step 11. Check connectivity from other pod and verify that the srcIP is the expected egressIP and verify that the srcIP is the expected nodeIP, failed: %v", err)
})

ginkgo.DescribeTable("[OVN network] multiple namespaces with different primary networks", func(otherNetworkAttachParms networkAttachmentConfigParams) {
if !isNetworkSegmentationEnabled() {
ginkgo.Skip("Network segmentation is disabled")
Expand Down

0 comments on commit 1e550f4

Please sign in to comment.