k8s.io/kubernetes@v1.29.3/test/e2e/node/pod_gc.go (about) 1 /* 2 Copyright 2015 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 node 18 19 import ( 20 "context" 21 "fmt" 22 "time" 23 24 "github.com/onsi/ginkgo/v2" 25 26 v1 "k8s.io/api/core/v1" 27 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 28 "k8s.io/apimachinery/pkg/util/uuid" 29 "k8s.io/apimachinery/pkg/util/wait" 30 31 "k8s.io/kubernetes/test/e2e/feature" 32 "k8s.io/kubernetes/test/e2e/framework" 33 imageutils "k8s.io/kubernetes/test/utils/image" 34 admissionapi "k8s.io/pod-security-admission/api" 35 ) 36 37 // This test requires that --terminated-pod-gc-threshold=100 be set on the controller manager 38 // 39 // Slow by design (7 min) 40 var _ = SIGDescribe("Pod garbage collector", feature.PodGarbageCollector, framework.WithSlow(), func() { 41 f := framework.NewDefaultFramework("pod-garbage-collector") 42 f.NamespacePodSecurityLevel = admissionapi.LevelPrivileged 43 ginkgo.It("should handle the creation of 1000 pods", func(ctx context.Context) { 44 var count int 45 for count < 1000 { 46 pod, err := createTerminatingPod(ctx, f) 47 if err != nil { 48 framework.Failf("err creating pod: %v", err) 49 } 50 pod.ResourceVersion = "" 51 pod.Status.Phase = v1.PodFailed 52 _, err = f.ClientSet.CoreV1().Pods(f.Namespace.Name).UpdateStatus(ctx, pod, metav1.UpdateOptions{}) 53 if err != nil { 54 framework.Failf("err failing pod: %v", err) 55 } 56 57 count++ 58 if count%50 == 0 { 59 framework.Logf("count: %v", count) 60 } 61 } 62 63 framework.Logf("created: %v", count) 64 65 // The gc controller polls every 30s and fires off a goroutine per 66 // pod to terminate. 67 var err error 68 var pods *v1.PodList 69 timeout := 2 * time.Minute 70 gcThreshold := 100 71 72 ginkgo.By(fmt.Sprintf("Waiting for gc controller to gc all but %d pods", gcThreshold)) 73 pollErr := wait.Poll(1*time.Minute, timeout, func() (bool, error) { 74 pods, err = f.ClientSet.CoreV1().Pods(f.Namespace.Name).List(ctx, metav1.ListOptions{}) 75 if err != nil { 76 framework.Logf("Failed to list pod %v", err) 77 return false, nil 78 } 79 if len(pods.Items) != gcThreshold { 80 framework.Logf("Number of observed pods %v, waiting for %v", len(pods.Items), gcThreshold) 81 return false, nil 82 } 83 return true, nil 84 }) 85 if pollErr != nil { 86 framework.Failf("Failed to GC pods within %v, %v pods remaining, error: %v", timeout, len(pods.Items), err) 87 } 88 }) 89 }) 90 91 func createTerminatingPod(ctx context.Context, f *framework.Framework) (*v1.Pod, error) { 92 uuid := uuid.NewUUID() 93 pod := &v1.Pod{ 94 ObjectMeta: metav1.ObjectMeta{ 95 Name: string(uuid), 96 }, 97 Spec: v1.PodSpec{ 98 Containers: []v1.Container{ 99 { 100 Name: string(uuid), 101 Image: imageutils.GetE2EImage(imageutils.BusyBox), 102 }, 103 }, 104 SchedulerName: "please don't schedule my pods", 105 }, 106 } 107 return f.ClientSet.CoreV1().Pods(f.Namespace.Name).Create(ctx, pod, metav1.CreateOptions{}) 108 }