Skip to content

Commit 89283e0

Browse files
authored
Merge pull request kubernetes#124958 from bells17/qhint-volume-binding-storageclass
volumebinding: scheduler queueing hints - StorageClass
2 parents 29e4f5a + 4c3c412 commit 89283e0

File tree

2 files changed

+122
-1
lines changed

2 files changed

+122
-1
lines changed

pkg/scheduler/framework/plugins/volumebinding/volume_binding.go

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import (
2525

2626
v1 "k8s.io/api/core/v1"
2727
storagev1 "k8s.io/api/storage/v1"
28+
apiequality "k8s.io/apimachinery/pkg/api/equality"
2829
apierrors "k8s.io/apimachinery/pkg/api/errors"
2930
"k8s.io/apimachinery/pkg/runtime"
3031
corelisters "k8s.io/client-go/listers/core/v1"
@@ -98,7 +99,7 @@ func (pl *VolumeBinding) EventsToRegister() []framework.ClusterEventWithHint {
9899
// Pods may fail because of missing or mis-configured storage class
99100
// (e.g., allowedTopologies, volumeBindingMode), and hence may become
100101
// schedulable upon StorageClass Add or Update events.
101-
{Event: framework.ClusterEvent{Resource: framework.StorageClass, ActionType: framework.Add | framework.Update}},
102+
{Event: framework.ClusterEvent{Resource: framework.StorageClass, ActionType: framework.Add | framework.Update}, QueueingHintFn: pl.isSchedulableAfterStorageClassChange},
102103

103104
// We bind PVCs with PVs, so any changes may make the pods schedulable.
104105
{Event: framework.ClusterEvent{Resource: framework.PersistentVolumeClaim, ActionType: framework.Add | framework.Update}, QueueingHintFn: pl.isSchedulableAfterPersistentVolumeClaimChange},
@@ -195,6 +196,38 @@ func (pl *VolumeBinding) isSchedulableAfterPersistentVolumeClaimChange(logger kl
195196
return framework.QueueSkip, nil
196197
}
197198

199+
// isSchedulableAfterStorageClassChange checks whether an StorageClass event might make a Pod schedulable or not.
200+
// Any StorageClass addition and a StorageClass update to allowedTopologies
201+
// might make a Pod schedulable.
202+
// Note that an update to volume binding mode is not allowed and we don't have to consider while examining the update event.
203+
func (pl *VolumeBinding) isSchedulableAfterStorageClassChange(logger klog.Logger, pod *v1.Pod, oldObj, newObj interface{}) (framework.QueueingHint, error) {
204+
oldSC, newSC, err := util.As[*storagev1.StorageClass](oldObj, newObj)
205+
if err != nil {
206+
return framework.Queue, err
207+
}
208+
209+
logger = klog.LoggerWithValues(
210+
logger,
211+
"Pod", klog.KObj(pod),
212+
"StorageClass", klog.KObj(newSC),
213+
)
214+
215+
if oldSC == nil {
216+
// No further filtering can be made for a creation event,
217+
// and we just always return Queue.
218+
logger.V(5).Info("A new StorageClass was created, which could make a Pod schedulable")
219+
return framework.Queue, nil
220+
}
221+
222+
if !apiequality.Semantic.DeepEqual(newSC.AllowedTopologies, oldSC.AllowedTopologies) {
223+
logger.V(5).Info("StorageClass got an update in AllowedTopologies", "AllowedTopologies", newSC.AllowedTopologies)
224+
return framework.Queue, nil
225+
}
226+
227+
logger.V(5).Info("StorageClass was updated, but it doesn't make this pod schedulable")
228+
return framework.QueueSkip, nil
229+
}
230+
198231
// podHasPVCs returns 2 values:
199232
// - the first one to denote if the given "pod" has any PVC defined.
200233
// - the second one to return any error if the requested PVC is illegal.

pkg/scheduler/framework/plugins/volumebinding/volume_binding_test.go

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1093,3 +1093,91 @@ func TestIsSchedulableAfterPersistentVolumeClaimChange(t *testing.T) {
10931093
})
10941094
}
10951095
}
1096+
1097+
func TestIsSchedulableAfterStorageClassChange(t *testing.T) {
1098+
table := []struct {
1099+
name string
1100+
pod *v1.Pod
1101+
oldSC interface{}
1102+
newSC interface{}
1103+
pvcLister tf.PersistentVolumeClaimLister
1104+
err bool
1105+
expect framework.QueueingHint
1106+
}{
1107+
{
1108+
name: "When a new StorageClass is created, it returns Queue",
1109+
pod: makePod("pod-a").Pod,
1110+
oldSC: nil,
1111+
newSC: &storagev1.StorageClass{
1112+
ObjectMeta: metav1.ObjectMeta{
1113+
Name: "sc-a",
1114+
},
1115+
},
1116+
err: false,
1117+
expect: framework.Queue,
1118+
},
1119+
{
1120+
name: "When the AllowedTopologies are changed, it returns Queue",
1121+
pod: makePod("pod-a").Pod,
1122+
oldSC: &storagev1.StorageClass{
1123+
ObjectMeta: metav1.ObjectMeta{
1124+
Name: "sc-a",
1125+
},
1126+
},
1127+
newSC: &storagev1.StorageClass{
1128+
ObjectMeta: metav1.ObjectMeta{
1129+
Name: "sc-a",
1130+
},
1131+
AllowedTopologies: []v1.TopologySelectorTerm{
1132+
{
1133+
MatchLabelExpressions: []v1.TopologySelectorLabelRequirement{
1134+
{
1135+
Key: "kubernetes.io/hostname",
1136+
Values: []string{"node-a"},
1137+
},
1138+
},
1139+
},
1140+
},
1141+
},
1142+
err: false,
1143+
expect: framework.Queue,
1144+
},
1145+
{
1146+
name: "When there are no changes to the StorageClass, it returns QueueSkip",
1147+
pod: makePod("pod-a").Pod,
1148+
oldSC: &storagev1.StorageClass{
1149+
ObjectMeta: metav1.ObjectMeta{
1150+
Name: "sc-a",
1151+
},
1152+
},
1153+
newSC: &storagev1.StorageClass{
1154+
ObjectMeta: metav1.ObjectMeta{
1155+
Name: "sc-a",
1156+
},
1157+
},
1158+
err: false,
1159+
expect: framework.QueueSkip,
1160+
},
1161+
{
1162+
name: "type conversion error",
1163+
oldSC: new(struct{}),
1164+
newSC: new(struct{}),
1165+
err: true,
1166+
expect: framework.Queue,
1167+
},
1168+
}
1169+
1170+
for _, item := range table {
1171+
t.Run(item.name, func(t *testing.T) {
1172+
pl := &VolumeBinding{PVCLister: item.pvcLister}
1173+
logger, _ := ktesting.NewTestContext(t)
1174+
qhint, err := pl.isSchedulableAfterStorageClassChange(logger, item.pod, item.oldSC, item.newSC)
1175+
if (err != nil) != item.err {
1176+
t.Errorf("isSchedulableAfterStorageClassChange failed - got: %q", err)
1177+
}
1178+
if qhint != item.expect {
1179+
t.Errorf("QHint does not match: %v, want: %v", qhint, item.expect)
1180+
}
1181+
})
1182+
}
1183+
}

0 commit comments

Comments
 (0)