@@ -13,14 +13,17 @@ import (
1313 mg "github.com/openshift/origin/test/extended/machine_config"
1414 exutil "github.com/openshift/origin/test/extended/util"
1515 "golang.org/x/sync/errgroup"
16+ appsv1 "k8s.io/api/apps/v1"
1617 corev1 "k8s.io/api/core/v1"
1718 apierrors "k8s.io/apimachinery/pkg/api/errors"
1819 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
20+ "k8s.io/apimachinery/pkg/labels"
1921 "k8s.io/apimachinery/pkg/runtime/schema"
2022 "k8s.io/apimachinery/pkg/util/wait"
2123 "k8s.io/kubernetes/test/e2e/framework"
2224 e2epod "k8s.io/kubernetes/test/e2e/framework/pod"
2325 e2eoutput "k8s.io/kubernetes/test/e2e/framework/pod/output"
26+ e2eskipper "k8s.io/kubernetes/test/e2e/framework/skipper"
2427 "k8s.io/kubernetes/test/e2e/framework/statefulset"
2528 admissionapi "k8s.io/pod-security-admission/api"
2629
9396 rightServerCertName = "right_server"
9497 // Expiration date for certificates.
9598 certExpirationDate = time .Date (2034 , time .April , 10 , 0 , 0 , 0 , 0 , time .UTC )
99+ // http endpoint port for the pod traffic test
100+ port uint16 = 8080
96101)
97102
98103type trafficType string
@@ -652,6 +657,130 @@ var _ = g.Describe("[sig-network][Feature:IPsec]", g.Ordered, func() {
652657 })
653658})
654659
660+ var _ = g .Describe ("[sig-network][Feature:IPsec] IPsec resilience" , g .Ordered , func () {
661+ oc := exutil .NewCLIWithPodSecurityLevel ("ipsec" , admissionapi .LevelPrivileged )
662+ f := oc .KubeFramework ()
663+ var ipsecMode v1.IPsecMode
664+
665+ InOVNKubernetesContext (func () {
666+ g .BeforeAll (func () {
667+ var err error
668+ ipsecConfig , err := getIPsecConfig (oc )
669+ o .Expect (err ).NotTo (o .HaveOccurred ())
670+ ipsecMode = ipsecConfig .mode
671+ })
672+
673+ g .It ("check pod traffic is working across nodes [apigroup:config.openshift.io] [Suite:openshift/network/ipsec]" , func () {
674+ g .By ("creating test pods" )
675+ pods := createWebServerPods (oc , f .Namespace .Name )
676+ g .By ("checking crossing connectivity over the pods" )
677+ checkPodCrossConnectivity (pods )
678+ })
679+
680+ g .It ("check pod traffic is working across nodes after ipsec daemonset restart [apigroup:config.openshift.io] [Suite:openshift/network/ipsec]" , func () {
681+ // The IPsec daemonset manages IPsec connections between nodes for pod's east-west traffic.
682+ // The IPsec daemonset exists only in IPsec full mode, so skip this test for other IPsec modes.
683+ if ipsecMode != v1 .IPsecModeFull {
684+ e2eskipper .Skipf ("cluster is configured with IPsec %s mode, so skipping the test" , ipsecMode )
685+ }
686+ g .By ("creating test pods" )
687+ pods := createWebServerPods (oc , f .Namespace .Name )
688+ g .By ("checking crossing connectivity over the pods" )
689+ checkPodCrossConnectivity (pods )
690+ // Restart IPsec daemonset few times and check pod traffic is not impacted.
691+ for i := 1 ; i <= 5 ; i ++ {
692+ g .By (fmt .Sprintf ("attempt#%d restarting IPsec pods" , i ))
693+ restartIPsecDaemonSet (oc )
694+ g .By ("checking crossing connectivity over the pods" )
695+ checkPodCrossConnectivity (pods )
696+ }
697+ })
698+ })
699+ })
700+
701+ func restartIPsecDaemonSet (oc * exutil.CLI ) {
702+ g .GinkgoHelper ()
703+ ds , err := getDaemonSet (oc , ovnNamespace , ovnIPsecDsName )
704+ o .Expect (err ).NotTo (o .HaveOccurred ())
705+ o .Expect (ds ).NotTo (o .BeNil ())
706+ err = deleteDaemonSet (oc .AdminKubeClient (), ovnNamespace , ovnIPsecDsName )
707+ o .Expect (err ).NotTo (o .HaveOccurred ())
708+ // wait until CNO reconciles IPsec daemonset.
709+ err = ensureIPsecFullEnabled (oc )
710+ o .Expect (err ).NotTo (o .HaveOccurred ())
711+ }
712+
713+ func createWebServerPods (oc * exutil.CLI , namespace string ) []corev1.Pod {
714+ g .GinkgoHelper ()
715+ immediate := int64 (0 )
716+ ds := & appsv1.DaemonSet {
717+ ObjectMeta : metav1.ObjectMeta {
718+ Name : "ipsec-webserver" ,
719+ Namespace : namespace ,
720+ },
721+ Spec : appsv1.DaemonSetSpec {
722+ Selector : & metav1.LabelSelector {
723+ MatchLabels : map [string ]string {
724+ "apps" : "ipsec-webserver" ,
725+ },
726+ },
727+ Template : corev1.PodTemplateSpec {
728+ ObjectMeta : metav1.ObjectMeta {
729+ Labels : map [string ]string {
730+ "apps" : "ipsec-webserver" ,
731+ },
732+ },
733+ Spec : corev1.PodSpec {
734+ Tolerations : []corev1.Toleration {
735+ {
736+ Key : "node-role.kubernetes.io/master" ,
737+ Operator : corev1 .TolerationOpExists ,
738+ Effect : corev1 .TaintEffectNoSchedule ,
739+ },
740+ },
741+ TerminationGracePeriodSeconds : & immediate ,
742+ Containers : []corev1.Container {e2epod .NewAgnhostContainer ("agnhost-container" , nil , nil , httpServerContainerCmd (port )... )},
743+ },
744+ },
745+ },
746+ }
747+ ds , err := oc .AdminKubeClient ().AppsV1 ().DaemonSets (namespace ).Create (context .Background (), ds , metav1.CreateOptions {})
748+ o .Expect (err ).NotTo (o .HaveOccurred ())
749+ err = wait .PollUntilContextTimeout (context .Background (), 1 * time .Second ,
750+ 180 * time .Second , true , func (ctx context.Context ) (bool , error ) {
751+ return isDaemonSetRunning (oc , namespace , ds .Name )
752+ })
753+ o .Expect (err ).NotTo (o .HaveOccurred ())
754+
755+ pods , err := oc .AdminKubeClient ().CoreV1 ().Pods (namespace ).List (context .Background (),
756+ metav1.ListOptions {LabelSelector : labels .Set (ds .Spec .Selector .MatchLabels ).String ()})
757+ o .Expect (err ).NotTo (o .HaveOccurred ())
758+ ds , err = getDaemonSet (oc , namespace , ds .Name )
759+ o .Expect (err ).NotTo (o .HaveOccurred ())
760+ o .Expect (len (pods .Items )).To (o .Equal (int (ds .Status .NumberAvailable )), fmt .Sprintf ("%#v" , pods .Items ))
761+ return pods .Items
762+ }
763+
764+ func checkPodCrossConnectivity (pods []corev1.Pod ) {
765+ g .GinkgoHelper ()
766+ var testFns []func () error
767+ for _ , sourcePod := range pods {
768+ for _ , targetPod := range pods {
769+ if sourcePod .Name == targetPod .Name {
770+ // Skip if source and target pod are same, pod connectivity check is not required
771+ // for this case.
772+ continue
773+ }
774+ testFns = append (testFns , func () error {
775+ framework .Logf ("Checking pod connectivity from node %s to node %s" , sourcePod .Spec .NodeName , targetPod .Spec .NodeName )
776+ return connectToServer (podConfiguration {namespace : sourcePod .Namespace , name : sourcePod .Name }, targetPod .Status .PodIP , int (port ))
777+ })
778+ }
779+ }
780+ errs := ParallelTest (6 , testFns )
781+ o .Expect (errs ).To (o .Equal ([]error (nil )))
782+ }
783+
655784func waitForIPsecConfigToComplete (oc * exutil.CLI , ipsecMode v1.IPsecMode ) {
656785 g .GinkgoHelper ()
657786 switch ipsecMode {
0 commit comments