Skip to content

Commit c7dab2a

Browse files
authored
Merge pull request kubernetes#125280 from HirazawaUi/add-pvc-events-queueinghintfn
Add QueueingHintFn for pvc events in VolumeRestriction plugin
2 parents bae5979 + cd13be8 commit c7dab2a

File tree

2 files changed

+122
-1
lines changed

2 files changed

+122
-1
lines changed

pkg/scheduler/framework/plugins/volumerestrictions/volume_restrictions.go

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -329,10 +329,37 @@ func (pl *VolumeRestrictions) EventsToRegister() []framework.ClusterEventWithHin
329329
{Event: framework.ClusterEvent{Resource: framework.Node, ActionType: framework.Add}},
330330
// Pods may fail to schedule because the PVC it uses has not yet been created.
331331
// This PVC is required to exist to check its access modes.
332-
{Event: framework.ClusterEvent{Resource: framework.PersistentVolumeClaim, ActionType: framework.Add | framework.Update}},
332+
{Event: framework.ClusterEvent{Resource: framework.PersistentVolumeClaim, ActionType: framework.Add},
333+
QueueingHintFn: pl.isSchedulableAfterPersistentVolumeClaimAdded},
333334
}
334335
}
335336

337+
// isSchedulableAfterPersistentVolumeClaimAdded is invoked whenever a PersistentVolumeClaim added or changed, It checks whether
338+
// that change made a previously unschedulable pod schedulable.
339+
func (pl *VolumeRestrictions) isSchedulableAfterPersistentVolumeClaimAdded(logger klog.Logger, pod *v1.Pod, oldObj, newObj interface{}) (framework.QueueingHint, error) {
340+
_, newPersistentVolumeClaim, err := util.As[*v1.PersistentVolumeClaim](oldObj, newObj)
341+
if err != nil {
342+
return framework.Queue, fmt.Errorf("unexpected objects in isSchedulableAfterPersistentVolumeClaimChange: %w", err)
343+
}
344+
345+
if newPersistentVolumeClaim.Namespace != pod.Namespace {
346+
return framework.QueueSkip, nil
347+
}
348+
349+
for _, volume := range pod.Spec.Volumes {
350+
if volume.PersistentVolumeClaim == nil {
351+
continue
352+
}
353+
354+
if volume.PersistentVolumeClaim.ClaimName == newPersistentVolumeClaim.Name {
355+
logger.V(5).Info("PVC that is referred from the pod was created, which might make this pod schedulable", "pod", klog.KObj(pod), "PVC", klog.KObj(newPersistentVolumeClaim))
356+
return framework.Queue, nil
357+
}
358+
}
359+
logger.V(5).Info("PVC irrelevant to the Pod was created, which doesn't make this pod schedulable", "pod", klog.KObj(pod), "PVC", klog.KObj(newPersistentVolumeClaim))
360+
return framework.QueueSkip, nil
361+
}
362+
336363
// isSchedulableAfterPodDeleted is invoked whenever a pod deleted,
337364
// It checks whether the deleted pod will conflict with volumes of other pods on the same node
338365
// TODO If we observe good throughput, we will add a check for conflicts between the deleted Pod and the readWriteOncePodPVC of the current Pod.

pkg/scheduler/framework/plugins/volumerestrictions/volume_restrictions_test.go

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -667,6 +667,100 @@ func Test_isSchedulableAfterPodDeleted(t *testing.T) {
667667
}
668668
}
669669

670+
func Test_isSchedulableAfterPersistentVolumeClaimChange(t *testing.T) {
671+
podWithOnePVC := st.MakePod().Name("pod-with-one-pvc").Namespace(metav1.NamespaceDefault).PVC("claim-with-rwx-1").Node("node-1").Obj()
672+
podWithTwoPVCs := st.MakePod().Name("pod-with-two-pvcs").Namespace(metav1.NamespaceDefault).PVC("claim-with-rwx-1").PVC("claim-with-rwx-2").Node("node-1").Obj()
673+
podWithNotEqualNamespace := st.MakePod().Name("pod-with-one-pvc").Namespace(metav1.NamespaceSystem).PVC("claim-with-rwx-1").Node("claim-with-rwx-2").Obj()
674+
675+
PVC1 := &v1.PersistentVolumeClaim{
676+
ObjectMeta: metav1.ObjectMeta{
677+
Namespace: "default",
678+
Name: "claim-with-rwx-1",
679+
},
680+
Spec: v1.PersistentVolumeClaimSpec{
681+
AccessModes: []v1.PersistentVolumeAccessMode{v1.ReadWriteMany},
682+
},
683+
}
684+
685+
PVC2 := &v1.PersistentVolumeClaim{
686+
ObjectMeta: metav1.ObjectMeta{
687+
Namespace: "default",
688+
Name: "claim-with-rwx-2",
689+
},
690+
Spec: v1.PersistentVolumeClaimSpec{
691+
AccessModes: []v1.PersistentVolumeAccessMode{v1.ReadWriteMany},
692+
},
693+
}
694+
695+
testcases := map[string]struct {
696+
existingPods []*v1.Pod
697+
pod *v1.Pod
698+
oldObj, newObj interface{}
699+
expectedHint framework.QueueingHint
700+
expectedErr bool
701+
}{
702+
"queue-new-object-pvc-belong-pod": {
703+
existingPods: []*v1.Pod{},
704+
pod: podWithTwoPVCs,
705+
newObj: PVC1,
706+
expectedHint: framework.Queue,
707+
expectedErr: false,
708+
},
709+
"skip-new-object-unused": {
710+
existingPods: []*v1.Pod{},
711+
pod: podWithOnePVC,
712+
newObj: PVC2,
713+
expectedHint: framework.QueueSkip,
714+
expectedErr: false,
715+
},
716+
"skip-nil-old-object": {
717+
existingPods: []*v1.Pod{},
718+
pod: podWithOnePVC,
719+
newObj: PVC2,
720+
expectedHint: framework.QueueSkip,
721+
expectedErr: false,
722+
},
723+
"skip-new-object-not-belong-pod": {
724+
existingPods: []*v1.Pod{},
725+
pod: podWithOnePVC,
726+
newObj: PVC2,
727+
expectedHint: framework.QueueSkip,
728+
expectedErr: false,
729+
},
730+
"skip-new-object-namespace-not-equal-pod": {
731+
existingPods: []*v1.Pod{},
732+
pod: podWithNotEqualNamespace,
733+
newObj: PVC1,
734+
expectedHint: framework.QueueSkip,
735+
expectedErr: false,
736+
},
737+
}
738+
739+
for name, tc := range testcases {
740+
t.Run(name, func(t *testing.T) {
741+
logger, _ := ktesting.NewTestContext(t)
742+
ctx, cancel := context.WithCancel(context.Background())
743+
defer cancel()
744+
p := newPluginWithListers(ctx, t, tc.existingPods, nil, []*v1.PersistentVolumeClaim{tc.newObj.(*v1.PersistentVolumeClaim)})
745+
746+
actualHint, err := p.(*VolumeRestrictions).isSchedulableAfterPersistentVolumeClaimAdded(logger, tc.pod, tc.oldObj, tc.newObj)
747+
if tc.expectedErr {
748+
if err == nil {
749+
t.Error("Expect error, but got nil")
750+
}
751+
return
752+
}
753+
if err != nil {
754+
t.Errorf("Unexpected error: %v", err)
755+
}
756+
757+
if diff := cmp.Diff(tc.expectedHint, actualHint); diff != "" {
758+
t.Errorf("Unexpected QueueingHint (-want, +got): %s", diff)
759+
}
760+
})
761+
}
762+
}
763+
670764
func newPlugin(ctx context.Context, t *testing.T) framework.Plugin {
671765
return newPluginWithListers(ctx, t, nil, nil, nil)
672766
}

0 commit comments

Comments
 (0)