diff --git a/pkg/scheduler/framework/plugins/nodevolumelimits/csi.go b/pkg/scheduler/framework/plugins/nodevolumelimits/csi.go index bb10bff5214..48fb165ef0f 100644 --- a/pkg/scheduler/framework/plugins/nodevolumelimits/csi.go +++ b/pkg/scheduler/framework/plugins/nodevolumelimits/csi.go @@ -22,6 +22,7 @@ import ( v1 "k8s.io/api/core/v1" storagev1 "k8s.io/api/storage/v1" + apierrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/rand" corelisters "k8s.io/client-go/listers/core/v1" @@ -80,6 +81,7 @@ func (pl *CSILimits) EventsToRegister() []framework.ClusterEventWithHint { // because any new CSINode could make pods that were rejected by CSI volumes schedulable. {Event: framework.ClusterEvent{Resource: framework.CSINode, ActionType: framework.Add}}, {Event: framework.ClusterEvent{Resource: framework.Pod, ActionType: framework.Delete}}, + {Event: framework.ClusterEvent{Resource: framework.PersistentVolumeClaim, ActionType: framework.Add}}, } } @@ -123,6 +125,10 @@ func (pl *CSILimits) Filter(ctx context.Context, _ *framework.CycleState, pod *v newVolumes := make(map[string]string) if err := pl.filterAttachableVolumes(logger, pod, csiNode, true /* new pod */, newVolumes); err != nil { + if apierrors.IsNotFound(err) { + // PVC is not found. This Pod will never be schedulable until PVC is created. + return framework.NewStatus(framework.UnschedulableAndUnresolvable, err.Error()) + } return framework.AsStatus(err) } @@ -212,7 +218,7 @@ func (pl *CSILimits) filterAttachableVolumes( // The PVC is required to proceed with // scheduling of a new pod because it cannot // run without it. Bail out immediately. - return fmt.Errorf("looking up PVC %s/%s: %v", pod.Namespace, pvcName, err) + return fmt.Errorf("looking up PVC %s/%s: %w", pod.Namespace, pvcName, err) } // If the PVC is invalid, we don't count the volume because // there's no guarantee that it belongs to the running predicate. diff --git a/pkg/scheduler/framework/plugins/nodevolumelimits/csi_test.go b/pkg/scheduler/framework/plugins/nodevolumelimits/csi_test.go index c7a1c4c8d21..c18f8a8bb1b 100644 --- a/pkg/scheduler/framework/plugins/nodevolumelimits/csi_test.go +++ b/pkg/scheduler/framework/plugins/nodevolumelimits/csi_test.go @@ -495,7 +495,7 @@ func TestCSILimits(t *testing.T) { ephemeralEnabled: true, driverNames: []string{ebsCSIDriverName}, test: "ephemeral volume missing", - wantStatus: framework.AsStatus(errors.New(`looking up PVC test/abc-xyz: persistentvolumeclaims "abc-xyz" not found`)), + wantStatus: framework.NewStatus(framework.UnschedulableAndUnresolvable, `looking up PVC test/abc-xyz: persistentvolumeclaims "abc-xyz" not found`), }, { newPod: ephemeralVolumePod, @@ -595,7 +595,7 @@ func TestCSILimits(t *testing.T) { ephemeralEnabled: true, driverNames: []string{ebsCSIDriverName}, test: "don't skip Filter when the pod has ephemeral volumes", - wantStatus: framework.AsStatus(errors.New(`looking up PVC test/abc-xyz: persistentvolumeclaims "abc-xyz" not found`)), + wantStatus: framework.NewStatus(framework.UnschedulableAndUnresolvable, `looking up PVC test/abc-xyz: persistentvolumeclaims "abc-xyz" not found`), }, { newPod: inlineMigratablePodWithConfigmapAndSecret, diff --git a/pkg/scheduler/framework/plugins/nodevolumelimits/non_csi.go b/pkg/scheduler/framework/plugins/nodevolumelimits/non_csi.go index 150b21dbe3e..cab293058c9 100644 --- a/pkg/scheduler/framework/plugins/nodevolumelimits/non_csi.go +++ b/pkg/scheduler/framework/plugins/nodevolumelimits/non_csi.go @@ -26,6 +26,7 @@ import ( v1 "k8s.io/api/core/v1" storage "k8s.io/api/storage/v1" + apierrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/rand" "k8s.io/apimachinery/pkg/util/sets" @@ -209,6 +210,7 @@ func (pl *nonCSILimits) EventsToRegister() []framework.ClusterEventWithHint { return []framework.ClusterEventWithHint{ {Event: framework.ClusterEvent{Resource: framework.Node, ActionType: framework.Add}}, {Event: framework.ClusterEvent{Resource: framework.Pod, ActionType: framework.Delete}}, + {Event: framework.ClusterEvent{Resource: framework.PersistentVolumeClaim, ActionType: framework.Add}}, } } @@ -244,6 +246,10 @@ func (pl *nonCSILimits) Filter(ctx context.Context, _ *framework.CycleState, pod logger := klog.FromContext(ctx) newVolumes := sets.New[string]() if err := pl.filterVolumes(logger, pod, true /* new pod */, newVolumes); err != nil { + if apierrors.IsNotFound(err) { + // PVC is not found. This Pod will never be schedulable until PVC is created. + return framework.NewStatus(framework.UnschedulableAndUnresolvable, err.Error()) + } return framework.AsStatus(err) } @@ -336,7 +342,7 @@ func (pl *nonCSILimits) filterVolumes(logger klog.Logger, pod *v1.Pod, newPod bo // The PVC is required to proceed with // scheduling of a new pod because it cannot // run without it. Bail out immediately. - return fmt.Errorf("looking up PVC %s/%s: %v", pod.Namespace, pvcName, err) + return fmt.Errorf("looking up PVC %s/%s: %w", pod.Namespace, pvcName, err) } // If the PVC is invalid, we don't count the volume because // there's no guarantee that it belongs to the running predicate. diff --git a/pkg/scheduler/framework/plugins/nodevolumelimits/non_csi_test.go b/pkg/scheduler/framework/plugins/nodevolumelimits/non_csi_test.go index fdb2c8b3fe0..5135f20eab5 100644 --- a/pkg/scheduler/framework/plugins/nodevolumelimits/non_csi_test.go +++ b/pkg/scheduler/framework/plugins/nodevolumelimits/non_csi_test.go @@ -139,7 +139,7 @@ func TestEphemeralLimits(t *testing.T) { newPod: ephemeralVolumePod, ephemeralEnabled: true, test: "volume missing", - wantStatus: framework.AsStatus(errors.New(`looking up PVC test/abc-xyz: persistentvolumeclaims "abc-xyz" not found`)), + wantStatus: framework.NewStatus(framework.UnschedulableAndUnresolvable, `looking up PVC test/abc-xyz: persistentvolumeclaims "abc-xyz" not found`), }, { newPod: ephemeralVolumePod,