volcano.sh/volcano@v1.9.0/pkg/controllers/podgroup/pg_controller.go (about) 1 /* 2 Copyright 2019 The Volcano 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 podgroup 18 19 import ( 20 "k8s.io/apimachinery/pkg/util/wait" 21 utilfeature "k8s.io/apiserver/pkg/util/feature" 22 "k8s.io/client-go/informers" 23 appinformers "k8s.io/client-go/informers/apps/v1" 24 coreinformers "k8s.io/client-go/informers/core/v1" 25 "k8s.io/client-go/kubernetes" 26 corelisters "k8s.io/client-go/listers/core/v1" 27 "k8s.io/client-go/tools/cache" 28 "k8s.io/client-go/util/workqueue" 29 "k8s.io/klog/v2" 30 31 scheduling "volcano.sh/apis/pkg/apis/scheduling/v1beta1" 32 vcclientset "volcano.sh/apis/pkg/client/clientset/versioned" 33 informerfactory "volcano.sh/apis/pkg/client/informers/externalversions" 34 vcinformer "volcano.sh/apis/pkg/client/informers/externalversions" 35 schedulinginformer "volcano.sh/apis/pkg/client/informers/externalversions/scheduling/v1beta1" 36 schedulinglister "volcano.sh/apis/pkg/client/listers/scheduling/v1beta1" 37 "volcano.sh/volcano/pkg/controllers/framework" 38 "volcano.sh/volcano/pkg/features" 39 commonutil "volcano.sh/volcano/pkg/util" 40 ) 41 42 func init() { 43 framework.RegisterController(&pgcontroller{}) 44 } 45 46 // pgcontroller the Podgroup pgcontroller type. 47 type pgcontroller struct { 48 kubeClient kubernetes.Interface 49 vcClient vcclientset.Interface 50 51 podInformer coreinformers.PodInformer 52 pgInformer schedulinginformer.PodGroupInformer 53 rsInformer appinformers.ReplicaSetInformer 54 55 informerFactory informers.SharedInformerFactory 56 vcInformerFactory vcinformer.SharedInformerFactory 57 58 // A store of pods 59 podLister corelisters.PodLister 60 podSynced func() bool 61 62 // A store of podgroups 63 pgLister schedulinglister.PodGroupLister 64 pgSynced func() bool 65 66 // A store of replicaset 67 rsSynced func() bool 68 69 queue workqueue.RateLimitingInterface 70 71 schedulerNames []string 72 workers uint32 73 74 // To determine whether inherit owner's annotations for pods when create podgroup 75 inheritOwnerAnnotations bool 76 } 77 78 func (pg *pgcontroller) Name() string { 79 return "pg-controller" 80 } 81 82 // Initialize create new Podgroup Controller. 83 func (pg *pgcontroller) Initialize(opt *framework.ControllerOption) error { 84 pg.kubeClient = opt.KubeClient 85 pg.vcClient = opt.VolcanoClient 86 pg.workers = opt.WorkerThreadsForPG 87 88 pg.queue = workqueue.NewRateLimitingQueue(workqueue.DefaultControllerRateLimiter()) 89 90 pg.schedulerNames = make([]string, len(opt.SchedulerNames)) 91 copy(pg.schedulerNames, opt.SchedulerNames) 92 pg.inheritOwnerAnnotations = opt.InheritOwnerAnnotations 93 94 pg.informerFactory = opt.SharedInformerFactory 95 pg.podInformer = opt.SharedInformerFactory.Core().V1().Pods() 96 pg.podLister = pg.podInformer.Lister() 97 pg.podSynced = pg.podInformer.Informer().HasSynced 98 pg.podInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ 99 AddFunc: pg.addPod, 100 }) 101 102 factory := informerfactory.NewSharedInformerFactory(pg.vcClient, 0) 103 pg.vcInformerFactory = factory 104 pg.pgInformer = factory.Scheduling().V1beta1().PodGroups() 105 pg.pgLister = pg.pgInformer.Lister() 106 pg.pgSynced = pg.pgInformer.Informer().HasSynced 107 108 if utilfeature.DefaultFeatureGate.Enabled(features.WorkLoadSupport) { 109 pg.rsInformer = pg.informerFactory.Apps().V1().ReplicaSets() 110 pg.rsSynced = pg.rsInformer.Informer().HasSynced 111 pg.rsInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ 112 AddFunc: pg.addReplicaSet, 113 UpdateFunc: pg.updateReplicaSet, 114 }) 115 } 116 return nil 117 } 118 119 // Run start NewPodgroupController. 120 func (pg *pgcontroller) Run(stopCh <-chan struct{}) { 121 pg.informerFactory.Start(stopCh) 122 pg.vcInformerFactory.Start(stopCh) 123 124 for informerType, ok := range pg.informerFactory.WaitForCacheSync(stopCh) { 125 if !ok { 126 klog.Errorf("caches failed to sync: %v", informerType) 127 } 128 } 129 for informerType, ok := range pg.vcInformerFactory.WaitForCacheSync(stopCh) { 130 if !ok { 131 klog.Errorf("caches failed to sync: %v", informerType) 132 return 133 } 134 } 135 136 for i := 0; i < int(pg.workers); i++ { 137 go wait.Until(pg.worker, 0, stopCh) 138 } 139 140 klog.Infof("PodgroupController is running ...... ") 141 } 142 143 func (pg *pgcontroller) worker() { 144 for pg.processNextReq() { 145 } 146 } 147 148 func (pg *pgcontroller) processNextReq() bool { 149 obj, shutdown := pg.queue.Get() 150 if shutdown { 151 klog.Errorf("Fail to pop item from queue") 152 return false 153 } 154 155 req := obj.(podRequest) 156 defer pg.queue.Done(req) 157 158 pod, err := pg.podLister.Pods(req.podNamespace).Get(req.podName) 159 if err != nil { 160 klog.Errorf("Failed to get pod by <%v> from cache: %v", req, err) 161 return true 162 } 163 164 if !commonutil.Contains(pg.schedulerNames, pod.Spec.SchedulerName) { 165 klog.V(5).Infof("pod %v/%v field SchedulerName is not matched", pod.Namespace, pod.Name) 166 return true 167 } 168 169 if pod.Annotations != nil && pod.Annotations[scheduling.KubeGroupNameAnnotationKey] != "" { 170 klog.V(5).Infof("pod %v/%v has created podgroup", pod.Namespace, pod.Name) 171 return true 172 } 173 174 // normal pod use volcano 175 if err := pg.createNormalPodPGIfNotExist(pod); err != nil { 176 klog.Errorf("Failed to handle Pod <%s/%s>: %v", pod.Namespace, pod.Name, err) 177 pg.queue.AddRateLimited(req) 178 return true 179 } 180 181 // If no error, forget it. 182 pg.queue.Forget(req) 183 184 return true 185 }