8e5b17cf13
Signed-off-by: Mrunal Patel <mrunalp@gmail.com>
134 lines
4.2 KiB
Go
134 lines
4.2 KiB
Go
/*
|
|
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 scheduler
|
|
|
|
import (
|
|
"hash/adler32"
|
|
|
|
"github.com/golang/groupcache/lru"
|
|
|
|
"sync"
|
|
|
|
"k8s.io/kubernetes/pkg/api/v1"
|
|
hashutil "k8s.io/kubernetes/pkg/util/hash"
|
|
"k8s.io/kubernetes/plugin/pkg/scheduler/algorithm"
|
|
)
|
|
|
|
// TODO(harryz) figure out the right number for this, 4096 may be too big
|
|
const maxCacheEntries = 4096
|
|
|
|
type HostPredicate struct {
|
|
Fit bool
|
|
FailReasons []algorithm.PredicateFailureReason
|
|
}
|
|
|
|
type AlgorithmCache struct {
|
|
// Only consider predicates for now, priorities rely on: #31606
|
|
predicatesCache *lru.Cache
|
|
}
|
|
|
|
func newAlgorithmCache() AlgorithmCache {
|
|
return AlgorithmCache{
|
|
predicatesCache: lru.New(maxCacheEntries),
|
|
}
|
|
}
|
|
|
|
// Store a map of predicate cache with maxsize
|
|
type EquivalenceCache struct {
|
|
sync.RWMutex
|
|
getEquivalencePod algorithm.GetEquivalencePodFunc
|
|
algorithmCache map[string]AlgorithmCache
|
|
}
|
|
|
|
func NewEquivalenceCache(getEquivalencePodFunc algorithm.GetEquivalencePodFunc) *EquivalenceCache {
|
|
return &EquivalenceCache{
|
|
getEquivalencePod: getEquivalencePodFunc,
|
|
algorithmCache: make(map[string]AlgorithmCache),
|
|
}
|
|
}
|
|
|
|
// addPodPredicate adds pod predicate for equivalence class
|
|
func (ec *EquivalenceCache) addPodPredicate(podKey uint64, nodeName string, fit bool, failReasons []algorithm.PredicateFailureReason) {
|
|
if _, exist := ec.algorithmCache[nodeName]; !exist {
|
|
ec.algorithmCache[nodeName] = newAlgorithmCache()
|
|
}
|
|
ec.algorithmCache[nodeName].predicatesCache.Add(podKey, HostPredicate{Fit: fit, FailReasons: failReasons})
|
|
}
|
|
|
|
// AddPodPredicatesCache cache pod predicate for equivalence class
|
|
func (ec *EquivalenceCache) AddPodPredicatesCache(pod *v1.Pod, fitNodeList []*v1.Node, failedPredicates *FailedPredicateMap) {
|
|
equivalenceHash := ec.hashEquivalencePod(pod)
|
|
|
|
for _, fitNode := range fitNodeList {
|
|
ec.addPodPredicate(equivalenceHash, fitNode.Name, true, nil)
|
|
}
|
|
for failNodeName, failReasons := range *failedPredicates {
|
|
ec.addPodPredicate(equivalenceHash, failNodeName, false, failReasons)
|
|
}
|
|
}
|
|
|
|
// GetCachedPredicates gets cached predicates for equivalence class
|
|
func (ec *EquivalenceCache) GetCachedPredicates(pod *v1.Pod, nodes []*v1.Node) ([]*v1.Node, FailedPredicateMap, []*v1.Node) {
|
|
fitNodeList := []*v1.Node{}
|
|
failedPredicates := FailedPredicateMap{}
|
|
noCacheNodeList := []*v1.Node{}
|
|
equivalenceHash := ec.hashEquivalencePod(pod)
|
|
for _, node := range nodes {
|
|
findCache := false
|
|
if algorithmCache, exist := ec.algorithmCache[node.Name]; exist {
|
|
if cachePredicate, exist := algorithmCache.predicatesCache.Get(equivalenceHash); exist {
|
|
hostPredicate := cachePredicate.(HostPredicate)
|
|
if hostPredicate.Fit {
|
|
fitNodeList = append(fitNodeList, node)
|
|
} else {
|
|
failedPredicates[node.Name] = hostPredicate.FailReasons
|
|
}
|
|
findCache = true
|
|
}
|
|
}
|
|
if !findCache {
|
|
noCacheNodeList = append(noCacheNodeList, node)
|
|
}
|
|
}
|
|
return fitNodeList, failedPredicates, noCacheNodeList
|
|
}
|
|
|
|
// SendInvalidAlgorithmCacheReq marks AlgorithmCache item as invalid
|
|
func (ec *EquivalenceCache) SendInvalidAlgorithmCacheReq(nodeName string) {
|
|
ec.Lock()
|
|
defer ec.Unlock()
|
|
// clear the cache of this node
|
|
delete(ec.algorithmCache, nodeName)
|
|
}
|
|
|
|
// SendClearAllCacheReq marks all cached item as invalid
|
|
func (ec *EquivalenceCache) SendClearAllCacheReq() {
|
|
ec.Lock()
|
|
defer ec.Unlock()
|
|
// clear cache of all nodes
|
|
for nodeName := range ec.algorithmCache {
|
|
delete(ec.algorithmCache, nodeName)
|
|
}
|
|
}
|
|
|
|
// hashEquivalencePod returns the hash of equivalence pod.
|
|
func (ec *EquivalenceCache) hashEquivalencePod(pod *v1.Pod) uint64 {
|
|
equivalencePod := ec.getEquivalencePod(pod)
|
|
hash := adler32.New()
|
|
hashutil.DeepHashObject(hash, equivalencePod)
|
|
return uint64(hash.Sum32())
|
|
}
|