volcano.sh/volcano@v1.9.0/pkg/scheduler/plugins/predicates/predicates.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 predicates 18 19 import ( 20 "context" 21 "fmt" 22 "strings" 23 24 v1 "k8s.io/api/core/v1" 25 "k8s.io/apimachinery/pkg/util/sets" 26 utilFeature "k8s.io/apiserver/pkg/util/feature" 27 "k8s.io/klog/v2" 28 "k8s.io/kubernetes/pkg/features" 29 "k8s.io/kubernetes/pkg/scheduler/apis/config" 30 k8sframework "k8s.io/kubernetes/pkg/scheduler/framework" 31 "k8s.io/kubernetes/pkg/scheduler/framework/plugins/feature" 32 "k8s.io/kubernetes/pkg/scheduler/framework/plugins/interpodaffinity" 33 "k8s.io/kubernetes/pkg/scheduler/framework/plugins/nodeaffinity" 34 "k8s.io/kubernetes/pkg/scheduler/framework/plugins/nodeports" 35 "k8s.io/kubernetes/pkg/scheduler/framework/plugins/nodeunschedulable" 36 "k8s.io/kubernetes/pkg/scheduler/framework/plugins/nodevolumelimits" 37 "k8s.io/kubernetes/pkg/scheduler/framework/plugins/podtopologyspread" 38 "k8s.io/kubernetes/pkg/scheduler/framework/plugins/tainttoleration" 39 "k8s.io/kubernetes/pkg/scheduler/framework/plugins/volumezone" 40 41 "volcano.sh/volcano/pkg/scheduler/api" 42 "volcano.sh/volcano/pkg/scheduler/framework" 43 "volcano.sh/volcano/pkg/scheduler/plugins/util/k8s" 44 ) 45 46 const ( 47 // PluginName indicates name of volcano scheduler plugin. 48 PluginName = "predicates" 49 50 // NodeAffinityEnable is the key for enabling Node Affinity Predicates in scheduler configmap 51 NodeAffinityEnable = "predicate.NodeAffinityEnable" 52 53 // NodePortsEnable is the key for enabling Node Port Predicates in scheduler configmap 54 NodePortsEnable = "predicate.NodePortsEnable" 55 56 // TaintTolerationEnable is the key for enabling Taint Toleration Predicates in scheduler configmap 57 TaintTolerationEnable = "predicate.TaintTolerationEnable" 58 59 // PodAffinityEnable is the key for enabling Pod Affinity Predicates in scheduler configmap 60 PodAffinityEnable = "predicate.PodAffinityEnable" 61 62 // NodeVolumeLimitsEnable is the key for enabling Node Volume Limits Predicates in scheduler configmap 63 NodeVolumeLimitsEnable = "predicate.NodeVolumeLimitsEnable" 64 65 // VolumeZoneEnable is the key for enabling Volume Zone Predicates in scheduler configmap 66 VolumeZoneEnable = "predicate.VolumeZoneEnable" 67 68 // PodTopologySpreadEnable is the key for enabling Pod Topology Spread Predicates in scheduler configmap 69 PodTopologySpreadEnable = "predicate.PodTopologySpreadEnable" 70 71 // CachePredicate control cache predicate feature 72 CachePredicate = "predicate.CacheEnable" 73 74 // ProportionalPredicate is the key for enabling Proportional Predicate in YAML 75 ProportionalPredicate = "predicate.ProportionalEnable" 76 // ProportionalResource is the key for additional resource key name 77 ProportionalResource = "predicate.resources" 78 // ProportionalResourcesPrefix is the key prefix for additional resource key name 79 ProportionalResourcesPrefix = ProportionalResource + "." 80 ) 81 82 type predicatesPlugin struct { 83 // Arguments given for the plugin 84 pluginArguments framework.Arguments 85 } 86 87 // New return predicate plugin 88 func New(arguments framework.Arguments) framework.Plugin { 89 return &predicatesPlugin{pluginArguments: arguments} 90 } 91 92 func (pp *predicatesPlugin) Name() string { 93 return PluginName 94 } 95 96 type baseResource struct { 97 CPU float64 98 Memory float64 99 } 100 101 type predicateEnable struct { 102 nodeAffinityEnable bool 103 nodePortEnable bool 104 taintTolerationEnable bool 105 podAffinityEnable bool 106 nodeVolumeLimitsEnable bool 107 volumeZoneEnable bool 108 podTopologySpreadEnable bool 109 cacheEnable bool 110 proportionalEnable bool 111 proportional map[v1.ResourceName]baseResource 112 } 113 114 func enablePredicate(args framework.Arguments) predicateEnable { 115 /* 116 User Should give predicatesEnable in this format(predicate.GPUSharingEnable). 117 Currently supported only GPUSharing predicate checks. 118 119 actions: "reclaim, allocate, backfill, preempt" 120 tiers: 121 - plugins: 122 - name: priority 123 - name: gang 124 - name: conformance 125 - plugins: 126 - name: drf 127 - name: predicates 128 arguments: 129 predicate.NodeAffinityEnable: true 130 predicate.NodePortsEnable: true 131 predicate.TaintTolerationEnable: true 132 predicate.PodAffinityEnable: true 133 predicate.NodeVolumeLimitsEnable: true 134 predicate.VolumeZoneEnable: true 135 predicate.PodTopologySpreadEnable: true 136 predicate.GPUSharingEnable: true 137 predicate.GPUNumberEnable: true 138 predicate.CacheEnable: true 139 predicate.ProportionalEnable: true 140 predicate.resources: nvidia.com/gpu 141 predicate.resources.nvidia.com/gpu.cpu: 4 142 predicate.resources.nvidia.com/gpu.memory: 8 143 - name: proportion 144 - name: nodeorder 145 */ 146 147 predicate := predicateEnable{ 148 nodeAffinityEnable: true, 149 nodePortEnable: true, 150 taintTolerationEnable: true, 151 podAffinityEnable: true, 152 nodeVolumeLimitsEnable: true, 153 volumeZoneEnable: true, 154 podTopologySpreadEnable: true, 155 cacheEnable: false, 156 proportionalEnable: false, 157 } 158 159 // Checks whether predicate enable args is provided or not. 160 // If args were given by scheduler configmap, cover the values in predicateEnable struct. 161 args.GetBool(&predicate.nodeAffinityEnable, NodeAffinityEnable) 162 args.GetBool(&predicate.nodePortEnable, NodePortsEnable) 163 args.GetBool(&predicate.taintTolerationEnable, TaintTolerationEnable) 164 args.GetBool(&predicate.podAffinityEnable, PodAffinityEnable) 165 args.GetBool(&predicate.nodeVolumeLimitsEnable, NodeVolumeLimitsEnable) 166 args.GetBool(&predicate.volumeZoneEnable, VolumeZoneEnable) 167 args.GetBool(&predicate.podTopologySpreadEnable, PodTopologySpreadEnable) 168 169 args.GetBool(&predicate.cacheEnable, CachePredicate) 170 // Checks whether predicate.ProportionalEnable is provided or not, if given, modifies the value in predicateEnable struct. 171 args.GetBool(&predicate.proportionalEnable, ProportionalPredicate) 172 resourcesProportional := make(map[v1.ResourceName]baseResource) 173 resourcesStr, ok := args[ProportionalResource].(string) 174 if !ok { 175 resourcesStr = "" 176 } 177 resources := strings.Split(resourcesStr, ",") 178 for _, resource := range resources { 179 resource = strings.TrimSpace(resource) 180 if resource == "" { 181 continue 182 } 183 // proportional.resources.[ResourceName] 184 cpuResourceKey := ProportionalResourcesPrefix + resource + ".cpu" 185 cpuResourceRate := 1.0 186 args.GetFloat64(&cpuResourceRate, cpuResourceKey) 187 if cpuResourceRate < 0 { 188 cpuResourceRate = 1.0 189 } 190 memoryResourceKey := ProportionalResourcesPrefix + resource + ".memory" 191 memoryResourceRate := 1.0 192 args.GetFloat64(&memoryResourceRate, memoryResourceKey) 193 if memoryResourceRate < 0 { 194 memoryResourceRate = 1.0 195 } 196 r := baseResource{ 197 CPU: cpuResourceRate, 198 Memory: memoryResourceRate, 199 } 200 resourcesProportional[v1.ResourceName(resource)] = r 201 } 202 predicate.proportional = resourcesProportional 203 204 return predicate 205 } 206 207 func (pp *predicatesPlugin) OnSessionOpen(ssn *framework.Session) { 208 pl := ssn.PodLister 209 nodeMap := ssn.NodeMap 210 211 pCache := predicateCacheNew() 212 predicate := enablePredicate(pp.pluginArguments) 213 214 // Register event handlers to update task info in PodLister & nodeMap 215 ssn.AddEventHandler(&framework.EventHandler{ 216 AllocateFunc: func(event *framework.Event) { 217 klog.V(4).Infoln("predicates, allocate", event.Task.NodeName) 218 pod := pl.UpdateTask(event.Task, event.Task.NodeName) 219 nodeName := event.Task.NodeName 220 node, found := nodeMap[nodeName] 221 if !found { 222 klog.Errorf("predicates, update pod %s/%s allocate to NOT EXIST node [%s]", pod.Namespace, pod.Name, nodeName) 223 return 224 } 225 nodeInfo, ok := ssn.Nodes[nodeName] 226 if !ok { 227 klog.Errorf("Failed to get node %s info from cache", nodeName) 228 return 229 } 230 //predicate gpu sharing 231 for _, val := range api.RegisteredDevices { 232 if devices, ok := nodeInfo.Others[val].(api.Devices); ok { 233 if !devices.HasDeviceRequest(pod) { 234 continue 235 } 236 237 err := devices.Allocate(ssn.KubeClient(), pod) 238 if err != nil { 239 klog.Errorf("AllocateToPod failed %s", err.Error()) 240 return 241 } 242 } else { 243 klog.Warningf("Devices %s assertion conversion failed, skip", val) 244 } 245 } 246 node.AddPod(pod) 247 klog.V(4).Infof("predicates, update pod %s/%s allocate to node [%s]", pod.Namespace, pod.Name, nodeName) 248 }, 249 DeallocateFunc: func(event *framework.Event) { 250 klog.V(4).Infoln("predicates, deallocate", event.Task.NodeName) 251 pod := pl.UpdateTask(event.Task, "") 252 nodeName := event.Task.NodeName 253 node, found := nodeMap[nodeName] 254 if !found { 255 klog.Errorf("predicates, update pod %s/%s allocate from NOT EXIST node [%s]", pod.Namespace, pod.Name, nodeName) 256 return 257 } 258 259 nodeInfo, ok := ssn.Nodes[nodeName] 260 if !ok { 261 klog.Errorf("Failed to get node %s info from cache", nodeName) 262 return 263 } 264 265 for _, val := range api.RegisteredDevices { 266 if devices, ok := nodeInfo.Others[val].(api.Devices); ok { 267 if !devices.HasDeviceRequest(pod) { 268 continue 269 } 270 271 // deallocate pod gpu id 272 err := devices.Release(ssn.KubeClient(), pod) 273 if err != nil { 274 klog.Errorf(err.Error()) 275 return 276 } 277 } else { 278 klog.Warningf("Devices %s assertion conversion failed, skip", val) 279 } 280 } 281 282 err := node.RemovePod(klog.FromContext(context.TODO()), pod) 283 if err != nil { 284 klog.Errorf("predicates, remove pod %s/%s from node [%s] error: %v", pod.Namespace, pod.Name, nodeName, err) 285 return 286 } 287 klog.V(4).Infof("predicates, update pod %s/%s deallocate from node [%s]", pod.Namespace, pod.Name, nodeName) 288 }, 289 }) 290 291 features := feature.Features{ 292 EnableVolumeCapacityPriority: utilFeature.DefaultFeatureGate.Enabled(features.VolumeCapacityPriority), 293 EnableMinDomainsInPodTopologySpread: utilFeature.DefaultFeatureGate.Enabled(features.MinDomainsInPodTopologySpread), 294 EnableNodeInclusionPolicyInPodTopologySpread: utilFeature.DefaultFeatureGate.Enabled(features.NodeInclusionPolicyInPodTopologySpread), 295 EnableMatchLabelKeysInPodTopologySpread: utilFeature.DefaultFeatureGate.Enabled(features.MatchLabelKeysInPodTopologySpread), 296 } 297 // Initialize k8s plugins 298 // TODO: Add more predicates, k8s.io/kubernetes/pkg/scheduler/framework/plugins/legacy_registry.go 299 handle := k8s.NewFrameworkHandle(nodeMap, ssn.KubeClient(), ssn.InformerFactory()) 300 // 1. NodeUnschedulable 301 plugin, _ := nodeunschedulable.New(context.TODO(), nil, handle) 302 nodeUnscheduleFilter := plugin.(*nodeunschedulable.NodeUnschedulable) 303 // 2. NodeAffinity 304 nodeAffinityArgs := config.NodeAffinityArgs{ 305 AddedAffinity: &v1.NodeAffinity{}, 306 } 307 plugin, _ = nodeaffinity.New(context.TODO(), &nodeAffinityArgs, handle) 308 nodeAffinityFilter := plugin.(*nodeaffinity.NodeAffinity) 309 // 3. NodePorts 310 plugin, _ = nodeports.New(context.TODO(), nil, handle) 311 nodePortFilter := plugin.(*nodeports.NodePorts) 312 // 4. TaintToleration 313 plugin, _ = tainttoleration.New(context.TODO(), nil, handle) 314 tolerationFilter := plugin.(*tainttoleration.TaintToleration) 315 // 5. InterPodAffinity 316 plArgs := &config.InterPodAffinityArgs{} 317 plugin, _ = interpodaffinity.New(context.TODO(), plArgs, handle) 318 podAffinityFilter := plugin.(*interpodaffinity.InterPodAffinity) 319 // 6. NodeVolumeLimits 320 plugin, _ = nodevolumelimits.NewCSI(context.TODO(), nil, handle, features) 321 nodeVolumeLimitsCSIFilter := plugin.(*nodevolumelimits.CSILimits) 322 // 7. VolumeZone 323 plugin, _ = volumezone.New(context.TODO(), nil, handle) 324 volumeZoneFilter := plugin.(*volumezone.VolumeZone) 325 // 8. PodTopologySpread 326 // Setting cluster level default constraints is not support for now. 327 ptsArgs := &config.PodTopologySpreadArgs{DefaultingType: config.SystemDefaulting} 328 plugin, _ = podtopologyspread.New(context.TODO(), ptsArgs, handle, features) 329 podTopologySpreadFilter := plugin.(*podtopologyspread.PodTopologySpread) 330 331 state := k8sframework.NewCycleState() 332 skipPlugins := make(map[api.TaskID]sets.Set[string]) 333 334 ssn.AddPrePredicateFn(pp.Name(), func(task *api.TaskInfo) error { 335 // Check NodePorts 336 if predicate.nodePortEnable { 337 _, status := nodePortFilter.PreFilter(context.TODO(), state, task.Pod) 338 if err := handleSkipPrePredicatePlugin(status, task, skipPlugins, nodeports.Name); err != nil { 339 return err 340 } 341 } 342 343 // InterPodAffinity Predicate 344 // TODO: Update the node information to be processed by the filer based on the node list returned by the prefilter. 345 // In K8S V1.25, the return value result is added to the Prefile interface, 346 // indicating the list of nodes that meet filtering conditions. 347 // If the value of result is nil, all nodes meet the conditions. 348 // If the specified node information exists, only the node information in result meets the conditions. 349 // The value of Prefile in the current InterPodAffinity package always returns nil. 350 // The outer layer does not need to be processed temporarily. 351 // If the filtering logic is added to the Prefile node in the Volumebinding package in the future, 352 // the processing logic needs to be added to the return value result. 353 if predicate.podAffinityEnable { 354 _, status := podAffinityFilter.PreFilter(context.TODO(), state, task.Pod) 355 if err := handleSkipPrePredicatePlugin(status, task, skipPlugins, interpodaffinity.Name); err != nil { 356 return err 357 } 358 } 359 360 // Check PodTopologySpread 361 // TODO: Update the node information to be processed by the filer based on the node list returned by the prefilter. 362 // In K8S V1.25, the return value result is added to the Prefile interface, 363 // indicating the list of nodes that meet filtering conditions. 364 // If the value of result is nil, all nodes meet the conditions. 365 // If the specified node information exists, only the node information in result meets the conditions. 366 // The value of Prefile in the current PodTopologySpread package always returns nil. 367 // The outer layer does not need to be processed temporarily. 368 // If the filtering logic is added to the Prefile node in the Volumebinding package in the future, 369 // the processing logic needs to be added to the return value result. 370 if predicate.podTopologySpreadEnable { 371 _, status := podTopologySpreadFilter.PreFilter(context.TODO(), state, task.Pod) 372 if err := handleSkipPrePredicatePlugin(status, task, skipPlugins, podTopologySpreadFilter.Name()); err != nil { 373 return err 374 } 375 } 376 return nil 377 }) 378 379 ssn.AddPredicateFn(pp.Name(), func(task *api.TaskInfo, node *api.NodeInfo) ([]*api.Status, error) { 380 predicateStatus := make([]*api.Status, 0) 381 nodeInfo, found := nodeMap[node.Name] 382 if !found { 383 return predicateStatus, fmt.Errorf("failed to predicates, node info for %s not found", node.Name) 384 } 385 386 if node.Allocatable.MaxTaskNum <= len(nodeInfo.Pods) { 387 klog.V(4).Infof("NodePodNumber predicates Task <%s/%s> on Node <%s> failed, allocatable <%d>, existed <%d>", 388 task.Namespace, task.Name, node.Name, node.Allocatable.MaxTaskNum, len(nodeInfo.Pods)) 389 podsNumStatus := &api.Status{ 390 Code: api.Unschedulable, 391 Reason: api.NodePodNumberExceeded, 392 } 393 predicateStatus = append(predicateStatus, podsNumStatus) 394 } 395 396 predicateByStablefilter := func(pod *v1.Pod, nodeInfo *k8sframework.NodeInfo) ([]*api.Status, bool, error) { 397 // CheckNodeUnschedulable 398 predicateStatus := make([]*api.Status, 0) 399 status := nodeUnscheduleFilter.Filter(context.TODO(), state, task.Pod, nodeInfo) 400 nodeUnscheduleStatus := framework.ConvertPredicateStatus(status) 401 if nodeUnscheduleStatus.Code != api.Success { 402 predicateStatus = append(predicateStatus, nodeUnscheduleStatus) 403 return predicateStatus, false, fmt.Errorf("plugin %s predicates failed %s", nodeUnscheduleFilter.Name(), status.Message()) 404 } 405 406 // Check NodeAffinity 407 if predicate.nodeAffinityEnable { 408 status := nodeAffinityFilter.Filter(context.TODO(), state, task.Pod, nodeInfo) 409 nodeAffinityStatus := framework.ConvertPredicateStatus(status) 410 if nodeAffinityStatus.Code != api.Success { 411 predicateStatus = append(predicateStatus, nodeAffinityStatus) 412 return predicateStatus, false, fmt.Errorf("plugin %s predicates failed %s", nodeAffinityFilter.Name(), status.Message()) 413 } 414 } 415 416 // PodToleratesNodeTaints: TaintToleration 417 if predicate.taintTolerationEnable { 418 status := tolerationFilter.Filter(context.TODO(), state, task.Pod, nodeInfo) 419 tolerationStatus := framework.ConvertPredicateStatus(status) 420 if tolerationStatus.Code != api.Success { 421 predicateStatus = append(predicateStatus, tolerationStatus) 422 return predicateStatus, false, fmt.Errorf("plugin %s predicates failed %s", tolerationFilter.Name(), status.Message()) 423 } 424 } 425 426 return predicateStatus, true, nil 427 } 428 429 // Check PredicateWithCache 430 var err error 431 var fit bool 432 predicateCacheStatus := make([]*api.Status, 0) 433 if predicate.cacheEnable { 434 fit, err = pCache.PredicateWithCache(node.Name, task.Pod) 435 if err != nil { 436 predicateCacheStatus, fit, err = predicateByStablefilter(task.Pod, nodeInfo) 437 pCache.UpdateCache(node.Name, task.Pod, fit) 438 } else { 439 if !fit { 440 err = fmt.Errorf("plugin equivalence cache predicates failed") 441 } 442 } 443 } else { 444 predicateCacheStatus, fit, err = predicateByStablefilter(task.Pod, nodeInfo) 445 } 446 447 predicateStatus = append(predicateStatus, predicateCacheStatus...) 448 if !fit { 449 return predicateStatus, err 450 } 451 452 // Check NodePort 453 if predicate.nodePortEnable { 454 isSkipNodePorts := handleSkipPredicatePlugin(task, skipPlugins, nodePortFilter.Name(), node) 455 if !isSkipNodePorts { 456 status := nodePortFilter.Filter(context.TODO(), state, nil, nodeInfo) 457 nodePortStatus := framework.ConvertPredicateStatus(status) 458 if nodePortStatus.Code != api.Success { 459 predicateStatus = append(predicateStatus, nodePortStatus) 460 return predicateStatus, fmt.Errorf("plugin %s predicates failed %s", nodePortFilter.Name(), status.Message()) 461 } 462 } 463 } 464 465 // Check PodAffinity 466 if predicate.podAffinityEnable { 467 isSkipInterPodAffinity := handleSkipPredicatePlugin(task, skipPlugins, podAffinityFilter.Name(), node) 468 if !isSkipInterPodAffinity { 469 status := podAffinityFilter.Filter(context.TODO(), state, task.Pod, nodeInfo) 470 podAffinityStatus := framework.ConvertPredicateStatus(status) 471 if podAffinityStatus.Code != api.Success { 472 predicateStatus = append(predicateStatus, podAffinityStatus) 473 return predicateStatus, fmt.Errorf("plugin %s predicates failed %s", podAffinityFilter.Name(), status.Message()) 474 } 475 } 476 } 477 478 // Check NodeVolumeLimits 479 if predicate.nodeVolumeLimitsEnable { 480 status := nodeVolumeLimitsCSIFilter.Filter(context.TODO(), state, task.Pod, nodeInfo) 481 nodeVolumeStatus := framework.ConvertPredicateStatus(status) 482 predicateStatus = append(predicateStatus, nodeVolumeStatus) 483 } 484 485 // Check VolumeZone 486 if predicate.volumeZoneEnable { 487 status := volumeZoneFilter.Filter(context.TODO(), state, task.Pod, nodeInfo) 488 volumeZoneStatus := framework.ConvertPredicateStatus(status) 489 if volumeZoneStatus.Code != api.Success { 490 predicateStatus = append(predicateStatus, volumeZoneStatus) 491 return predicateStatus, fmt.Errorf("plugin %s predicates failed %s", volumeZoneFilter.Name(), status.Message()) 492 } 493 } 494 495 // Check PodTopologySpread 496 if predicate.podTopologySpreadEnable { 497 isSkipPodTopologySpreadFilter := handleSkipPredicatePlugin(task, skipPlugins, podTopologySpreadFilter.Name(), node) 498 if !isSkipPodTopologySpreadFilter { 499 status := podTopologySpreadFilter.Filter(context.TODO(), state, task.Pod, nodeInfo) 500 podTopologyStatus := framework.ConvertPredicateStatus(status) 501 if podTopologyStatus.Code != api.Success { 502 predicateStatus = append(predicateStatus, podTopologyStatus) 503 return predicateStatus, fmt.Errorf("plugin %s predicates failed %s", podTopologySpreadFilter.Name(), status.Message()) 504 } 505 } 506 } 507 508 if predicate.proportionalEnable { 509 // Check ProportionalPredicate 510 proportionalStatus, err := checkNodeResourceIsProportional(task, node, predicate.proportional) 511 if proportionalStatus.Code != api.Success { 512 predicateStatus = append(predicateStatus, proportionalStatus) 513 return predicateStatus, err 514 } 515 klog.V(4).Infof("checkNodeResourceIsProportional predicates Task <%s/%s> on Node <%s>: fit %v", 516 task.Namespace, task.Name, node.Name, fit) 517 } 518 return predicateStatus, nil 519 }) 520 } 521 522 func handleSkipPredicatePlugin(task *api.TaskInfo, skipPlugins map[api.TaskID]sets.Set[string], pluginName string, node *api.NodeInfo) bool { 523 isSkipPluginFilter := false 524 taskKey := api.PodKey(task.Pod) 525 if plugins, ok := skipPlugins[taskKey]; ok { 526 if plugins.Has(pluginName) { 527 isSkipPluginFilter = true 528 klog.V(5).Infof("pod(%s/%s) affinity require information is nil, plugin %s is skip for node %s", 529 task.Namespace, task.Name, pluginName, node.Name) 530 } 531 } 532 return isSkipPluginFilter 533 } 534 535 func handleSkipPrePredicatePlugin(status *k8sframework.Status, task *api.TaskInfo, skipPlugins map[api.TaskID]sets.Set[string], pluginName string) error { 536 if status.IsSkip() { 537 taskKey := api.PodKey(task.Pod) 538 if _, ok := skipPlugins[taskKey]; !ok { 539 plugins := sets.New[string]() 540 skipPlugins[taskKey] = plugins 541 } 542 skipPlugins[taskKey].Insert(pluginName) 543 klog.V(5).Infof("pod(%s/%s) affinity require information is nil, plugin %s is skipped", 544 task.Namespace, task.Name, pluginName) 545 } else if !status.IsSuccess() { 546 return fmt.Errorf("plugin %s pre-predicates failed %s", pluginName, status.Message()) 547 } 548 return nil 549 } 550 551 func (pp *predicatesPlugin) OnSessionClose(ssn *framework.Session) {}