Extract PredicateChecker interface
This commit is contained in:
		
							parent
							
								
									fd01b98670
								
							
						
					
					
						commit
						373c558303
					
				| 
						 | 
				
			
			@ -41,7 +41,7 @@ type AutoscalingContext struct {
 | 
			
		|||
	CloudProvider cloudprovider.CloudProvider
 | 
			
		||||
	// TODO(kgolab) - move away too as it's not config
 | 
			
		||||
	// PredicateChecker to check if a pod can fit into a node.
 | 
			
		||||
	PredicateChecker *simulator.PredicateChecker
 | 
			
		||||
	PredicateChecker simulator.PredicateChecker
 | 
			
		||||
	// ExpanderStrategy is the strategy used to choose which node group to expand when scaling up
 | 
			
		||||
	ExpanderStrategy expander.Strategy
 | 
			
		||||
	// EstimatorBuilder is the builder function for node count estimator to be used.
 | 
			
		||||
| 
						 | 
				
			
			@ -83,7 +83,7 @@ func NewResourceLimiterFromAutoscalingOptions(options config.AutoscalingOptions)
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
// NewAutoscalingContext returns an autoscaling context from all the necessary parameters passed via arguments
 | 
			
		||||
func NewAutoscalingContext(options config.AutoscalingOptions, predicateChecker *simulator.PredicateChecker,
 | 
			
		||||
func NewAutoscalingContext(options config.AutoscalingOptions, predicateChecker simulator.PredicateChecker,
 | 
			
		||||
	autoscalingKubeClients *AutoscalingKubeClients, cloudProvider cloudprovider.CloudProvider,
 | 
			
		||||
	expanderStrategy expander.Strategy, estimatorBuilder estimator.EstimatorBuilder,
 | 
			
		||||
	processorCallbacks processor_callbacks.ProcessorCallbacks) *AutoscalingContext {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -41,7 +41,7 @@ type AutoscalerOptions struct {
 | 
			
		|||
	EventsKubeClient       kube_client.Interface
 | 
			
		||||
	AutoscalingKubeClients *context.AutoscalingKubeClients
 | 
			
		||||
	CloudProvider          cloudprovider.CloudProvider
 | 
			
		||||
	PredicateChecker       *simulator.PredicateChecker
 | 
			
		||||
	PredicateChecker       simulator.PredicateChecker
 | 
			
		||||
	ExpanderStrategy       expander.Strategy
 | 
			
		||||
	EstimatorBuilder       estimator.EstimatorBuilder
 | 
			
		||||
	Processors             *ca_processors.AutoscalingProcessors
 | 
			
		||||
| 
						 | 
				
			
			@ -86,7 +86,7 @@ func initializeDefaultOptions(opts *AutoscalerOptions) error {
 | 
			
		|||
	}
 | 
			
		||||
	if opts.PredicateChecker == nil {
 | 
			
		||||
		predicateCheckerStopChannel := make(chan struct{})
 | 
			
		||||
		predicateChecker, err := simulator.NewPredicateChecker(opts.KubeClient, predicateCheckerStopChannel)
 | 
			
		||||
		predicateChecker, err := simulator.NewSchedulerBasedPredicateChecker(opts.KubeClient, predicateCheckerStopChannel)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -92,7 +92,7 @@ func (filterOutSchedulablePodListProcessor) CleanUp() {
 | 
			
		|||
// tries to pack the higher priority pods first. It takes into account pods that are bound to node
 | 
			
		||||
// and will be scheduled after lower priority pod preemption.
 | 
			
		||||
func filterOutSchedulableByPacking(unschedulableCandidates []*apiv1.Pod, nodes []*apiv1.Node,
 | 
			
		||||
	allScheduled []*apiv1.Pod, predicateChecker *simulator.PredicateChecker,
 | 
			
		||||
	allScheduled []*apiv1.Pod, predicateChecker simulator.PredicateChecker,
 | 
			
		||||
	expendablePodsPriorityCutoff int, nodesExist bool) []*apiv1.Pod {
 | 
			
		||||
	var unschedulablePods []*apiv1.Pod
 | 
			
		||||
	nonExpendableScheduled := utils.FilterOutExpendablePods(allScheduled, expendablePodsPriorityCutoff)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -109,7 +109,7 @@ func (callbacks *staticAutoscalerProcessorCallbacks) reset() {
 | 
			
		|||
// NewStaticAutoscaler creates an instance of Autoscaler filled with provided parameters
 | 
			
		||||
func NewStaticAutoscaler(
 | 
			
		||||
	opts config.AutoscalingOptions,
 | 
			
		||||
	predicateChecker *simulator.PredicateChecker,
 | 
			
		||||
	predicateChecker simulator.PredicateChecker,
 | 
			
		||||
	autoscalingKubeClients *context.AutoscalingKubeClients,
 | 
			
		||||
	processors *ca_processors.AutoscalingProcessors,
 | 
			
		||||
	cloudProvider cloudprovider.CloudProvider,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -63,7 +63,7 @@ func TestPodSchedulableMap(t *testing.T) {
 | 
			
		|||
	assert.True(t, found)
 | 
			
		||||
	assert.Nil(t, err)
 | 
			
		||||
 | 
			
		||||
	cpuErr := &simulator.PredicateError{}
 | 
			
		||||
	cpuErr := simulator.GenericPredicateError()
 | 
			
		||||
 | 
			
		||||
	// Pod in different RC
 | 
			
		||||
	_, found = pMap.Get(podInRc2)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -50,7 +50,7 @@ const (
 | 
			
		|||
func GetNodeInfosForGroups(nodes []*apiv1.Node, nodeInfoCache map[string]*schedulernodeinfo.NodeInfo, cloudProvider cloudprovider.CloudProvider, listers kube_util.ListerRegistry,
 | 
			
		||||
	// TODO(mwielgus): This returns map keyed by url, while most code (including scheduler) uses node.Name for a key.
 | 
			
		||||
	// TODO(mwielgus): Review error policy - sometimes we may continue with partial errors.
 | 
			
		||||
	daemonsets []*appsv1.DaemonSet, predicateChecker *simulator.PredicateChecker, ignoredTaints TaintKeySet) (map[string]*schedulernodeinfo.NodeInfo, errors.AutoscalerError) {
 | 
			
		||||
	daemonsets []*appsv1.DaemonSet, predicateChecker simulator.PredicateChecker, ignoredTaints TaintKeySet) (map[string]*schedulernodeinfo.NodeInfo, errors.AutoscalerError) {
 | 
			
		||||
	result := make(map[string]*schedulernodeinfo.NodeInfo)
 | 
			
		||||
	seenGroups := make(map[string]bool)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -173,7 +173,7 @@ func getPodsForNodes(listers kube_util.ListerRegistry) (map[string][]*apiv1.Pod,
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
// GetNodeInfoFromTemplate returns NodeInfo object built base on TemplateNodeInfo returned by NodeGroup.TemplateNodeInfo().
 | 
			
		||||
func GetNodeInfoFromTemplate(nodeGroup cloudprovider.NodeGroup, daemonsets []*appsv1.DaemonSet, predicateChecker *simulator.PredicateChecker, ignoredTaints TaintKeySet) (*schedulernodeinfo.NodeInfo, errors.AutoscalerError) {
 | 
			
		||||
func GetNodeInfoFromTemplate(nodeGroup cloudprovider.NodeGroup, daemonsets []*appsv1.DaemonSet, predicateChecker simulator.PredicateChecker, ignoredTaints TaintKeySet) (*schedulernodeinfo.NodeInfo, errors.AutoscalerError) {
 | 
			
		||||
	id := nodeGroup.Id()
 | 
			
		||||
	baseNodeInfo, err := nodeGroup.TemplateNodeInfo()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -34,11 +34,11 @@ type podInfo struct {
 | 
			
		|||
 | 
			
		||||
// BinpackingNodeEstimator estimates the number of needed nodes to handle the given amount of pods.
 | 
			
		||||
type BinpackingNodeEstimator struct {
 | 
			
		||||
	predicateChecker *simulator.PredicateChecker
 | 
			
		||||
	predicateChecker simulator.PredicateChecker
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewBinpackingNodeEstimator builds a new BinpackingNodeEstimator.
 | 
			
		||||
func NewBinpackingNodeEstimator(predicateChecker *simulator.PredicateChecker) *BinpackingNodeEstimator {
 | 
			
		||||
func NewBinpackingNodeEstimator(predicateChecker simulator.PredicateChecker) *BinpackingNodeEstimator {
 | 
			
		||||
	return &BinpackingNodeEstimator{
 | 
			
		||||
		predicateChecker: predicateChecker,
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -38,13 +38,13 @@ type Estimator interface {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
// EstimatorBuilder creates a new estimator object.
 | 
			
		||||
type EstimatorBuilder func(*simulator.PredicateChecker) Estimator
 | 
			
		||||
type EstimatorBuilder func(simulator.PredicateChecker) Estimator
 | 
			
		||||
 | 
			
		||||
// NewEstimatorBuilder creates a new estimator object from flag.
 | 
			
		||||
func NewEstimatorBuilder(name string) (EstimatorBuilder, error) {
 | 
			
		||||
	switch name {
 | 
			
		||||
	case BinpackingEstimatorName:
 | 
			
		||||
		return func(predicateChecker *simulator.PredicateChecker) Estimator {
 | 
			
		||||
		return func(predicateChecker simulator.PredicateChecker) Estimator {
 | 
			
		||||
			return NewBinpackingNodeEstimator(predicateChecker)
 | 
			
		||||
		}, nil
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -71,7 +71,7 @@ type UtilizationInfo struct {
 | 
			
		|||
// FindNodesToRemove finds nodes that can be removed. Returns also an information about good
 | 
			
		||||
// rescheduling location for each of the pods.
 | 
			
		||||
func FindNodesToRemove(candidates []*apiv1.Node, destinationNodes []*apiv1.Node, pods []*apiv1.Pod,
 | 
			
		||||
	listers kube_util.ListerRegistry, predicateChecker *PredicateChecker, maxCount int,
 | 
			
		||||
	listers kube_util.ListerRegistry, predicateChecker PredicateChecker, maxCount int,
 | 
			
		||||
	fastCheck bool, oldHints map[string]string, usageTracker *UsageTracker,
 | 
			
		||||
	timestamp time.Time,
 | 
			
		||||
	podDisruptionBudgets []*policyv1.PodDisruptionBudget,
 | 
			
		||||
| 
						 | 
				
			
			@ -218,7 +218,7 @@ func calculateUtilizationOfResource(node *apiv1.Node, nodeInfo *schedulernodeinf
 | 
			
		|||
 | 
			
		||||
// TODO: We don't need to pass list of nodes here as they are already available in nodeInfos.
 | 
			
		||||
func findPlaceFor(removedNode string, pods []*apiv1.Pod, nodes []*apiv1.Node, nodeInfos map[string]*schedulernodeinfo.NodeInfo,
 | 
			
		||||
	predicateChecker *PredicateChecker, oldHints map[string]string, newHints map[string]string, usageTracker *UsageTracker,
 | 
			
		||||
	predicateChecker PredicateChecker, oldHints map[string]string, newHints map[string]string, usageTracker *UsageTracker,
 | 
			
		||||
	timestamp time.Time) error {
 | 
			
		||||
 | 
			
		||||
	newNodeInfos := make(map[string]*schedulernodeinfo.NodeInfo)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,29 @@
 | 
			
		|||
/*
 | 
			
		||||
Copyright 2016 The Kubernetes Authors.
 | 
			
		||||
 | 
			
		||||
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.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
package simulator
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	apiv1 "k8s.io/api/core/v1"
 | 
			
		||||
	scheduler_nodeinfo "k8s.io/kubernetes/pkg/scheduler/nodeinfo"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// PredicateChecker checks whether all required predicates pass for given Pod and Node.
 | 
			
		||||
type PredicateChecker interface {
 | 
			
		||||
	SnapshotClusterState() error
 | 
			
		||||
	FitsAny(pod *apiv1.Pod, nodeInfos map[string]*scheduler_nodeinfo.NodeInfo) (string, error)
 | 
			
		||||
	CheckPredicates(pod *apiv1.Pod, nodeInfo *scheduler_nodeinfo.NodeInfo) *PredicateError
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -35,8 +35,9 @@ import (
 | 
			
		|||
	"k8s.io/kubernetes/pkg/scheduler/algorithmprovider"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// PredicateChecker checks whether all required predicates pass for given Pod and Node.
 | 
			
		||||
type PredicateChecker struct {
 | 
			
		||||
// SchedulerBasedPredicateChecker checks whether all required predicates pass for given Pod and Node.
 | 
			
		||||
// The verification is done by calling out to scheduler code.
 | 
			
		||||
type SchedulerBasedPredicateChecker struct {
 | 
			
		||||
	framework scheduler_framework.Framework
 | 
			
		||||
	snapshot  scheduler_listers.SharedLister
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -46,8 +47,8 @@ type PredicateChecker struct {
 | 
			
		|||
// There are no const arrays in Go, this is meant to be used as a const.
 | 
			
		||||
var priorityPredicates = []string{"PodFitsResources", "PodToleratesNodeTaints", "GeneralPredicates", "ready"}
 | 
			
		||||
 | 
			
		||||
// NewPredicateChecker builds PredicateChecker.
 | 
			
		||||
func NewPredicateChecker(kubeClient kube_client.Interface, stop <-chan struct{}) (*PredicateChecker, error) {
 | 
			
		||||
// NewSchedulerBasedPredicateChecker builds scheduler based PredicateChecker.
 | 
			
		||||
func NewSchedulerBasedPredicateChecker(kubeClient kube_client.Interface, stop <-chan struct{}) (*SchedulerBasedPredicateChecker, error) {
 | 
			
		||||
	informerFactory := informers.NewSharedInformerFactory(kubeClient, 0)
 | 
			
		||||
	providerRegistry := algorithmprovider.NewRegistry(1) // 1 here is hardPodAffinityWeight not relevant for CA
 | 
			
		||||
	config := providerRegistry[scheduler_apis_config.SchedulerDefaultProviderName]
 | 
			
		||||
| 
						 | 
				
			
			@ -82,27 +83,21 @@ func NewPredicateChecker(kubeClient kube_client.Interface, stop <-chan struct{})
 | 
			
		|||
	// informerFactory....Lister()/informerFactory....Informer() methods
 | 
			
		||||
	informerFactory.Start(stop)
 | 
			
		||||
 | 
			
		||||
	return &PredicateChecker{
 | 
			
		||||
	return &SchedulerBasedPredicateChecker{
 | 
			
		||||
		framework: framework,
 | 
			
		||||
		snapshot:  snapshot,
 | 
			
		||||
	}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewTestPredicateChecker builds test version of PredicateChecker.
 | 
			
		||||
func NewTestPredicateChecker() *PredicateChecker {
 | 
			
		||||
	// TODO(scheduler_framework)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SnapshotClusterState updates cluster snapshot used by the predicate checker.
 | 
			
		||||
// It should be called every CA loop iteration.
 | 
			
		||||
func (p *PredicateChecker) SnapshotClusterState() error {
 | 
			
		||||
func (p *SchedulerBasedPredicateChecker) SnapshotClusterState() error {
 | 
			
		||||
	// TODO(scheduler_framework rebuild snapshot
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// FitsAny checks if the given pod can be place on any of the given nodes.
 | 
			
		||||
func (p *PredicateChecker) FitsAny(pod *apiv1.Pod, nodeInfos map[string]*scheduler_nodeinfo.NodeInfo) (string, error) {
 | 
			
		||||
func (p *SchedulerBasedPredicateChecker) FitsAny(pod *apiv1.Pod, nodeInfos map[string]*scheduler_nodeinfo.NodeInfo) (string, error) {
 | 
			
		||||
	state := scheduler_framework.NewCycleState()
 | 
			
		||||
	preFilterStatus := p.framework.RunPreFilterPlugins(context.TODO(), state, pod)
 | 
			
		||||
	if !preFilterStatus.IsSuccess() {
 | 
			
		||||
| 
						 | 
				
			
			@ -131,7 +126,7 @@ func (p *PredicateChecker) FitsAny(pod *apiv1.Pod, nodeInfos map[string]*schedul
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
// CheckPredicates checks if the given pod can be placed on the given node.
 | 
			
		||||
func (p *PredicateChecker) CheckPredicates(pod *apiv1.Pod, nodeInfo *scheduler_nodeinfo.NodeInfo) *PredicateError {
 | 
			
		||||
func (p *SchedulerBasedPredicateChecker) CheckPredicates(pod *apiv1.Pod, nodeInfo *scheduler_nodeinfo.NodeInfo) *PredicateError {
 | 
			
		||||
	state := scheduler_framework.NewCycleState()
 | 
			
		||||
	preFilterStatus := p.framework.RunPreFilterPlugins(context.TODO(), state, pod)
 | 
			
		||||
	if !preFilterStatus.IsSuccess() {
 | 
			
		||||
| 
						 | 
				
			
			@ -165,7 +160,7 @@ func (p *PredicateChecker) CheckPredicates(pod *apiv1.Pod, nodeInfo *scheduler_n
 | 
			
		|||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *PredicateChecker) buildDebugInfo(filterName string, nodeInfo *scheduler_nodeinfo.NodeInfo) func() string {
 | 
			
		||||
func (p *SchedulerBasedPredicateChecker) buildDebugInfo(filterName string, nodeInfo *scheduler_nodeinfo.NodeInfo) func() string {
 | 
			
		||||
	switch filterName {
 | 
			
		||||
	case "TaintToleration":
 | 
			
		||||
		taints := nodeInfo.Node().Spec.Taints
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,38 @@
 | 
			
		|||
/*
 | 
			
		||||
Copyright 2020 The Kubernetes Authors.
 | 
			
		||||
 | 
			
		||||
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.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
package simulator
 | 
			
		||||
 | 
			
		||||
import scheduler_predicates "k8s.io/kubernetes/pkg/scheduler/algorithm/predicates"
 | 
			
		||||
 | 
			
		||||
// PredicateInfo assigns a name to a predicate
 | 
			
		||||
type PredicateInfo struct {
 | 
			
		||||
	Name      string
 | 
			
		||||
	Predicate scheduler_predicates.FitPredicate
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewTestPredicateChecker builds test version of PredicateChecker.
 | 
			
		||||
func NewTestPredicateChecker() PredicateChecker {
 | 
			
		||||
	// TODO(scheduler_framework)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewCustomTestPredicateChecker builds test version of PredicateChecker with additional predicates.
 | 
			
		||||
// Helps with benchmarking different ordering of predicates.
 | 
			
		||||
func NewCustomTestPredicateChecker(predicateInfos []PredicateInfo) PredicateChecker {
 | 
			
		||||
	// TODO(scheduler_framework)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -28,7 +28,7 @@ import (
 | 
			
		|||
)
 | 
			
		||||
 | 
			
		||||
// GetDaemonSetPodsForNode returns daemonset nodes for the given pod.
 | 
			
		||||
func GetDaemonSetPodsForNode(nodeInfo *schedulernodeinfo.NodeInfo, daemonsets []*appsv1.DaemonSet, predicateChecker *simulator.PredicateChecker) []*apiv1.Pod {
 | 
			
		||||
func GetDaemonSetPodsForNode(nodeInfo *schedulernodeinfo.NodeInfo, daemonsets []*appsv1.DaemonSet, predicateChecker simulator.PredicateChecker) []*apiv1.Pod {
 | 
			
		||||
	result := make([]*apiv1.Pod, 0)
 | 
			
		||||
	for _, ds := range daemonsets {
 | 
			
		||||
		pod := newPod(ds, nodeInfo.Node().Name)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue