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