Don't count unrelated volumes in scheduler predicate

This commit is contained in:
Fabio Bertinatto
2019-07-29 13:37:28 +02:00
parent e5cec2edc8
commit ee7b48b7c5
3 changed files with 188 additions and 29 deletions

View File

@@ -287,6 +287,7 @@ type MaxPDVolumeCountChecker struct {
maxVolumeFunc func(node *v1.Node) int
pvInfo PersistentVolumeInfo
pvcInfo PersistentVolumeClaimInfo
scInfo StorageClassInfo
// The string below is generated randomly during the struct's initialization.
// It is used to prefix volumeID generated inside the predicate() method to
@@ -299,6 +300,8 @@ type VolumeFilter struct {
// Filter normal volumes
FilterVolume func(vol *v1.Volume) (id string, relevant bool)
FilterPersistentVolume func(pv *v1.PersistentVolume) (id string, relevant bool)
// MatchProvisioner evaluates if the StorageClass provisioner matches the running predicate
MatchProvisioner func(sc *storagev1.StorageClass) (relevant bool)
// IsMigrated returns a boolean specifying whether the plugin is migrated to a CSI driver
IsMigrated func(csiNode *storagev1beta1.CSINode) bool
}
@@ -314,7 +317,7 @@ type VolumeFilter struct {
// types, counts the number of unique volumes, and rejects the new pod if it would place the total count over
// the maximum.
func NewMaxPDVolumeCountPredicate(
filterName string, pvInfo PersistentVolumeInfo, pvcInfo PersistentVolumeClaimInfo) FitPredicate {
filterName string, scInfo StorageClassInfo, pvInfo PersistentVolumeInfo, pvcInfo PersistentVolumeClaimInfo) FitPredicate {
var filter VolumeFilter
var volumeLimitKey v1.ResourceName
@@ -344,6 +347,7 @@ func NewMaxPDVolumeCountPredicate(
maxVolumeFunc: getMaxVolumeFunc(filterName),
pvInfo: pvInfo,
pvcInfo: pvcInfo,
scInfo: scInfo,
randomVolumeIDPrefix: rand.String(32),
}
@@ -428,19 +432,23 @@ func (c *MaxPDVolumeCountChecker) filterVolumes(volumes []v1.Volume, namespace s
if pvName == "" {
// PVC is not bound. It was either deleted and created again or
// it was forcefully unbound by admin. The pod can still use the
// original PV where it was bound to -> log the error and count
// the PV towards the PV limit
klog.V(4).Infof("PVC %s/%s is not bound, assuming PVC matches predicate when counting limits", namespace, pvcName)
filteredVolumes[pvID] = true
// original PV where it was bound to, so we count the volume if
// it belongs to the running predicate.
if c.matchProvisioner(pvc) {
klog.V(4).Infof("PVC %s/%s is not bound, assuming PVC matches predicate when counting limits", namespace, pvcName)
filteredVolumes[pvID] = true
}
continue
}
pv, err := c.pvInfo.GetPersistentVolumeInfo(pvName)
if err != nil || pv == nil {
// if the PV is not found, log the error
// and count the PV towards the PV limit
klog.V(4).Infof("Unable to look up PV info for %s/%s/%s, assuming PV matches predicate when counting limits: %v", namespace, pvcName, pvName, err)
filteredVolumes[pvID] = true
// If the PV is invalid and PVC belongs to the running predicate,
// log the error and count the PV towards the PV limit.
if c.matchProvisioner(pvc) {
klog.V(4).Infof("Unable to look up PV info for %s/%s/%s, assuming PV matches predicate when counting limits: %v", namespace, pvcName, pvName, err)
filteredVolumes[pvID] = true
}
continue
}
@@ -453,6 +461,20 @@ func (c *MaxPDVolumeCountChecker) filterVolumes(volumes []v1.Volume, namespace s
return nil
}
// matchProvisioner helps identify if the given PVC belongs to the running predicate.
func (c *MaxPDVolumeCountChecker) matchProvisioner(pvc *v1.PersistentVolumeClaim) bool {
if pvc.Spec.StorageClassName == nil {
return false
}
storageClass, err := c.scInfo.GetStorageClassInfo(*pvc.Spec.StorageClassName)
if err != nil || storageClass == nil {
return false
}
return c.filter.MatchProvisioner(storageClass)
}
func (c *MaxPDVolumeCountChecker) predicate(pod *v1.Pod, meta PredicateMetadata, nodeInfo *schedulernodeinfo.NodeInfo) (bool, []PredicateFailureReason, error) {
// If a pod doesn't have any volume attached to it, the predicate will always be true.
// Thus we make a fast path for it, to avoid unnecessary computations in this case.
@@ -530,6 +552,13 @@ var EBSVolumeFilter = VolumeFilter{
return "", false
},
MatchProvisioner: func(sc *storagev1.StorageClass) (relevant bool) {
if sc.Provisioner == csilibplugins.AWSEBSInTreePluginName {
return true
}
return false
},
IsMigrated: func(csiNode *storagev1beta1.CSINode) bool {
return isCSIMigrationOn(csiNode, csilibplugins.AWSEBSInTreePluginName)
},
@@ -551,6 +580,13 @@ var GCEPDVolumeFilter = VolumeFilter{
return "", false
},
MatchProvisioner: func(sc *storagev1.StorageClass) (relevant bool) {
if sc.Provisioner == csilibplugins.GCEPDInTreePluginName {
return true
}
return false
},
IsMigrated: func(csiNode *storagev1beta1.CSINode) bool {
return isCSIMigrationOn(csiNode, csilibplugins.GCEPDInTreePluginName)
},
@@ -572,6 +608,13 @@ var AzureDiskVolumeFilter = VolumeFilter{
return "", false
},
MatchProvisioner: func(sc *storagev1.StorageClass) (relevant bool) {
if sc.Provisioner == csilibplugins.AzureDiskInTreePluginName {
return true
}
return false
},
IsMigrated: func(csiNode *storagev1beta1.CSINode) bool {
return isCSIMigrationOn(csiNode, csilibplugins.AzureDiskInTreePluginName)
},
@@ -594,6 +637,13 @@ var CinderVolumeFilter = VolumeFilter{
return "", false
},
MatchProvisioner: func(sc *storagev1.StorageClass) (relevant bool) {
if sc.Provisioner == csilibplugins.CinderInTreePluginName {
return true
}
return false
},
IsMigrated: func(csiNode *storagev1beta1.CSINode) bool {
return isCSIMigrationOn(csiNode, csilibplugins.CinderInTreePluginName)
},