k8s.io/kubernetes@v1.31.0-alpha.0.0.20240520171757-56147500dadc/test/e2e/cloud/gcp/node_lease.go (about) 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 gcp 18 19 import ( 20 "context" 21 "fmt" 22 "strings" 23 "time" 24 25 v1 "k8s.io/api/core/v1" 26 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 27 clientset "k8s.io/client-go/kubernetes" 28 "k8s.io/kubernetes/test/e2e/framework" 29 e2enode "k8s.io/kubernetes/test/e2e/framework/node" 30 e2epod "k8s.io/kubernetes/test/e2e/framework/pod" 31 e2eskipper "k8s.io/kubernetes/test/e2e/framework/skipper" 32 admissionapi "k8s.io/pod-security-admission/api" 33 34 "github.com/onsi/ginkgo/v2" 35 "github.com/onsi/gomega" 36 ) 37 38 var _ = SIGDescribe(framework.WithDisruptive(), "NodeLease", func() { 39 f := framework.NewDefaultFramework("node-lease-test") 40 f.NamespacePodSecurityLevel = admissionapi.LevelPrivileged 41 var systemPodsNo int 42 var c clientset.Interface 43 var ns string 44 var group string 45 46 ginkgo.BeforeEach(func(ctx context.Context) { 47 e2eskipper.SkipUnlessProviderIs("gce", "gke") 48 c = f.ClientSet 49 ns = f.Namespace.Name 50 systemPods, err := e2epod.GetPodsInNamespace(ctx, c, ns, map[string]string{}) 51 framework.ExpectNoError(err) 52 systemPodsNo = len(systemPods) 53 if strings.Contains(framework.TestContext.CloudConfig.NodeInstanceGroup, ",") { 54 framework.Failf("Test dose not support cluster setup with more than one MIG: %s", framework.TestContext.CloudConfig.NodeInstanceGroup) 55 } else { 56 group = framework.TestContext.CloudConfig.NodeInstanceGroup 57 } 58 }) 59 60 ginkgo.Describe("NodeLease deletion", func() { 61 var skipped bool 62 63 ginkgo.BeforeEach(func() { 64 skipped = true 65 e2eskipper.SkipUnlessProviderIs("gce", "gke", "aws") 66 e2eskipper.SkipUnlessNodeCountIsAtLeast(2) 67 skipped = false 68 }) 69 70 ginkgo.AfterEach(func(ctx context.Context) { 71 if skipped { 72 return 73 } 74 75 ginkgo.By("restoring the original node instance group size") 76 if err := framework.ResizeGroup(group, int32(framework.TestContext.CloudConfig.NumNodes)); err != nil { 77 framework.Failf("Couldn't restore the original node instance group size: %v", err) 78 } 79 // In GKE, our current tunneling setup has the potential to hold on to a broken tunnel (from a 80 // rebooted/deleted node) for up to 5 minutes before all tunnels are dropped and recreated. 81 // Most tests make use of some proxy feature to verify functionality. So, if a reboot test runs 82 // right before a test that tries to get logs, for example, we may get unlucky and try to use a 83 // closed tunnel to a node that was recently rebooted. There's no good way to framework.Poll for proxies 84 // being closed, so we sleep. 85 // 86 // TODO(cjcullen) reduce this sleep (#19314) 87 if framework.ProviderIs("gke") { 88 ginkgo.By("waiting 5 minutes for all dead tunnels to be dropped") 89 time.Sleep(5 * time.Minute) 90 } 91 if err := framework.WaitForGroupSize(group, int32(framework.TestContext.CloudConfig.NumNodes)); err != nil { 92 framework.Failf("Couldn't restore the original node instance group size: %v", err) 93 } 94 95 if err := e2enode.WaitForReadyNodes(ctx, c, framework.TestContext.CloudConfig.NumNodes, 10*time.Minute); err != nil { 96 framework.Failf("Couldn't restore the original cluster size: %v", err) 97 } 98 // Many e2e tests assume that the cluster is fully healthy before they start. Wait until 99 // the cluster is restored to health. 100 ginkgo.By("waiting for system pods to successfully restart") 101 err := e2epod.WaitForPodsRunningReady(ctx, c, metav1.NamespaceSystem, systemPodsNo, framework.PodReadyBeforeTimeout) 102 framework.ExpectNoError(err) 103 }) 104 105 ginkgo.It("node lease should be deleted when corresponding node is deleted", func(ctx context.Context) { 106 leaseClient := c.CoordinationV1().Leases(v1.NamespaceNodeLease) 107 err := e2enode.WaitForReadyNodes(ctx, c, framework.TestContext.CloudConfig.NumNodes, 10*time.Minute) 108 framework.ExpectNoError(err) 109 110 ginkgo.By("verify node lease exists for every nodes") 111 originalNodes, err := e2enode.GetReadySchedulableNodes(ctx, c) 112 framework.ExpectNoError(err) 113 gomega.Expect(originalNodes.Items).To(gomega.HaveLen(framework.TestContext.CloudConfig.NumNodes)) 114 115 gomega.Eventually(ctx, func() error { 116 pass := true 117 for _, node := range originalNodes.Items { 118 if _, err := leaseClient.Get(ctx, node.ObjectMeta.Name, metav1.GetOptions{}); err != nil { 119 framework.Logf("Try to get lease of node %s, but got error: %v", node.ObjectMeta.Name, err) 120 pass = false 121 } 122 } 123 if pass { 124 return nil 125 } 126 return fmt.Errorf("some node lease is not ready") 127 }, 1*time.Minute, 5*time.Second).Should(gomega.BeNil()) 128 129 targetNumNodes := int32(framework.TestContext.CloudConfig.NumNodes - 1) 130 ginkgo.By(fmt.Sprintf("decreasing cluster size to %d", targetNumNodes)) 131 err = framework.ResizeGroup(group, targetNumNodes) 132 framework.ExpectNoError(err) 133 err = framework.WaitForGroupSize(group, targetNumNodes) 134 framework.ExpectNoError(err) 135 err = e2enode.WaitForReadyNodes(ctx, c, framework.TestContext.CloudConfig.NumNodes-1, 10*time.Minute) 136 framework.ExpectNoError(err) 137 targetNodes, err := e2enode.GetReadySchedulableNodes(ctx, c) 138 framework.ExpectNoError(err) 139 gomega.Expect(targetNodes.Items).To(gomega.HaveLen(int(targetNumNodes))) 140 141 ginkgo.By("verify node lease is deleted for the deleted node") 142 var deletedNodeName string 143 for _, originalNode := range originalNodes.Items { 144 originalNodeName := originalNode.ObjectMeta.Name 145 for _, targetNode := range targetNodes.Items { 146 if originalNodeName == targetNode.ObjectMeta.Name { 147 continue 148 } 149 } 150 deletedNodeName = originalNodeName 151 break 152 } 153 gomega.Expect(deletedNodeName).NotTo(gomega.BeEmpty()) 154 gomega.Eventually(ctx, func() error { 155 if _, err := leaseClient.Get(ctx, deletedNodeName, metav1.GetOptions{}); err == nil { 156 return fmt.Errorf("node lease is not deleted yet for node %q", deletedNodeName) 157 } 158 return nil 159 }, 1*time.Minute, 5*time.Second).Should(gomega.BeNil()) 160 161 ginkgo.By("verify node leases still exist for remaining nodes") 162 gomega.Eventually(ctx, func() error { 163 for _, node := range targetNodes.Items { 164 if _, err := leaseClient.Get(ctx, node.ObjectMeta.Name, metav1.GetOptions{}); err != nil { 165 return err 166 } 167 } 168 return nil 169 }, 1*time.Minute, 5*time.Second).Should(gomega.BeNil()) 170 }) 171 }) 172 })