diff --git a/pkg/controller/volume/scheduling/scheduler_binder.go b/pkg/controller/volume/scheduling/scheduler_binder.go index ed3805099bd..25ffc05b355 100644 --- a/pkg/controller/volume/scheduling/scheduler_binder.go +++ b/pkg/controller/volume/scheduling/scheduler_binder.go @@ -68,6 +68,8 @@ const ( ErrReasonNodeConflict ConflictReason = "node(s) had volume node affinity conflict" // ErrReasonNotEnoughSpace is used when a pod cannot start on a node because not enough storage space is available. ErrReasonNotEnoughSpace = "node(s) did not have enough free storage" + // ErrReasonPVNotExist is used when a PVC can't find the bound persistent volumes" + ErrReasonPVNotExist = "pvc(s) bound to non-existent pv(s)" ) // BindingInfo holds a binding between PV and PVC. @@ -246,6 +248,7 @@ func (b *volumeBinder) FindPodVolumes(pod *v1.Pod, boundClaims, claimsToBind []* unboundVolumesSatisfied := true boundVolumesSatisfied := true sufficientStorage := true + boundPVsFound := true defer func() { if err != nil { return @@ -259,6 +262,9 @@ func (b *volumeBinder) FindPodVolumes(pod *v1.Pod, boundClaims, claimsToBind []* if !sufficientStorage { reasons = append(reasons, ErrReasonNotEnoughSpace) } + if !boundPVsFound { + reasons = append(reasons, ErrReasonPVNotExist) + } }() start := time.Now() @@ -288,7 +294,7 @@ func (b *volumeBinder) FindPodVolumes(pod *v1.Pod, boundClaims, claimsToBind []* // Check PV node affinity on bound volumes if len(boundClaims) > 0 { - boundVolumesSatisfied, err = b.checkBoundClaims(boundClaims, node, podName) + boundVolumesSatisfied, boundPVsFound, err = b.checkBoundClaims(boundClaims, node, podName) if err != nil { return } @@ -762,7 +768,7 @@ func (b *volumeBinder) GetPodVolumes(pod *v1.Pod) (boundClaims []*v1.PersistentV return boundClaims, unboundClaimsDelayBinding, unboundClaimsImmediate, nil } -func (b *volumeBinder) checkBoundClaims(claims []*v1.PersistentVolumeClaim, node *v1.Node, podName string) (bool, error) { +func (b *volumeBinder) checkBoundClaims(claims []*v1.PersistentVolumeClaim, node *v1.Node, podName string) (bool, bool, error) { csiNode, err := b.csiNodeLister.Get(node.Name) if err != nil { // TODO: return the error once CSINode is created by default @@ -773,24 +779,27 @@ func (b *volumeBinder) checkBoundClaims(claims []*v1.PersistentVolumeClaim, node pvName := pvc.Spec.VolumeName pv, err := b.pvCache.GetPV(pvName) if err != nil { - return false, err + if _, ok := err.(*errNotFound); ok { + err = nil + } + return true, false, err } pv, err = b.tryTranslatePVToCSI(pv, csiNode) if err != nil { - return false, err + return false, true, err } err = volumeutil.CheckNodeAffinity(pv, node.Labels) if err != nil { klog.V(4).Infof("PersistentVolume %q, Node %q mismatch for Pod %q: %v", pvName, node.Name, podName, err) - return false, nil + return false, true, nil } klog.V(5).Infof("PersistentVolume %q, Node %q matches for Pod %q", pvName, node.Name, podName) } klog.V(4).Infof("All bound volumes for Pod %q match with Node %q", podName, node.Name) - return true, nil + return true, true, nil } // findMatchingVolumes tries to find matching volumes for given claims, diff --git a/pkg/controller/volume/scheduling/scheduler_binder_test.go b/pkg/controller/volume/scheduling/scheduler_binder_test.go index 93815e8f498..bb142915974 100644 --- a/pkg/controller/volume/scheduling/scheduler_binder_test.go +++ b/pkg/controller/volume/scheduling/scheduler_binder_test.go @@ -880,7 +880,8 @@ func TestFindPodVolumesWithoutProvisioning(t *testing.T) { }, "bound-pvc,pv-not-exists": { podPVCs: []*v1.PersistentVolumeClaim{boundPVC}, - shouldFail: true, + shouldFail: false, + reasons: ConflictReasons{ErrReasonPVNotExist}, }, "prebound-pvc": { podPVCs: []*v1.PersistentVolumeClaim{preboundPVC}, diff --git a/pkg/scheduler/framework/plugins/volumebinding/volume_binding_test.go b/pkg/scheduler/framework/plugins/volumebinding/volume_binding_test.go index 3014fd068cd..ba3056d0e42 100644 --- a/pkg/scheduler/framework/plugins/volumebinding/volume_binding_test.go +++ b/pkg/scheduler/framework/plugins/volumebinding/volume_binding_test.go @@ -138,6 +138,22 @@ func TestVolumeBinding(t *testing.T) { podVolumesByNode: map[string]*scheduling.PodVolumes{}, }, }, + { + name: "PVC does not exist", + pod: makePod("pod-a", []string{"pvc-a"}), + node: &v1.Node{}, + pvcs: []*v1.PersistentVolumeClaim{}, + wantPreFilterStatus: framework.NewStatus(framework.UnschedulableAndUnresolvable, `persistentvolumeclaim "pvc-a" not found`), + }, + { + name: "Part of PVCs do not exist", + pod: makePod("pod-a", []string{"pvc-a", "pvc-b"}), + node: &v1.Node{}, + pvcs: []*v1.PersistentVolumeClaim{ + makePVC("pvc-a", "pv-a", waitSC.Name), + }, + wantPreFilterStatus: framework.NewStatus(framework.UnschedulableAndUnresolvable, `persistentvolumeclaim "pvc-b" not found`), + }, { name: "immediate claims not bound", pod: makePod("pod-a", []string{"pvc-a"}), @@ -227,7 +243,7 @@ func TestVolumeBinding(t *testing.T) { claimsToBind: []*v1.PersistentVolumeClaim{}, podVolumesByNode: map[string]*scheduling.PodVolumes{}, }, - wantFilterStatus: framework.NewStatus(framework.Error, `could not find v1.PersistentVolume "pv-a"`), + wantFilterStatus: framework.NewStatus(framework.UnschedulableAndUnresolvable, `pvc(s) bound to non-existent pv(s)`), }, }