| 
									
										
										
										
											2015-09-22 06:51:27 +08:00
										 |  |  | /* | 
					
						
							| 
									
										
										
										
											2016-06-03 08:25:58 +08:00
										 |  |  | Copyright 2015 The Kubernetes Authors. | 
					
						
							| 
									
										
										
										
											2015-09-22 06:51:27 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | Licensed under the Apache License, Version 2.0 (the "License"); | 
					
						
							|  |  |  | you may not use this file except in compliance with the License. | 
					
						
							|  |  |  | You may obtain a copy of the License at | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     http://www.apache.org/licenses/LICENSE-2.0
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Unless required by applicable law or agreed to in writing, software | 
					
						
							|  |  |  | distributed under the License is distributed on an "AS IS" BASIS, | 
					
						
							|  |  |  | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
					
						
							|  |  |  | See the License for the specific language governing permissions and | 
					
						
							|  |  |  | limitations under the License. | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-07 06:43:57 +08:00
										 |  |  | package podgc | 
					
						
							| 
									
										
										
										
											2015-09-22 06:51:27 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							| 
									
										
										
										
											2020-02-08 10:16:47 +08:00
										 |  |  | 	"context" | 
					
						
							| 
									
										
										
										
											2015-09-22 06:51:27 +08:00
										 |  |  | 	"sort" | 
					
						
							|  |  |  | 	"sync" | 
					
						
							|  |  |  | 	"time" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-05 11:23:42 +08:00
										 |  |  | 	v1 "k8s.io/api/core/v1" | 
					
						
							| 
									
										
										
										
											2019-10-23 22:54:54 +08:00
										 |  |  | 	"k8s.io/apimachinery/pkg/api/errors" | 
					
						
							| 
									
										
										
										
											2017-01-22 11:36:02 +08:00
										 |  |  | 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | 
					
						
							| 
									
										
										
										
											2017-01-11 22:09:48 +08:00
										 |  |  | 	"k8s.io/apimachinery/pkg/labels" | 
					
						
							|  |  |  | 	utilruntime "k8s.io/apimachinery/pkg/util/runtime" | 
					
						
							|  |  |  | 	"k8s.io/apimachinery/pkg/util/sets" | 
					
						
							|  |  |  | 	"k8s.io/apimachinery/pkg/util/wait" | 
					
						
							| 
									
										
										
										
											2022-03-27 00:23:21 +08:00
										 |  |  | 	utilfeature "k8s.io/apiserver/pkg/util/feature" | 
					
						
							| 
									
										
										
										
											2017-06-24 04:56:37 +08:00
										 |  |  | 	coreinformers "k8s.io/client-go/informers/core/v1" | 
					
						
							|  |  |  | 	clientset "k8s.io/client-go/kubernetes" | 
					
						
							|  |  |  | 	corelisters "k8s.io/client-go/listers/core/v1" | 
					
						
							| 
									
										
										
										
											2017-01-24 22:11:51 +08:00
										 |  |  | 	"k8s.io/client-go/tools/cache" | 
					
						
							| 
									
										
										
										
											2019-10-23 22:54:54 +08:00
										 |  |  | 	"k8s.io/client-go/util/workqueue" | 
					
						
							| 
									
										
										
										
											2020-04-18 03:25:06 +08:00
										 |  |  | 	"k8s.io/klog/v2" | 
					
						
							| 
									
										
										
										
											2022-08-02 13:58:08 +08:00
										 |  |  | 	apipod "k8s.io/kubernetes/pkg/api/v1/pod" | 
					
						
							| 
									
										
										
										
											2022-03-27 00:23:21 +08:00
										 |  |  | 	"k8s.io/kubernetes/pkg/features" | 
					
						
							|  |  |  | 	nodeutil "k8s.io/kubernetes/pkg/util/node" | 
					
						
							| 
									
										
										
										
											2022-08-02 13:58:08 +08:00
										 |  |  | 	utilpod "k8s.io/kubernetes/pkg/util/pod" | 
					
						
							| 
									
										
										
										
											2022-03-27 00:23:21 +08:00
										 |  |  | 	"k8s.io/kubernetes/pkg/util/taints" | 
					
						
							| 
									
										
										
										
											2015-09-22 06:51:27 +08:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const ( | 
					
						
							| 
									
										
										
										
											2019-10-23 22:54:54 +08:00
										 |  |  | 	// gcCheckPeriod defines frequency of running main controller loop
 | 
					
						
							| 
									
										
										
										
											2015-10-06 17:12:00 +08:00
										 |  |  | 	gcCheckPeriod = 20 * time.Second | 
					
						
							| 
									
										
										
										
											2019-10-23 22:54:54 +08:00
										 |  |  | 	// quarantineTime defines how long Orphaned GC waits for nodes to show up
 | 
					
						
							|  |  |  | 	// in an informer before issuing a GET call to check if they are truly gone
 | 
					
						
							|  |  |  | 	quarantineTime = 40 * time.Second | 
					
						
							| 
									
										
										
										
											2015-09-22 06:51:27 +08:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-07 06:43:57 +08:00
										 |  |  | type PodGCController struct { | 
					
						
							| 
									
										
										
										
											2016-09-12 22:47:17 +08:00
										 |  |  | 	kubeClient clientset.Interface | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-23 22:54:54 +08:00
										 |  |  | 	podLister        corelisters.PodLister | 
					
						
							|  |  |  | 	podListerSynced  cache.InformerSynced | 
					
						
							|  |  |  | 	nodeLister       corelisters.NodeLister | 
					
						
							|  |  |  | 	nodeListerSynced cache.InformerSynced | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	nodeQueue workqueue.DelayingInterface | 
					
						
							| 
									
										
										
										
											2016-09-12 22:47:17 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	terminatedPodThreshold int | 
					
						
							| 
									
										
										
										
											2022-07-15 17:51:50 +08:00
										 |  |  | 	gcCheckPeriod          time.Duration | 
					
						
							|  |  |  | 	quarantineTime         time.Duration | 
					
						
							| 
									
										
										
										
											2015-09-22 06:51:27 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-23 02:27:59 +08:00
										 |  |  | func NewPodGC(ctx context.Context, kubeClient clientset.Interface, podInformer coreinformers.PodInformer, | 
					
						
							| 
									
										
										
										
											2019-10-23 22:54:54 +08:00
										 |  |  | 	nodeInformer coreinformers.NodeInformer, terminatedPodThreshold int) *PodGCController { | 
					
						
							| 
									
										
										
										
											2022-07-15 17:51:50 +08:00
										 |  |  | 	return NewPodGCInternal(ctx, kubeClient, podInformer, nodeInformer, terminatedPodThreshold, gcCheckPeriod, quarantineTime) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // This function is only intended for integration tests
 | 
					
						
							|  |  |  | func NewPodGCInternal(ctx context.Context, kubeClient clientset.Interface, podInformer coreinformers.PodInformer, | 
					
						
							|  |  |  | 	nodeInformer coreinformers.NodeInformer, terminatedPodThreshold int, gcCheckPeriod, quarantineTime time.Duration) *PodGCController { | 
					
						
							| 
									
										
										
										
											2016-06-07 06:43:57 +08:00
										 |  |  | 	gcc := &PodGCController{ | 
					
						
							| 
									
										
										
										
											2016-09-12 22:47:17 +08:00
										 |  |  | 		kubeClient:             kubeClient, | 
					
						
							|  |  |  | 		terminatedPodThreshold: terminatedPodThreshold, | 
					
						
							| 
									
										
										
										
											2019-10-23 22:54:54 +08:00
										 |  |  | 		podLister:              podInformer.Lister(), | 
					
						
							|  |  |  | 		podListerSynced:        podInformer.Informer().HasSynced, | 
					
						
							|  |  |  | 		nodeLister:             nodeInformer.Lister(), | 
					
						
							|  |  |  | 		nodeListerSynced:       nodeInformer.Informer().HasSynced, | 
					
						
							|  |  |  | 		nodeQueue:              workqueue.NewNamedDelayingQueue("orphaned_pods_nodes"), | 
					
						
							| 
									
										
										
										
											2022-07-15 17:51:50 +08:00
										 |  |  | 		gcCheckPeriod:          gcCheckPeriod, | 
					
						
							|  |  |  | 		quarantineTime:         quarantineTime, | 
					
						
							| 
									
										
										
										
											2015-09-22 06:51:27 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return gcc | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-23 02:27:59 +08:00
										 |  |  | func (gcc *PodGCController) Run(ctx context.Context) { | 
					
						
							| 
									
										
										
										
											2017-04-13 03:49:17 +08:00
										 |  |  | 	defer utilruntime.HandleCrash() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-10 02:49:10 +08:00
										 |  |  | 	klog.Infof("Starting GC controller") | 
					
						
							| 
									
										
										
										
											2019-10-23 22:54:54 +08:00
										 |  |  | 	defer gcc.nodeQueue.ShutDown() | 
					
						
							| 
									
										
										
										
											2018-11-10 02:49:10 +08:00
										 |  |  | 	defer klog.Infof("Shutting down GC controller") | 
					
						
							| 
									
										
										
										
											2017-04-13 03:49:17 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-23 02:27:59 +08:00
										 |  |  | 	if !cache.WaitForNamedCacheSync("GC", ctx.Done(), gcc.podListerSynced, gcc.nodeListerSynced) { | 
					
						
							| 
									
										
										
										
											2017-02-07 02:35:50 +08:00
										 |  |  | 		return | 
					
						
							| 
									
										
										
										
											2016-09-12 22:47:17 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-02-07 02:35:50 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-15 17:51:50 +08:00
										 |  |  | 	go wait.UntilWithContext(ctx, gcc.gc, gcc.gcCheckPeriod) | 
					
						
							| 
									
										
										
										
											2017-04-13 03:49:17 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-23 02:27:59 +08:00
										 |  |  | 	<-ctx.Done() | 
					
						
							| 
									
										
										
										
											2015-09-22 06:51:27 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-23 02:27:59 +08:00
										 |  |  | func (gcc *PodGCController) gc(ctx context.Context) { | 
					
						
							| 
									
										
										
										
											2017-02-07 02:35:50 +08:00
										 |  |  | 	pods, err := gcc.podLister.List(labels.Everything()) | 
					
						
							| 
									
										
										
										
											2016-09-12 22:47:17 +08:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2019-10-23 22:54:54 +08:00
										 |  |  | 		klog.Errorf("Error while listing all pods: %v", err) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	nodes, err := gcc.nodeLister.List(labels.Everything()) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		klog.Errorf("Error while listing all nodes: %v", err) | 
					
						
							| 
									
										
										
										
											2016-09-12 22:47:17 +08:00
										 |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if gcc.terminatedPodThreshold > 0 { | 
					
						
							| 
									
										
										
										
											2022-07-11 23:43:40 +08:00
										 |  |  | 		gcc.gcTerminated(ctx, pods) | 
					
						
							| 
									
										
										
										
											2016-09-12 22:47:17 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-03-27 00:23:21 +08:00
										 |  |  | 	if utilfeature.DefaultFeatureGate.Enabled(features.NodeOutOfServiceVolumeDetach) { | 
					
						
							| 
									
										
										
										
											2022-07-11 23:43:40 +08:00
										 |  |  | 		gcc.gcTerminating(ctx, pods) | 
					
						
							| 
									
										
										
										
											2022-03-27 00:23:21 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-04-23 02:27:59 +08:00
										 |  |  | 	gcc.gcOrphaned(ctx, pods, nodes) | 
					
						
							| 
									
										
										
										
											2022-07-11 23:43:40 +08:00
										 |  |  | 	gcc.gcUnscheduledTerminating(ctx, pods) | 
					
						
							| 
									
										
										
										
											2016-09-12 22:47:17 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-19 04:50:17 +08:00
										 |  |  | func isPodTerminated(pod *v1.Pod) bool { | 
					
						
							|  |  |  | 	if phase := pod.Status.Phase; phase != v1.PodPending && phase != v1.PodRunning && phase != v1.PodUnknown { | 
					
						
							| 
									
										
										
										
											2016-09-12 22:47:17 +08:00
										 |  |  | 		return true | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return false | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-27 00:23:21 +08:00
										 |  |  | // isPodTerminating returns true if the pod is terminating.
 | 
					
						
							|  |  |  | func isPodTerminating(pod *v1.Pod) bool { | 
					
						
							|  |  |  | 	return pod.ObjectMeta.DeletionTimestamp != nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-11 23:43:40 +08:00
										 |  |  | func (gcc *PodGCController) gcTerminating(ctx context.Context, pods []*v1.Pod) { | 
					
						
							| 
									
										
										
										
											2022-03-27 00:23:21 +08:00
										 |  |  | 	klog.V(4).Info("GC'ing terminating pods that are on out-of-service nodes") | 
					
						
							|  |  |  | 	terminatingPods := []*v1.Pod{} | 
					
						
							|  |  |  | 	for _, pod := range pods { | 
					
						
							|  |  |  | 		if isPodTerminating(pod) { | 
					
						
							|  |  |  | 			node, err := gcc.nodeLister.Get(string(pod.Spec.NodeName)) | 
					
						
							|  |  |  | 			if err != nil { | 
					
						
							|  |  |  | 				klog.Errorf("failed to get node %s : %s", string(pod.Spec.NodeName), err) | 
					
						
							|  |  |  | 				continue | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			// Add this pod to terminatingPods list only if the following conditions are met:
 | 
					
						
							|  |  |  | 			// 1. Node is not ready.
 | 
					
						
							|  |  |  | 			// 2. Node has `node.kubernetes.io/out-of-service` taint.
 | 
					
						
							|  |  |  | 			if !nodeutil.IsNodeReady(node) && taints.TaintKeyExists(node.Spec.Taints, v1.TaintNodeOutOfService) { | 
					
						
							|  |  |  | 				klog.V(4).Infof("garbage collecting pod %s that is terminating. Phase [%v]", pod.Name, pod.Status.Phase) | 
					
						
							|  |  |  | 				terminatingPods = append(terminatingPods, pod) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	deleteCount := len(terminatingPods) | 
					
						
							|  |  |  | 	if deleteCount == 0 { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	klog.V(4).Infof("Garbage collecting %v pods that are terminating on node tainted with node.kubernetes.io/out-of-service", deleteCount) | 
					
						
							|  |  |  | 	// sort only when necessary
 | 
					
						
							|  |  |  | 	sort.Sort(byCreationTimestamp(terminatingPods)) | 
					
						
							|  |  |  | 	var wait sync.WaitGroup | 
					
						
							|  |  |  | 	for i := 0; i < deleteCount; i++ { | 
					
						
							|  |  |  | 		wait.Add(1) | 
					
						
							| 
									
										
										
										
											2022-08-02 13:58:08 +08:00
										 |  |  | 		go func(pod *v1.Pod) { | 
					
						
							| 
									
										
										
										
											2022-03-27 00:23:21 +08:00
										 |  |  | 			defer wait.Done() | 
					
						
							| 
									
										
										
										
											2022-08-02 13:58:08 +08:00
										 |  |  | 			if err := gcc.markFailedAndDeletePod(ctx, pod); err != nil { | 
					
						
							| 
									
										
										
										
											2022-03-27 00:23:21 +08:00
										 |  |  | 				// ignore not founds
 | 
					
						
							|  |  |  | 				utilruntime.HandleError(err) | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2022-08-02 13:58:08 +08:00
										 |  |  | 		}(terminatingPods[i]) | 
					
						
							| 
									
										
										
										
											2022-03-27 00:23:21 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	wait.Wait() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-11 23:43:40 +08:00
										 |  |  | func (gcc *PodGCController) gcTerminated(ctx context.Context, pods []*v1.Pod) { | 
					
						
							| 
									
										
										
										
											2016-11-19 04:50:17 +08:00
										 |  |  | 	terminatedPods := []*v1.Pod{} | 
					
						
							| 
									
										
										
										
											2016-09-12 22:47:17 +08:00
										 |  |  | 	for _, pod := range pods { | 
					
						
							|  |  |  | 		if isPodTerminated(pod) { | 
					
						
							|  |  |  | 			terminatedPods = append(terminatedPods, pod) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-22 06:51:27 +08:00
										 |  |  | 	terminatedPodCount := len(terminatedPods) | 
					
						
							| 
									
										
										
										
											2016-09-12 22:47:17 +08:00
										 |  |  | 	deleteCount := terminatedPodCount - gcc.terminatedPodThreshold | 
					
						
							| 
									
										
										
										
											2015-09-22 06:51:27 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-23 22:54:54 +08:00
										 |  |  | 	if deleteCount <= 0 { | 
					
						
							| 
									
										
										
										
											2019-09-05 11:23:42 +08:00
										 |  |  | 		return | 
					
						
							| 
									
										
										
										
											2015-09-22 06:51:27 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-30 21:29:52 +08:00
										 |  |  | 	klog.InfoS("Garbage collecting pods", "numPods", deleteCount) | 
					
						
							| 
									
										
										
										
											2019-09-05 11:23:42 +08:00
										 |  |  | 	// sort only when necessary
 | 
					
						
							|  |  |  | 	sort.Sort(byCreationTimestamp(terminatedPods)) | 
					
						
							| 
									
										
										
										
											2015-09-22 06:51:27 +08:00
										 |  |  | 	var wait sync.WaitGroup | 
					
						
							|  |  |  | 	for i := 0; i < deleteCount; i++ { | 
					
						
							|  |  |  | 		wait.Add(1) | 
					
						
							| 
									
										
										
										
											2022-08-02 13:58:08 +08:00
										 |  |  | 		go func(pod *v1.Pod) { | 
					
						
							| 
									
										
										
										
											2015-09-22 06:51:27 +08:00
										 |  |  | 			defer wait.Done() | 
					
						
							| 
									
										
										
										
											2022-08-02 13:58:08 +08:00
										 |  |  | 			if err := gcc.markFailedAndDeletePod(ctx, pod); err != nil { | 
					
						
							| 
									
										
										
										
											2015-09-22 06:51:27 +08:00
										 |  |  | 				// ignore not founds
 | 
					
						
							| 
									
										
										
										
											2016-01-15 15:32:10 +08:00
										 |  |  | 				defer utilruntime.HandleError(err) | 
					
						
							| 
									
										
										
										
											2015-09-22 06:51:27 +08:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2022-08-02 13:58:08 +08:00
										 |  |  | 		}(terminatedPods[i]) | 
					
						
							| 
									
										
										
										
											2015-09-22 06:51:27 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	wait.Wait() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-26 02:18:58 +08:00
										 |  |  | // gcOrphaned deletes pods that are bound to nodes that don't exist.
 | 
					
						
							| 
									
										
										
										
											2021-04-23 02:27:59 +08:00
										 |  |  | func (gcc *PodGCController) gcOrphaned(ctx context.Context, pods []*v1.Pod, nodes []*v1.Node) { | 
					
						
							| 
									
										
										
										
											2018-11-10 02:49:10 +08:00
										 |  |  | 	klog.V(4).Infof("GC'ing orphaned") | 
					
						
							| 
									
										
										
										
											2019-10-23 22:54:54 +08:00
										 |  |  | 	existingNodeNames := sets.NewString() | 
					
						
							|  |  |  | 	for _, node := range nodes { | 
					
						
							|  |  |  | 		existingNodeNames.Insert(node.Name) | 
					
						
							| 
									
										
										
										
											2016-11-23 17:33:52 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-10-23 22:54:54 +08:00
										 |  |  | 	// Add newly found unknown nodes to quarantine
 | 
					
						
							| 
									
										
										
										
											2016-09-12 22:47:17 +08:00
										 |  |  | 	for _, pod := range pods { | 
					
						
							| 
									
										
										
										
											2019-10-23 22:54:54 +08:00
										 |  |  | 		if pod.Spec.NodeName != "" && !existingNodeNames.Has(pod.Spec.NodeName) { | 
					
						
							| 
									
										
										
										
											2022-07-15 17:51:50 +08:00
										 |  |  | 			gcc.nodeQueue.AddAfter(pod.Spec.NodeName, gcc.quarantineTime) | 
					
						
							| 
									
										
										
										
											2016-09-12 22:47:17 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-10-23 22:54:54 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	// Check if nodes are still missing after quarantine period
 | 
					
						
							| 
									
										
										
										
											2021-04-23 02:27:59 +08:00
										 |  |  | 	deletedNodesNames, quit := gcc.discoverDeletedNodes(ctx, existingNodeNames) | 
					
						
							| 
									
										
										
										
											2019-10-23 22:54:54 +08:00
										 |  |  | 	if quit { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// Delete orphaned pods
 | 
					
						
							|  |  |  | 	for _, pod := range pods { | 
					
						
							|  |  |  | 		if !deletedNodesNames.Has(pod.Spec.NodeName) { | 
					
						
							| 
									
										
										
										
											2016-09-12 22:47:17 +08:00
										 |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2021-03-30 21:29:52 +08:00
										 |  |  | 		klog.V(2).InfoS("Found orphaned Pod assigned to the Node, deleting.", "pod", klog.KObj(pod), "node", pod.Spec.NodeName) | 
					
						
							| 
									
										
										
										
											2022-08-02 13:58:08 +08:00
										 |  |  | 		condition := &v1.PodCondition{ | 
					
						
							|  |  |  | 			Type:    v1.AlphaNoCompatGuaranteeDisruptionTarget, | 
					
						
							|  |  |  | 			Status:  v1.ConditionTrue, | 
					
						
							|  |  |  | 			Reason:  "DeletionByPodGC", | 
					
						
							|  |  |  | 			Message: "PodGC: node no longer exists", | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if err := gcc.markFailedAndDeletePodWithCondition(ctx, pod, condition); err != nil { | 
					
						
							| 
									
										
										
										
											2016-09-12 22:47:17 +08:00
										 |  |  | 			utilruntime.HandleError(err) | 
					
						
							|  |  |  | 		} else { | 
					
						
							| 
									
										
										
										
											2022-08-05 09:44:34 +08:00
										 |  |  | 			klog.InfoS("Forced deletion of orphaned Pod succeeded", "pod", klog.KObj(pod)) | 
					
						
							| 
									
										
										
										
											2016-10-26 02:18:58 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-23 02:27:59 +08:00
										 |  |  | func (gcc *PodGCController) discoverDeletedNodes(ctx context.Context, existingNodeNames sets.String) (sets.String, bool) { | 
					
						
							| 
									
										
										
										
											2019-10-23 22:54:54 +08:00
										 |  |  | 	deletedNodesNames := sets.NewString() | 
					
						
							|  |  |  | 	for gcc.nodeQueue.Len() > 0 { | 
					
						
							|  |  |  | 		item, quit := gcc.nodeQueue.Get() | 
					
						
							|  |  |  | 		if quit { | 
					
						
							|  |  |  | 			return nil, true | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		nodeName := item.(string) | 
					
						
							|  |  |  | 		if !existingNodeNames.Has(nodeName) { | 
					
						
							| 
									
										
										
										
											2021-04-23 02:27:59 +08:00
										 |  |  | 			exists, err := gcc.checkIfNodeExists(ctx, nodeName) | 
					
						
							| 
									
										
										
										
											2019-10-23 22:54:54 +08:00
										 |  |  | 			switch { | 
					
						
							|  |  |  | 			case err != nil: | 
					
						
							| 
									
										
										
										
											2021-05-29 17:20:19 +08:00
										 |  |  | 				klog.ErrorS(err, "Error while getting node", "node", klog.KRef("", nodeName)) | 
					
						
							| 
									
										
										
										
											2019-10-23 22:54:54 +08:00
										 |  |  | 				// Node will be added back to the queue in the subsequent loop if still needed
 | 
					
						
							|  |  |  | 			case !exists: | 
					
						
							|  |  |  | 				deletedNodesNames.Insert(nodeName) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		gcc.nodeQueue.Done(item) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return deletedNodesNames, false | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-23 02:27:59 +08:00
										 |  |  | func (gcc *PodGCController) checkIfNodeExists(ctx context.Context, name string) (bool, error) { | 
					
						
							|  |  |  | 	_, fetchErr := gcc.kubeClient.CoreV1().Nodes().Get(ctx, name, metav1.GetOptions{}) | 
					
						
							| 
									
										
										
										
											2019-10-23 22:54:54 +08:00
										 |  |  | 	if errors.IsNotFound(fetchErr) { | 
					
						
							|  |  |  | 		return false, nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return fetchErr == nil, fetchErr | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-26 02:18:58 +08:00
										 |  |  | // gcUnscheduledTerminating deletes pods that are terminating and haven't been scheduled to a particular node.
 | 
					
						
							| 
									
										
										
										
											2022-07-11 23:43:40 +08:00
										 |  |  | func (gcc *PodGCController) gcUnscheduledTerminating(ctx context.Context, pods []*v1.Pod) { | 
					
						
							| 
									
										
										
										
											2018-11-10 02:49:10 +08:00
										 |  |  | 	klog.V(4).Infof("GC'ing unscheduled pods which are terminating.") | 
					
						
							| 
									
										
										
										
											2016-10-26 02:18:58 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	for _, pod := range pods { | 
					
						
							| 
									
										
										
										
											2016-10-28 04:30:04 +08:00
										 |  |  | 		if pod.DeletionTimestamp == nil || len(pod.Spec.NodeName) > 0 { | 
					
						
							| 
									
										
										
										
											2016-10-26 02:18:58 +08:00
										 |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-30 21:29:52 +08:00
										 |  |  | 		klog.V(2).InfoS("Found unscheduled terminating Pod not assigned to any Node, deleting.", "pod", klog.KObj(pod)) | 
					
						
							| 
									
										
										
										
											2022-08-02 13:58:08 +08:00
										 |  |  | 		if err := gcc.markFailedAndDeletePod(ctx, pod); err != nil { | 
					
						
							| 
									
										
										
										
											2016-10-26 02:18:58 +08:00
										 |  |  | 			utilruntime.HandleError(err) | 
					
						
							|  |  |  | 		} else { | 
					
						
							| 
									
										
										
										
											2022-08-05 09:44:34 +08:00
										 |  |  | 			klog.InfoS("Forced deletion of unscheduled terminating Pod succeeded", "pod", klog.KObj(pod)) | 
					
						
							| 
									
										
										
										
											2016-09-12 22:47:17 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-22 06:51:27 +08:00
										 |  |  | // byCreationTimestamp sorts a list by creation timestamp, using their names as a tie breaker.
 | 
					
						
							| 
									
										
										
										
											2016-11-19 04:50:17 +08:00
										 |  |  | type byCreationTimestamp []*v1.Pod | 
					
						
							| 
									
										
										
										
											2015-09-22 06:51:27 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | func (o byCreationTimestamp) Len() int      { return len(o) } | 
					
						
							|  |  |  | func (o byCreationTimestamp) Swap(i, j int) { o[i], o[j] = o[j], o[i] } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (o byCreationTimestamp) Less(i, j int) bool { | 
					
						
							| 
									
										
										
										
											2017-08-04 23:04:14 +08:00
										 |  |  | 	if o[i].CreationTimestamp.Equal(&o[j].CreationTimestamp) { | 
					
						
							| 
									
										
										
										
											2015-09-22 06:51:27 +08:00
										 |  |  | 		return o[i].Name < o[j].Name | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-08-04 23:04:14 +08:00
										 |  |  | 	return o[i].CreationTimestamp.Before(&o[j].CreationTimestamp) | 
					
						
							| 
									
										
										
										
											2015-09-22 06:51:27 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2022-07-12 16:16:00 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-02 13:58:08 +08:00
										 |  |  | func (gcc *PodGCController) markFailedAndDeletePod(ctx context.Context, pod *v1.Pod) error { | 
					
						
							|  |  |  | 	return gcc.markFailedAndDeletePodWithCondition(ctx, pod, nil) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (gcc *PodGCController) markFailedAndDeletePodWithCondition(ctx context.Context, pod *v1.Pod, condition *v1.PodCondition) error { | 
					
						
							|  |  |  | 	klog.InfoS("PodGC is force deleting Pod", "pod", klog.KRef(pod.Namespace, pod.Name)) | 
					
						
							|  |  |  | 	if utilfeature.DefaultFeatureGate.Enabled(features.PodDisruptionConditions) { | 
					
						
							|  |  |  | 		newStatus := pod.Status.DeepCopy() | 
					
						
							|  |  |  | 		updated := false | 
					
						
							|  |  |  | 		if condition != nil { | 
					
						
							|  |  |  | 			updated = apipod.UpdatePodCondition(newStatus, condition) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		// Mark the pod as failed - this is especially important in case the pod
 | 
					
						
							|  |  |  | 		// is orphaned, in which case the pod would remain in the Running phase
 | 
					
						
							|  |  |  | 		// forever as there is no kubelet running to change the phase.
 | 
					
						
							|  |  |  | 		if pod.Status.Phase != v1.PodSucceeded && pod.Status.Phase != v1.PodFailed { | 
					
						
							|  |  |  | 			newStatus.Phase = v1.PodFailed | 
					
						
							|  |  |  | 			updated = true | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if updated { | 
					
						
							|  |  |  | 			if _, _, _, err := utilpod.PatchPodStatus(ctx, gcc.kubeClient, pod.Namespace, pod.Name, pod.UID, pod.Status, *newStatus); err != nil { | 
					
						
							|  |  |  | 				return err | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return gcc.kubeClient.CoreV1().Pods(pod.Namespace).Delete(ctx, pod.Name, *metav1.NewDeleteOptions(0)) | 
					
						
							| 
									
										
										
										
											2022-07-12 16:16:00 +08:00
										 |  |  | } |