github.com/looshlee/cilium@v1.6.12/test/k8sT/Nightly.go (about)

     1  // Copyright 2017-2019 Authors of Cilium
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  package k8sTest
    15  
    16  import (
    17  	"context"
    18  	"fmt"
    19  	"path"
    20  	"strings"
    21  	"time"
    22  
    23  	"github.com/cilium/cilium/api/v1/models"
    24  	. "github.com/cilium/cilium/test/ginkgo-ext"
    25  	"github.com/cilium/cilium/test/helpers"
    26  	"github.com/cilium/cilium/test/helpers/policygen"
    27  
    28  	"github.com/onsi/ginkgo"
    29  	. "github.com/onsi/gomega"
    30  	"github.com/sirupsen/logrus"
    31  )
    32  
    33  var (
    34  	endpointTimeout  = 1 * time.Minute
    35  	timeout          = 5 * time.Minute
    36  	netcatDsManifest = "netcat-ds.yaml"
    37  )
    38  
    39  var _ = Describe("NightlyEpsMeasurement", func() {
    40  
    41  	var kubectl *helpers.Kubectl
    42  
    43  	endpointCount := 45
    44  	endpointsTimeout := endpointTimeout * time.Duration(endpointCount)
    45  	manifestPath := "tmp.yaml"
    46  	vagrantManifestPath := path.Join(helpers.BasePath, manifestPath)
    47  	var err error
    48  
    49  	BeforeAll(func() {
    50  		kubectl = helpers.CreateKubectl(helpers.K8s1VMName(), logger)
    51  		DeployCiliumAndDNS(kubectl)
    52  	})
    53  	deleteAll := func() {
    54  		ctx, cancel := context.WithTimeout(context.Background(), endpointsTimeout)
    55  		defer cancel()
    56  		kubectl.ExecInBackground(ctx, fmt.Sprintf(
    57  			"%s delete --all pods,svc,cnp -n %s --grace-period=0 --force",
    58  			helpers.KubectlCmd, helpers.DefaultNamespace))
    59  
    60  		select {
    61  		case <-ctx.Done():
    62  			logger.Errorf("DeleteAll: delete all pods,services failed after %s", helpers.HelperTimeout)
    63  		}
    64  	}
    65  	AfterAll(func() {
    66  		deleteAll()
    67  		ExpectAllPodsTerminated(kubectl)
    68  		kubectl.CloseSSHClient()
    69  	})
    70  
    71  	AfterFailed(func() {
    72  		kubectl.CiliumReport(helpers.KubeSystemNamespace,
    73  			"cilium service list",
    74  			"cilium endpoint list")
    75  	})
    76  
    77  	JustAfterEach(func() {
    78  		kubectl.ValidateNoErrorsInLogs(CurrentGinkgoTestDescription().Duration)
    79  	})
    80  
    81  	AfterEach(func() {
    82  		ExpectAllPodsTerminated(kubectl)
    83  
    84  		kubectl.Delete(vagrantManifestPath)
    85  		ExpectAllPodsTerminated(kubectl)
    86  	})
    87  
    88  	deployEndpoints := func() {
    89  		_, _, err = helpers.GenerateManifestForEndpoints(endpointCount, manifestPath)
    90  		ExpectWithOffset(1, err).Should(BeNil(), "Manifest cannot be created correctly")
    91  
    92  		// This is equivalent to res := kubectl.Apply(vagrantManifestPath) but we
    93  		// need a longer timeout than helpers.ShortCommandTimeout
    94  		ctx, cancel := context.WithTimeout(context.Background(), endpointsTimeout)
    95  		defer cancel()
    96  		res := kubectl.ExecContext(ctx, fmt.Sprintf("%s apply -f  %s", helpers.KubectlCmd, vagrantManifestPath))
    97  		res.ExpectSuccess("cannot apply eps manifest :%s", res.GetDebugMessage())
    98  	}
    99  
   100  	getServices := func() map[string]string {
   101  		// getServices returns a map of services, where service name is the key
   102  		// and the ClusterIP is the value.
   103  		services, err := kubectl.Get(helpers.DefaultNamespace, fmt.Sprintf("services -l zgroup=testapp")).Filter(
   104  			`{range .items[*]}{.metadata.name}{"="}{.spec.clusterIP}{"\n"}{end}`)
   105  		ExpectWithOffset(1, err).To(BeNil(), "cannot retrieve testapp services")
   106  		result := make(map[string]string)
   107  		for _, line := range strings.Split(services.String(), "\n") {
   108  			vals := strings.Split(line, "=")
   109  			if len(vals) == 2 {
   110  				result[vals[0]] = vals[1]
   111  			}
   112  		}
   113  		return result
   114  	}
   115  
   116  	Measure("The endpoint creation", func(b ginkgo.Benchmarker) {
   117  		desiredState := string(models.EndpointStateReady)
   118  
   119  		deployEndpoints()
   120  		waitForPodsTime := b.Time("Wait for pods", func() {
   121  			err := kubectl.WaitforPods(helpers.DefaultNamespace, "-l zgroup=testapp", endpointsTimeout)
   122  			Expect(err).Should(BeNil(),
   123  				"Cannot retrieve %d pods in %d seconds", endpointCount, endpointsTimeout.Seconds())
   124  		})
   125  
   126  		log.WithFields(logrus.Fields{"pod creation time": waitForPodsTime}).Info("")
   127  
   128  		ciliumPods, err := kubectl.GetCiliumPods(helpers.KubeSystemNamespace)
   129  		Expect(err).To(BeNil(), "Cannot retrieve cilium pods")
   130  
   131  		runtime := b.Time("Endpoint creation", func() {
   132  			Eventually(func() bool {
   133  				count := 0
   134  				for _, pod := range ciliumPods {
   135  					status := kubectl.CiliumEndpointsStatus(pod)
   136  					result := map[string]int{}
   137  					for _, state := range status {
   138  						result[state]++
   139  					}
   140  					count += result[desiredState]
   141  					logger.WithFields(logrus.Fields{
   142  						"status": result,
   143  						"pod":    pod,
   144  					}).Info("Cilium endpoint status")
   145  				}
   146  				return count >= endpointCount
   147  			}, endpointsTimeout, 3*time.Second).Should(BeTrue())
   148  		})
   149  		log.WithFields(logrus.Fields{"endpoint creation time": runtime}).Info("")
   150  
   151  		services := getServices()
   152  		Expect(len(services)).To(BeNumerically(">", 0), "Was not able to get services")
   153  
   154  		pods, err := kubectl.GetPodNames(helpers.DefaultNamespace, "zgroup=testapp")
   155  		Expect(err).To(BeNil(), "cannot retrieve pods names")
   156  
   157  		err = kubectl.WaitforPods(helpers.DefaultNamespace, "", helpers.HelperTimeout)
   158  		Expect(err).Should(BeNil(), "Pods are not ready after timeout")
   159  
   160  		By("Testing if http requests to multiple endpoints do not timeout")
   161  		for i := 0; i < 5; i++ {
   162  			for _, pod := range pods {
   163  				for service, ip := range services {
   164  					b.Time("Curl to service", func() {
   165  
   166  						res := kubectl.ExecPodCmd(
   167  							helpers.DefaultNamespace, pod,
   168  							helpers.CurlFail(fmt.Sprintf("http://%s:80/", ip)))
   169  						res.ExpectSuccess(
   170  							"Cannot curl from %s to service %s on  ip %s", pod, service, ip)
   171  					})
   172  				}
   173  
   174  			}
   175  		}
   176  
   177  	}, 1)
   178  
   179  	Context("Nightly Policies", func() {
   180  
   181  		numPods := 20
   182  		bunchPods := 5
   183  		podsCreated := 0
   184  
   185  		AfterEach(func() {
   186  			deleteAll()
   187  			ExpectAllPodsTerminated(kubectl)
   188  		})
   189  
   190  		Measure(fmt.Sprintf("Applying policies to %d pods in a group of %d", numPods, bunchPods), func(b ginkgo.Benchmarker) {
   191  			testDef := func() {
   192  				logger.Errorf("Creating %d new pods, total created are %d", numPods, podsCreated)
   193  				testSpecGroup := policygen.TestSpecsGroup{}
   194  				for i := 0; i < bunchPods; i++ {
   195  					testSpec := policygen.GetBasicTestSpec()
   196  					testSpecGroup = append(testSpecGroup, &testSpec)
   197  				}
   198  
   199  				By("Creating endpoints")
   200  
   201  				endpoints := b.Time("Runtime", func() {
   202  					testSpecGroup.CreateAndApplyManifests(kubectl)
   203  					err := kubectl.WaitforPods(helpers.DefaultNamespace, "-l test=policygen", longTimeout)
   204  					Expect(err).To(BeNil(), "Pods are not ready after timeout")
   205  				})
   206  
   207  				b.RecordValue("Endpoint Creation in seconds", endpoints.Seconds())
   208  				By("Apply Policies")
   209  
   210  				policy := b.Time("policy", func() {
   211  					testSpecGroup.CreateAndApplyCNP(kubectl)
   212  				})
   213  				b.RecordValue("Policy Creation in seconds", policy.Seconds())
   214  
   215  				By("Connectivity Test")
   216  				conn := b.Time("connTest", func() {
   217  					testSpecGroup.ConnectivityTest()
   218  				})
   219  
   220  				b.RecordValue("Connectivity test in seconds", conn.Seconds())
   221  			}
   222  
   223  			for podsCreated < numPods {
   224  				testDef()
   225  				podsCreated = podsCreated + bunchPods
   226  			}
   227  		}, 1)
   228  	})
   229  
   230  	Context("Test long live connections", func() {
   231  		getServer := func(port string) string {
   232  			return fmt.Sprintf("nc -p %s -lk -v", port)
   233  		}
   234  
   235  		getClient := func(ip, port, filePipe string) string {
   236  			return fmt.Sprintf(
   237  				"rm %[1]s; touch %[1]s; tail -f %[1]s 2>&1 | nc -v %[2]s %[3]s",
   238  				filePipe, ip, port)
   239  		}
   240  
   241  		HTTPRequest := func(uid, host string) string {
   242  			request := `GET /public HTTP/1.1\r\n` +
   243  				`host: %s:8888\r\n` +
   244  				`user-agent: curl/7.54.0\r\n` +
   245  				`accept: */*\r\n` +
   246  				`UID: %s\r\n` +
   247  				`content-length: 0\r\n`
   248  			return fmt.Sprintf(request, host, uid)
   249  		}
   250  		// testConnectivity check that nc is running across the k8s nodes
   251  		testConnectivity := func() {
   252  
   253  			pipePath := "/tmp/nc_pipe.txt"
   254  			listeningString := "listening on [::]:8888"
   255  
   256  			err := kubectl.WaitforPods(helpers.DefaultNamespace, "-l zgroup=netcatds", helpers.HelperTimeout)
   257  			Expect(err).To(BeNil(), "Pods are not ready after timeout")
   258  
   259  			netcatPods, err := kubectl.GetPodNames(helpers.DefaultNamespace, "zgroup=netcatds")
   260  			Expect(err).To(BeNil(), "Cannot get pods names for netcatds")
   261  			Expect(len(netcatPods)).To(BeNumerically(">", 0), "Pods are not ready")
   262  
   263  			server := netcatPods[0]
   264  			client := netcatPods[1]
   265  			ips, err := kubectl.GetPodsIPs(helpers.DefaultNamespace, "zgroup=netcatds")
   266  			Expect(err).To(BeNil(), "Cannot get netcat ips")
   267  
   268  			ncServer := getServer("8888")
   269  			ncClient := getClient(ips[server], "8888", pipePath)
   270  
   271  			ctx, cancel := context.WithCancel(context.Background())
   272  			defer cancel()
   273  
   274  			serverctx := kubectl.ExecPodCmdBackground(ctx, helpers.DefaultNamespace, server, ncServer)
   275  			err = serverctx.WaitUntilMatch(listeningString)
   276  			Expect(err).To(BeNil(), "netcat server did not start correctly")
   277  
   278  			_ = kubectl.ExecPodCmdBackground(ctx, helpers.DefaultNamespace, client, ncClient)
   279  
   280  			testNcConnectivity := func(sleep time.Duration) {
   281  				helpers.Sleep(sleep)
   282  				uid := helpers.MakeUID()
   283  				_ = kubectl.ExecPodCmd(helpers.DefaultNamespace, client,
   284  					fmt.Sprintf(`echo -e "%s" >> %s`, HTTPRequest(uid, ips[client]), pipePath))
   285  				Expect(serverctx.WaitUntilMatch(uid)).To(BeNil(),
   286  					"%q is not in the server output after timeout", uid)
   287  				serverctx.ExpectContains(uid, "Cannot get server UUID")
   288  			}
   289  			By("Testing that simple nc works")
   290  			testNcConnectivity(1)
   291  
   292  			By("Sleeping for a minute to check tcp-keepalive")
   293  			testNcConnectivity(60)
   294  
   295  			By("Sleeping for six  minutes to check tcp-keepalive")
   296  			testNcConnectivity(360)
   297  		}
   298  
   299  		It("Test TCP Keepalive with L7 Policy", func() {
   300  			kubectl.ValidateNoErrorsInLogs(CurrentGinkgoTestDescription().Duration)
   301  			manifest := helpers.ManifestGet(netcatDsManifest)
   302  			kubectl.ApplyDefault(manifest).ExpectSuccess("Cannot apply netcat ds")
   303  			defer kubectl.Delete(manifest)
   304  			testConnectivity()
   305  		})
   306  
   307  		It("Test TCP Keepalive without L7 Policy", func() {
   308  			manifest := helpers.ManifestGet(netcatDsManifest)
   309  			kubectl.ApplyDefault(manifest).ExpectSuccess("Cannot apply netcat ds")
   310  			defer kubectl.Delete(manifest)
   311  			kubectl.Exec(fmt.Sprintf(
   312  				"%s delete --all cnp -n %s", helpers.KubectlCmd, helpers.DefaultNamespace))
   313  			testConnectivity()
   314  		})
   315  	})
   316  })
   317  
   318  var _ = Describe("NightlyExamples", func() {
   319  
   320  	var kubectl *helpers.Kubectl
   321  	var demoPath string
   322  	var l3Policy, l7Policy string
   323  
   324  	BeforeAll(func() {
   325  		kubectl = helpers.CreateKubectl(helpers.K8s1VMName(), logger)
   326  
   327  		demoPath = helpers.ManifestGet("demo.yaml")
   328  		l3Policy = helpers.ManifestGet("l3-l4-policy.yaml")
   329  		l7Policy = helpers.ManifestGet("l7-policy.yaml")
   330  	})
   331  
   332  	AfterFailed(func() {
   333  		kubectl.CiliumReport(helpers.KubeSystemNamespace,
   334  			"cilium service list",
   335  			"cilium endpoint list")
   336  	})
   337  
   338  	JustAfterEach(func() {
   339  		kubectl.ValidateNoErrorsInLogs(CurrentGinkgoTestDescription().Duration)
   340  	})
   341  
   342  	AfterEach(func() {
   343  		kubectl.Delete(demoPath)
   344  		kubectl.Delete(l3Policy)
   345  		kubectl.Delete(l7Policy)
   346  
   347  		ExpectAllPodsTerminated(kubectl)
   348  	})
   349  
   350  	AfterAll(func() {
   351  		kubectl.CloseSSHClient()
   352  	})
   353  
   354  	Context("Upgrade test", func() {
   355  		var cleanupCallback = func() { return }
   356  
   357  		BeforeEach(func() {
   358  			// Delete kube-dns because if not will be a restore the old endpoints
   359  			// from master instead of create the new ones.
   360  			_ = kubectl.Delete(helpers.DNSDeployment())
   361  
   362  			_ = kubectl.DeleteResource(
   363  				"deploy", fmt.Sprintf("-n %s cilium-operator", helpers.KubeSystemNamespace))
   364  
   365  			// Delete etcd operator because sometimes when install from
   366  			// clean-state the quorum is lost.
   367  			// ETCD operator maybe is not installed at all, so no assert here.
   368  			kubectl.DeleteETCDOperator()
   369  			ExpectAllPodsTerminated(kubectl)
   370  
   371  		})
   372  
   373  		AfterEach(func() {
   374  			cleanupCallback()
   375  		})
   376  
   377  		AfterAll(func() {
   378  			_ = kubectl.ApplyDefault(helpers.DNSDeployment())
   379  		})
   380  
   381  		for _, image := range helpers.NightlyStableUpgradesFrom {
   382  			func(version string) {
   383  				It(fmt.Sprintf("Update Cilium from %s to master", version), func() {
   384  					var assertUpgradeSuccessful func()
   385  					assertUpgradeSuccessful, cleanupCallback = InstallAndValidateCiliumUpgrades(
   386  						kubectl, image, helpers.CiliumDeveloperImage)
   387  					assertUpgradeSuccessful()
   388  				})
   389  			}(image)
   390  		}
   391  	})
   392  
   393  	Context("Getting started guides", func() {
   394  
   395  		var (
   396  			GRPCManifest = "../examples/kubernetes-grpc/cc-door-app.yaml"
   397  			GRPCPolicy   = "../examples/kubernetes-grpc/cc-door-ingress-security.yaml"
   398  
   399  			AppManifest    = helpers.GetFilePath(GRPCManifest)
   400  			PolicyManifest = helpers.GetFilePath(GRPCPolicy)
   401  		)
   402  
   403  		BeforeAll(func() {
   404  			DeployCiliumAndDNS(kubectl)
   405  		})
   406  
   407  		AfterAll(func() {
   408  			kubectl.Delete(AppManifest)
   409  			kubectl.Delete(PolicyManifest)
   410  			ExpectAllPodsTerminated(kubectl)
   411  		})
   412  
   413  		It("GRPC example", func() {
   414  
   415  			clientPod := "terminal-87"
   416  
   417  			By("Testing the example config")
   418  			kubectl.ApplyDefault(AppManifest).ExpectSuccess("cannot install the GRPC application")
   419  
   420  			err := kubectl.WaitforPods(helpers.DefaultNamespace, "-l zgroup=grpcExample", helpers.HelperTimeout)
   421  			Expect(err).Should(BeNil(), "Pods are not ready after timeout")
   422  
   423  			res := kubectl.ExecPodCmd(
   424  				helpers.DefaultNamespace, clientPod,
   425  				"python3 /cloudcity/cc_door_client.py GetName 1")
   426  			res.ExpectSuccess("Client cannot get Name")
   427  
   428  			res = kubectl.ExecPodCmd(
   429  				helpers.DefaultNamespace, clientPod,
   430  				"python3 /cloudcity/cc_door_client.py GetLocation 1")
   431  			res.ExpectSuccess("Client cannot get Location")
   432  
   433  			res = kubectl.ExecPodCmd(
   434  				helpers.DefaultNamespace, clientPod,
   435  				"python3 /cloudcity/cc_door_client.py SetAccessCode 1 999")
   436  			res.ExpectSuccess("Client cannot set Accesscode")
   437  
   438  			By("Testing with L7 policy")
   439  			_, err = kubectl.CiliumPolicyAction(
   440  				helpers.DefaultNamespace, PolicyManifest,
   441  				helpers.KubectlApply, helpers.HelperTimeout)
   442  			Expect(err).To(BeNil(), "Cannot import GPRC policy")
   443  
   444  			res = kubectl.ExecPodCmd(
   445  				helpers.DefaultNamespace, clientPod,
   446  				"python3 /cloudcity/cc_door_client.py GetName 1")
   447  			res.ExpectSuccess("Client cannot get Name")
   448  
   449  			res = kubectl.ExecPodCmd(
   450  				helpers.DefaultNamespace, clientPod,
   451  				"python3 /cloudcity/cc_door_client.py GetLocation 1")
   452  			res.ExpectSuccess("Client cannot get Location")
   453  
   454  			res = kubectl.ExecPodCmd(
   455  				helpers.DefaultNamespace, clientPod,
   456  				"python3 /cloudcity/cc_door_client.py SetAccessCode 1 999")
   457  			res.ExpectFail("Client can set Accesscode and it shoud not")
   458  		})
   459  	})
   460  })