mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-10-31 02:08:13 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			199 lines
		
	
	
		
			6.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			199 lines
		
	
	
		
			6.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| /*
 | |
| Copyright 2019 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 cache
 | |
| 
 | |
| import (
 | |
| 	"fmt"
 | |
| 
 | |
| 	v1 "k8s.io/api/core/v1"
 | |
| 	"k8s.io/apimachinery/pkg/util/sets"
 | |
| 	"k8s.io/kubernetes/pkg/scheduler/framework"
 | |
| )
 | |
| 
 | |
| // Snapshot is a snapshot of cache NodeInfo and NodeTree order. The scheduler takes a
 | |
| // snapshot at the beginning of each scheduling cycle and uses it for its operations in that cycle.
 | |
| type Snapshot struct {
 | |
| 	// nodeInfoMap a map of node name to a snapshot of its NodeInfo.
 | |
| 	nodeInfoMap map[string]*framework.NodeInfo
 | |
| 	// nodeInfoList is the list of nodes as ordered in the cache's nodeTree.
 | |
| 	nodeInfoList []*framework.NodeInfo
 | |
| 	// havePodsWithAffinityNodeInfoList is the list of nodes with at least one pod declaring affinity terms.
 | |
| 	havePodsWithAffinityNodeInfoList []*framework.NodeInfo
 | |
| 	// havePodsWithRequiredAntiAffinityNodeInfoList is the list of nodes with at least one pod declaring
 | |
| 	// required anti-affinity terms.
 | |
| 	havePodsWithRequiredAntiAffinityNodeInfoList []*framework.NodeInfo
 | |
| 	// usedPVCSet contains a set of PVC names that have one or more scheduled pods using them,
 | |
| 	// keyed in the format "namespace/name".
 | |
| 	usedPVCSet sets.Set[string]
 | |
| 	generation int64
 | |
| }
 | |
| 
 | |
| var _ framework.SharedLister = &Snapshot{}
 | |
| 
 | |
| // NewEmptySnapshot initializes a Snapshot struct and returns it.
 | |
| func NewEmptySnapshot() *Snapshot {
 | |
| 	return &Snapshot{
 | |
| 		nodeInfoMap: make(map[string]*framework.NodeInfo),
 | |
| 		usedPVCSet:  sets.New[string](),
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // NewSnapshot initializes a Snapshot struct and returns it.
 | |
| func NewSnapshot(pods []*v1.Pod, nodes []*v1.Node) *Snapshot {
 | |
| 	nodeInfoMap := createNodeInfoMap(pods, nodes)
 | |
| 	nodeInfoList := make([]*framework.NodeInfo, 0, len(nodeInfoMap))
 | |
| 	havePodsWithAffinityNodeInfoList := make([]*framework.NodeInfo, 0, len(nodeInfoMap))
 | |
| 	havePodsWithRequiredAntiAffinityNodeInfoList := make([]*framework.NodeInfo, 0, len(nodeInfoMap))
 | |
| 	for _, v := range nodeInfoMap {
 | |
| 		nodeInfoList = append(nodeInfoList, v)
 | |
| 		if len(v.PodsWithAffinity) > 0 {
 | |
| 			havePodsWithAffinityNodeInfoList = append(havePodsWithAffinityNodeInfoList, v)
 | |
| 		}
 | |
| 		if len(v.PodsWithRequiredAntiAffinity) > 0 {
 | |
| 			havePodsWithRequiredAntiAffinityNodeInfoList = append(havePodsWithRequiredAntiAffinityNodeInfoList, v)
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	s := NewEmptySnapshot()
 | |
| 	s.nodeInfoMap = nodeInfoMap
 | |
| 	s.nodeInfoList = nodeInfoList
 | |
| 	s.havePodsWithAffinityNodeInfoList = havePodsWithAffinityNodeInfoList
 | |
| 	s.havePodsWithRequiredAntiAffinityNodeInfoList = havePodsWithRequiredAntiAffinityNodeInfoList
 | |
| 	s.usedPVCSet = createUsedPVCSet(pods)
 | |
| 
 | |
| 	return s
 | |
| }
 | |
| 
 | |
| // createNodeInfoMap obtains a list of pods and pivots that list into a map
 | |
| // where the keys are node names and the values are the aggregated information
 | |
| // for that node.
 | |
| func createNodeInfoMap(pods []*v1.Pod, nodes []*v1.Node) map[string]*framework.NodeInfo {
 | |
| 	nodeNameToInfo := make(map[string]*framework.NodeInfo)
 | |
| 	for _, pod := range pods {
 | |
| 		nodeName := pod.Spec.NodeName
 | |
| 		if _, ok := nodeNameToInfo[nodeName]; !ok {
 | |
| 			nodeNameToInfo[nodeName] = framework.NewNodeInfo()
 | |
| 		}
 | |
| 		nodeNameToInfo[nodeName].AddPod(pod)
 | |
| 	}
 | |
| 	imageExistenceMap := createImageExistenceMap(nodes)
 | |
| 
 | |
| 	for _, node := range nodes {
 | |
| 		if _, ok := nodeNameToInfo[node.Name]; !ok {
 | |
| 			nodeNameToInfo[node.Name] = framework.NewNodeInfo()
 | |
| 		}
 | |
| 		nodeInfo := nodeNameToInfo[node.Name]
 | |
| 		nodeInfo.SetNode(node)
 | |
| 		nodeInfo.ImageStates = getNodeImageStates(node, imageExistenceMap)
 | |
| 	}
 | |
| 	return nodeNameToInfo
 | |
| }
 | |
| 
 | |
| func createUsedPVCSet(pods []*v1.Pod) sets.Set[string] {
 | |
| 	usedPVCSet := sets.New[string]()
 | |
| 	for _, pod := range pods {
 | |
| 		if pod.Spec.NodeName == "" {
 | |
| 			continue
 | |
| 		}
 | |
| 
 | |
| 		for _, v := range pod.Spec.Volumes {
 | |
| 			if v.PersistentVolumeClaim == nil {
 | |
| 				continue
 | |
| 			}
 | |
| 
 | |
| 			key := framework.GetNamespacedName(pod.Namespace, v.PersistentVolumeClaim.ClaimName)
 | |
| 			usedPVCSet.Insert(key)
 | |
| 		}
 | |
| 	}
 | |
| 	return usedPVCSet
 | |
| }
 | |
| 
 | |
| // getNodeImageStates returns the given node's image states based on the given imageExistence map.
 | |
| func getNodeImageStates(node *v1.Node, imageExistenceMap map[string]sets.Set[string]) map[string]*framework.ImageStateSummary {
 | |
| 	imageStates := make(map[string]*framework.ImageStateSummary)
 | |
| 
 | |
| 	for _, image := range node.Status.Images {
 | |
| 		for _, name := range image.Names {
 | |
| 			imageStates[name] = &framework.ImageStateSummary{
 | |
| 				Size:     image.SizeBytes,
 | |
| 				NumNodes: imageExistenceMap[name].Len(),
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 	return imageStates
 | |
| }
 | |
| 
 | |
| // createImageExistenceMap returns a map recording on which nodes the images exist, keyed by the images' names.
 | |
| func createImageExistenceMap(nodes []*v1.Node) map[string]sets.Set[string] {
 | |
| 	imageExistenceMap := make(map[string]sets.Set[string])
 | |
| 	for _, node := range nodes {
 | |
| 		for _, image := range node.Status.Images {
 | |
| 			for _, name := range image.Names {
 | |
| 				if _, ok := imageExistenceMap[name]; !ok {
 | |
| 					imageExistenceMap[name] = sets.New(node.Name)
 | |
| 				} else {
 | |
| 					imageExistenceMap[name].Insert(node.Name)
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 	return imageExistenceMap
 | |
| }
 | |
| 
 | |
| // NodeInfos returns a NodeInfoLister.
 | |
| func (s *Snapshot) NodeInfos() framework.NodeInfoLister {
 | |
| 	return s
 | |
| }
 | |
| 
 | |
| // StorageInfos returns a StorageInfoLister.
 | |
| func (s *Snapshot) StorageInfos() framework.StorageInfoLister {
 | |
| 	return s
 | |
| }
 | |
| 
 | |
| // NumNodes returns the number of nodes in the snapshot.
 | |
| func (s *Snapshot) NumNodes() int {
 | |
| 	return len(s.nodeInfoList)
 | |
| }
 | |
| 
 | |
| // List returns the list of nodes in the snapshot.
 | |
| func (s *Snapshot) List() ([]*framework.NodeInfo, error) {
 | |
| 	return s.nodeInfoList, nil
 | |
| }
 | |
| 
 | |
| // HavePodsWithAffinityList returns the list of nodes with at least one pod with inter-pod affinity
 | |
| func (s *Snapshot) HavePodsWithAffinityList() ([]*framework.NodeInfo, error) {
 | |
| 	return s.havePodsWithAffinityNodeInfoList, nil
 | |
| }
 | |
| 
 | |
| // HavePodsWithRequiredAntiAffinityList returns the list of nodes with at least one pod with
 | |
| // required inter-pod anti-affinity
 | |
| func (s *Snapshot) HavePodsWithRequiredAntiAffinityList() ([]*framework.NodeInfo, error) {
 | |
| 	return s.havePodsWithRequiredAntiAffinityNodeInfoList, nil
 | |
| }
 | |
| 
 | |
| // Get returns the NodeInfo of the given node name.
 | |
| func (s *Snapshot) Get(nodeName string) (*framework.NodeInfo, error) {
 | |
| 	if v, ok := s.nodeInfoMap[nodeName]; ok && v.Node() != nil {
 | |
| 		return v, nil
 | |
| 	}
 | |
| 	return nil, fmt.Errorf("nodeinfo not found for node name %q", nodeName)
 | |
| }
 | |
| 
 | |
| func (s *Snapshot) IsPVCUsedByPods(key string) bool {
 | |
| 	return s.usedPVCSet.Has(key)
 | |
| }
 | 
