mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-04 09:49:50 +00:00
volumezone: scheduler queueing hints
This commit is contained in:
parent
5b49afa66b
commit
ac15717653
@ -276,7 +276,7 @@ func (pl *VolumeZone) EventsToRegister() []framework.ClusterEventWithHint {
|
|||||||
return []framework.ClusterEventWithHint{
|
return []framework.ClusterEventWithHint{
|
||||||
// New storageClass with bind mode `VolumeBindingWaitForFirstConsumer` will make a pod schedulable.
|
// New storageClass with bind mode `VolumeBindingWaitForFirstConsumer` will make a pod schedulable.
|
||||||
// Due to immutable field `storageClass.volumeBindingMode`, storageClass update events are ignored.
|
// Due to immutable field `storageClass.volumeBindingMode`, storageClass update events are ignored.
|
||||||
{Event: framework.ClusterEvent{Resource: framework.StorageClass, ActionType: framework.Add}},
|
{Event: framework.ClusterEvent{Resource: framework.StorageClass, ActionType: framework.Add}, QueueingHintFn: pl.isSchedulableAfterStorageClassAdded},
|
||||||
// A new node or updating a node's volume zone labels may make a pod schedulable.
|
// A new node or updating a node's volume zone labels may make a pod schedulable.
|
||||||
//
|
//
|
||||||
// A note about UpdateNodeTaint event:
|
// A note about UpdateNodeTaint event:
|
||||||
@ -342,6 +342,23 @@ func (pl *VolumeZone) isPVCRequestedFromPod(logger klog.Logger, pvc *v1.Persiste
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// isSchedulableAfterStorageClassAdded is invoked whenever a StorageClass is added.
|
||||||
|
// It checks whether the addition of StorageClass has made a previously unschedulable pod schedulable.
|
||||||
|
// Only a new StorageClass with WaitForFirstConsumer will cause a pod to become schedulable.
|
||||||
|
func (pl *VolumeZone) isSchedulableAfterStorageClassAdded(logger klog.Logger, pod *v1.Pod, oldObj, newObj interface{}) (framework.QueueingHint, error) {
|
||||||
|
_, addedStorageClass, err := util.As[*storage.StorageClass](nil, newObj)
|
||||||
|
if err != nil {
|
||||||
|
return framework.Queue, fmt.Errorf("unexpected objects in isSchedulableAfterStorageClassAdded: %w", err)
|
||||||
|
}
|
||||||
|
if (addedStorageClass.VolumeBindingMode == nil) || (*addedStorageClass.VolumeBindingMode != storage.VolumeBindingWaitForFirstConsumer) {
|
||||||
|
logger.V(5).Info("StorageClass is created, but its VolumeBindingMode is not waitForFirstConsumer, which doesn't make the pod schedulable", "storageClass", klog.KObj(addedStorageClass), "pod", klog.KObj(pod))
|
||||||
|
return framework.QueueSkip, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.V(5).Info("StorageClass with waitForFirstConsumer mode was created and it might make this pod schedulable", "pod", klog.KObj(pod), "StorageClass", klog.KObj(addedStorageClass))
|
||||||
|
return framework.Queue, nil
|
||||||
|
}
|
||||||
|
|
||||||
// New initializes a new plugin and returns it.
|
// New initializes a new plugin and returns it.
|
||||||
func New(_ context.Context, _ runtime.Object, handle framework.Handle) (framework.Plugin, error) {
|
func New(_ context.Context, _ runtime.Object, handle framework.Handle) (framework.Plugin, error) {
|
||||||
informerFactory := handle.SharedInformerFactory()
|
informerFactory := handle.SharedInformerFactory()
|
||||||
|
@ -627,6 +627,54 @@ func TestIsSchedulableAfterPersistentVolumeClaimAdded(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestIsSchedulableAfterStorageClassAdded(t *testing.T) {
|
||||||
|
var modeWait = storagev1.VolumeBindingWaitForFirstConsumer
|
||||||
|
|
||||||
|
testcases := map[string]struct {
|
||||||
|
pod *v1.Pod
|
||||||
|
oldObj, newObj interface{}
|
||||||
|
expectedHint framework.QueueingHint
|
||||||
|
expectedErr bool
|
||||||
|
}{
|
||||||
|
"error-wrong-new-object": {
|
||||||
|
pod: createPodWithVolume("pod_1", "PVC_1"),
|
||||||
|
newObj: "not-a-storageclass",
|
||||||
|
expectedHint: framework.Queue,
|
||||||
|
expectedErr: true,
|
||||||
|
},
|
||||||
|
"sc-doesn't-have-volume-binding-mode": {
|
||||||
|
pod: createPodWithVolume("pod_1", "PVC_1"),
|
||||||
|
newObj: &storagev1.StorageClass{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{Name: "SC_1"},
|
||||||
|
},
|
||||||
|
expectedHint: framework.QueueSkip,
|
||||||
|
},
|
||||||
|
"new-sc-is-wait-for-first-consumer-mode": {
|
||||||
|
pod: createPodWithVolume("pod_1", "PVC_1"),
|
||||||
|
newObj: &storagev1.StorageClass{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{Name: "SC_1"},
|
||||||
|
VolumeBindingMode: &modeWait,
|
||||||
|
},
|
||||||
|
expectedHint: framework.Queue,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for name, tc := range testcases {
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
logger, _ := ktesting.NewTestContext(t)
|
||||||
|
p := &VolumeZone{}
|
||||||
|
|
||||||
|
got, err := p.isSchedulableAfterStorageClassAdded(logger, tc.pod, tc.oldObj, tc.newObj)
|
||||||
|
if err != nil && !tc.expectedErr {
|
||||||
|
t.Errorf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
if got != tc.expectedHint {
|
||||||
|
t.Errorf("isSchedulableAfterStorageClassAdded() = %v, want %v", got, tc.expectedHint)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func BenchmarkVolumeZone(b *testing.B) {
|
func BenchmarkVolumeZone(b *testing.B) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
Name string
|
Name string
|
||||||
|
Loading…
Reference in New Issue
Block a user