...

Source file src/k8s.io/kubernetes/test/e2e/windows/hybrid_network.go

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

     1  /*
     2  Copyright 2018 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 windows
    18  
    19  import (
    20  	"context"
    21  	"fmt"
    22  
    23  	v1 "k8s.io/api/core/v1"
    24  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    25  	"k8s.io/apimachinery/pkg/util/uuid"
    26  	"k8s.io/kubernetes/test/e2e/feature"
    27  	"k8s.io/kubernetes/test/e2e/framework"
    28  	e2epod "k8s.io/kubernetes/test/e2e/framework/pod"
    29  	e2eskipper "k8s.io/kubernetes/test/e2e/framework/skipper"
    30  	admissionapi "k8s.io/pod-security-admission/api"
    31  
    32  	imageutils "k8s.io/kubernetes/test/utils/image"
    33  
    34  	"github.com/onsi/ginkgo/v2"
    35  	"github.com/onsi/gomega"
    36  )
    37  
    38  const (
    39  	linuxOS   = "linux"
    40  	windowsOS = "windows"
    41  )
    42  
    43  var (
    44  	windowsBusyBoximage = imageutils.GetE2EImage(imageutils.Agnhost)
    45  	linuxBusyBoxImage   = imageutils.GetE2EImage(imageutils.Nginx)
    46  )
    47  
    48  var _ = sigDescribe("Hybrid cluster network", skipUnlessWindows(func() {
    49  	f := framework.NewDefaultFramework("hybrid-network")
    50  	f.NamespacePodSecurityLevel = admissionapi.LevelPrivileged
    51  
    52  	ginkgo.BeforeEach(func() {
    53  		e2eskipper.SkipUnlessNodeOSDistroIs("windows")
    54  	})
    55  
    56  	ginkgo.Context("for all supported CNIs", func() {
    57  
    58  		ginkgo.It("should have stable networking for Linux and Windows pods", func(ctx context.Context) {
    59  
    60  			linuxPod := createTestPod(f, linuxBusyBoxImage, linuxOS)
    61  			ginkgo.By("creating a linux pod and waiting for it to be running")
    62  			linuxPod = e2epod.NewPodClient(f).CreateSync(ctx, linuxPod)
    63  
    64  			windowsPod := createTestPod(f, windowsBusyBoximage, windowsOS)
    65  
    66  			windowsPod.Spec.Containers[0].Args = []string{"test-webserver"}
    67  			ginkgo.By("creating a windows pod and waiting for it to be running")
    68  			windowsPod = e2epod.NewPodClient(f).CreateSync(ctx, windowsPod)
    69  
    70  			ginkgo.By("verifying pod internal connectivity to the cluster dataplane")
    71  
    72  			ginkgo.By("checking connectivity from Linux to Windows")
    73  			assertConsistentConnectivity(ctx, f, linuxPod.ObjectMeta.Name, linuxOS, linuxCheck(windowsPod.Status.PodIP, 80), internalMaxTries)
    74  
    75  			ginkgo.By("checking connectivity from Windows to Linux")
    76  			assertConsistentConnectivity(ctx, f, windowsPod.ObjectMeta.Name, windowsOS, windowsCheck(linuxPod.Status.PodIP), internalMaxTries)
    77  
    78  		})
    79  
    80  		f.It("should provide Internet connection for Linux containers using DNS", feature.NetworkingDNS, func(ctx context.Context) {
    81  			linuxPod := createTestPod(f, linuxBusyBoxImage, linuxOS)
    82  			ginkgo.By("creating a linux pod and waiting for it to be running")
    83  			linuxPod = e2epod.NewPodClient(f).CreateSync(ctx, linuxPod)
    84  
    85  			ginkgo.By("verifying pod external connectivity to the internet")
    86  
    87  			ginkgo.By("checking connectivity to 8.8.8.8 53 (google.com) from Linux")
    88  			assertConsistentConnectivity(ctx, f, linuxPod.ObjectMeta.Name, linuxOS, linuxCheck("8.8.8.8", 53), externalMaxTries)
    89  		})
    90  
    91  		f.It("should provide Internet connection for Windows containers using DNS", feature.NetworkingDNS, func(ctx context.Context) {
    92  			windowsPod := createTestPod(f, windowsBusyBoximage, windowsOS)
    93  			ginkgo.By("creating a windows pod and waiting for it to be running")
    94  			windowsPod = e2epod.NewPodClient(f).CreateSync(ctx, windowsPod)
    95  
    96  			ginkgo.By("verifying pod external connectivity to the internet")
    97  
    98  			ginkgo.By("checking connectivity to 8.8.8.8 53 (google.com) from Windows")
    99  			assertConsistentConnectivity(ctx, f, windowsPod.ObjectMeta.Name, windowsOS, windowsCheck("www.google.com"), externalMaxTries)
   100  		})
   101  
   102  	})
   103  }))
   104  
   105  var (
   106  	warmUpDuration = "30s"
   107  	duration       = "10s"
   108  	pollInterval   = "1s"
   109  	timeoutSeconds = 10
   110  
   111  	externalMaxTries = 10
   112  	internalMaxTries = 1
   113  )
   114  
   115  func assertConsistentConnectivity(ctx context.Context, f *framework.Framework, podName string, os string, cmd []string, maxTries int) {
   116  	connChecker := func() error {
   117  		var err error
   118  		for i := 0; i < maxTries; i++ {
   119  			ginkgo.By(fmt.Sprintf("checking connectivity of %s-container in %s", os, podName))
   120  			stdout, stderr, err := e2epod.ExecCommandInContainerWithFullOutput(f, podName, os+"-container", cmd...)
   121  			if err == nil {
   122  				break
   123  			}
   124  			framework.Logf("Encountered error while running command: %v.\nStdout: %s\nStderr: %s\nErr: %v", cmd, stdout, stderr, err)
   125  		}
   126  		return err
   127  	}
   128  	gomega.Eventually(ctx, connChecker, warmUpDuration, pollInterval).ShouldNot(gomega.HaveOccurred())
   129  	gomega.Consistently(ctx, connChecker, duration, pollInterval).ShouldNot(gomega.HaveOccurred())
   130  }
   131  
   132  func linuxCheck(address string, port int) []string {
   133  	nc := fmt.Sprintf("nc -vz %s %v -w %v", address, port, timeoutSeconds)
   134  	cmd := []string{"/bin/sh", "-c", nc}
   135  	return cmd
   136  }
   137  
   138  func windowsCheck(address string) []string {
   139  	curl := fmt.Sprintf("curl.exe %s --connect-timeout %v --fail", address, timeoutSeconds)
   140  	cmd := []string{"cmd", "/c", curl}
   141  	return cmd
   142  }
   143  
   144  func createTestPod(f *framework.Framework, image string, os string) *v1.Pod {
   145  	containerName := fmt.Sprintf("%s-container", os)
   146  	podName := "pod-" + string(uuid.NewUUID())
   147  	pod := &v1.Pod{
   148  		TypeMeta: metav1.TypeMeta{
   149  			Kind:       "Pod",
   150  			APIVersion: "v1",
   151  		},
   152  		ObjectMeta: metav1.ObjectMeta{
   153  			Name: podName,
   154  		},
   155  		Spec: v1.PodSpec{
   156  			Containers: []v1.Container{
   157  				{
   158  					Name:  containerName,
   159  					Image: image,
   160  					Ports: []v1.ContainerPort{{ContainerPort: 80}},
   161  				},
   162  			},
   163  			NodeSelector: map[string]string{
   164  				"kubernetes.io/os": os,
   165  			},
   166  		},
   167  	}
   168  	if os == linuxOS {
   169  		pod.Spec.Tolerations = []v1.Toleration{
   170  			{
   171  				Operator: v1.TolerationOpExists,
   172  				Effect:   v1.TaintEffectNoSchedule,
   173  			},
   174  		}
   175  	}
   176  	return pod
   177  }
   178  

View as plain text