...

Source file src/k8s.io/kubernetes/test/e2e/network/no_snat.go

Documentation: k8s.io/kubernetes/test/e2e/network

     1  /*
     2  Copyright 2017 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package network
    18  
    19  import (
    20  	"context"
    21  	"fmt"
    22  	"net"
    23  	"time"
    24  
    25  	"github.com/onsi/ginkgo/v2"
    26  	"github.com/onsi/gomega"
    27  	v1 "k8s.io/api/core/v1"
    28  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    29  	"k8s.io/apimachinery/pkg/util/wait"
    30  	admissionapi "k8s.io/pod-security-admission/api"
    31  
    32  	"k8s.io/kubernetes/test/e2e/feature"
    33  	"k8s.io/kubernetes/test/e2e/framework"
    34  	e2enode "k8s.io/kubernetes/test/e2e/framework/node"
    35  	e2epod "k8s.io/kubernetes/test/e2e/framework/pod"
    36  	"k8s.io/kubernetes/test/e2e/network/common"
    37  	imageutils "k8s.io/kubernetes/test/utils/image"
    38  )
    39  
    40  const (
    41  	testPodPort    = "8080"
    42  	noSNATTestName = "no-snat-test"
    43  )
    44  
    45  var (
    46  	testPod = v1.Pod{
    47  		ObjectMeta: metav1.ObjectMeta{
    48  			GenerateName: noSNATTestName,
    49  			Labels: map[string]string{
    50  				noSNATTestName: "",
    51  			},
    52  		},
    53  		Spec: v1.PodSpec{
    54  			Containers: []v1.Container{
    55  				{
    56  					Name:  noSNATTestName,
    57  					Image: imageutils.GetE2EImage(imageutils.Agnhost),
    58  					Args:  []string{"netexec", "--http-port", testPodPort},
    59  				},
    60  			},
    61  		},
    62  	}
    63  )
    64  
    65  // This test verifies that a Pod on each node in a cluster can talk to Pods on every other node without SNAT.
    66  // We use the [Feature:NoSNAT] tag so that most jobs will skip this test by default.
    67  var _ = common.SIGDescribe("NoSNAT", feature.NoSNAT, framework.WithSlow(), func() {
    68  	f := framework.NewDefaultFramework("no-snat-test")
    69  	f.NamespacePodSecurityLevel = admissionapi.LevelPrivileged
    70  	ginkgo.It("Should be able to send traffic between Pods without SNAT", func(ctx context.Context) {
    71  		cs := f.ClientSet
    72  		pc := cs.CoreV1().Pods(f.Namespace.Name)
    73  
    74  		ginkgo.By("creating a test pod on each Node")
    75  		nodes, err := e2enode.GetReadySchedulableNodes(ctx, cs)
    76  		framework.ExpectNoError(err)
    77  		gomega.Expect(nodes.Items).ToNot(gomega.BeEmpty(), "no Nodes in the cluster")
    78  
    79  		for _, node := range nodes.Items {
    80  			// target Pod at Node
    81  			nodeSelection := e2epod.NodeSelection{Name: node.Name}
    82  			e2epod.SetNodeSelection(&testPod.Spec, nodeSelection)
    83  			_, err = pc.Create(ctx, &testPod, metav1.CreateOptions{})
    84  			framework.ExpectNoError(err)
    85  		}
    86  
    87  		ginkgo.By("waiting for all of the no-snat-test pods to be scheduled and running")
    88  		err = wait.PollImmediate(10*time.Second, 1*time.Minute, func() (bool, error) {
    89  			pods, err := pc.List(ctx, metav1.ListOptions{LabelSelector: noSNATTestName})
    90  			if err != nil {
    91  				return false, err
    92  			}
    93  
    94  			// check all pods are running
    95  			for _, pod := range pods.Items {
    96  				if pod.Status.Phase != v1.PodRunning {
    97  					if pod.Status.Phase != v1.PodPending {
    98  						return false, fmt.Errorf("expected pod to be in phase \"Pending\" or \"Running\"")
    99  					}
   100  					return false, nil // pod is still pending
   101  				}
   102  			}
   103  			return true, nil // all pods are running
   104  		})
   105  		framework.ExpectNoError(err)
   106  
   107  		ginkgo.By("sending traffic from each pod to the others and checking that SNAT does not occur")
   108  		pods, err := pc.List(ctx, metav1.ListOptions{LabelSelector: noSNATTestName})
   109  		framework.ExpectNoError(err)
   110  
   111  		// hit the /clientip endpoint on every other Pods to check if source ip is preserved
   112  		// this test is O(n^2) but it doesn't matter because we only run this test on small clusters (~3 nodes)
   113  		for _, sourcePod := range pods.Items {
   114  			for _, targetPod := range pods.Items {
   115  				if targetPod.Name == sourcePod.Name {
   116  					continue
   117  				}
   118  				targetAddr := net.JoinHostPort(targetPod.Status.PodIP, testPodPort)
   119  				sourceIP, execPodIP := execSourceIPTest(sourcePod, targetAddr)
   120  				ginkgo.By("Verifying the preserved source ip")
   121  				gomega.Expect(sourceIP).To(gomega.Equal(execPodIP))
   122  			}
   123  		}
   124  	})
   125  })
   126  

View as plain text