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 })