Merge pull request #95541 from cofyc/fix95538

volume binding: report UnschedulableAndUnresolvable status instead of an error when bound PVs not found
This commit is contained in:
Kubernetes Prow Robot 2020-11-05 15:16:51 -08:00 committed by GitHub
commit 2d6cd683bd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 34 additions and 8 deletions

View File

@ -68,6 +68,8 @@ const (
ErrReasonNodeConflict ConflictReason = "node(s) had volume node affinity conflict" 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 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" 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. // BindingInfo holds a binding between PV and PVC.
@ -246,6 +248,7 @@ func (b *volumeBinder) FindPodVolumes(pod *v1.Pod, boundClaims, claimsToBind []*
unboundVolumesSatisfied := true unboundVolumesSatisfied := true
boundVolumesSatisfied := true boundVolumesSatisfied := true
sufficientStorage := true sufficientStorage := true
boundPVsFound := true
defer func() { defer func() {
if err != nil { if err != nil {
return return
@ -259,6 +262,9 @@ func (b *volumeBinder) FindPodVolumes(pod *v1.Pod, boundClaims, claimsToBind []*
if !sufficientStorage { if !sufficientStorage {
reasons = append(reasons, ErrReasonNotEnoughSpace) reasons = append(reasons, ErrReasonNotEnoughSpace)
} }
if !boundPVsFound {
reasons = append(reasons, ErrReasonPVNotExist)
}
}() }()
start := time.Now() start := time.Now()
@ -288,7 +294,7 @@ func (b *volumeBinder) FindPodVolumes(pod *v1.Pod, boundClaims, claimsToBind []*
// Check PV node affinity on bound volumes // Check PV node affinity on bound volumes
if len(boundClaims) > 0 { if len(boundClaims) > 0 {
boundVolumesSatisfied, err = b.checkBoundClaims(boundClaims, node, podName) boundVolumesSatisfied, boundPVsFound, err = b.checkBoundClaims(boundClaims, node, podName)
if err != nil { if err != nil {
return return
} }
@ -762,7 +768,7 @@ func (b *volumeBinder) GetPodVolumes(pod *v1.Pod) (boundClaims []*v1.PersistentV
return boundClaims, unboundClaimsDelayBinding, unboundClaimsImmediate, nil 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) csiNode, err := b.csiNodeLister.Get(node.Name)
if err != nil { if err != nil {
// TODO: return the error once CSINode is created by default // 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 pvName := pvc.Spec.VolumeName
pv, err := b.pvCache.GetPV(pvName) pv, err := b.pvCache.GetPV(pvName)
if err != nil { if err != nil {
return false, err if _, ok := err.(*errNotFound); ok {
err = nil
}
return true, false, err
} }
pv, err = b.tryTranslatePVToCSI(pv, csiNode) pv, err = b.tryTranslatePVToCSI(pv, csiNode)
if err != nil { if err != nil {
return false, err return false, true, err
} }
err = volumeutil.CheckNodeAffinity(pv, node.Labels) err = volumeutil.CheckNodeAffinity(pv, node.Labels)
if err != nil { if err != nil {
klog.V(4).Infof("PersistentVolume %q, Node %q mismatch for Pod %q: %v", pvName, node.Name, podName, err) 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(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) 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, // findMatchingVolumes tries to find matching volumes for given claims,

View File

@ -880,7 +880,8 @@ func TestFindPodVolumesWithoutProvisioning(t *testing.T) {
}, },
"bound-pvc,pv-not-exists": { "bound-pvc,pv-not-exists": {
podPVCs: []*v1.PersistentVolumeClaim{boundPVC}, podPVCs: []*v1.PersistentVolumeClaim{boundPVC},
shouldFail: true, shouldFail: false,
reasons: ConflictReasons{ErrReasonPVNotExist},
}, },
"prebound-pvc": { "prebound-pvc": {
podPVCs: []*v1.PersistentVolumeClaim{preboundPVC}, podPVCs: []*v1.PersistentVolumeClaim{preboundPVC},

View File

@ -138,6 +138,22 @@ func TestVolumeBinding(t *testing.T) {
podVolumesByNode: map[string]*scheduling.PodVolumes{}, 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", name: "immediate claims not bound",
pod: makePod("pod-a", []string{"pvc-a"}), pod: makePod("pod-a", []string{"pvc-a"}),
@ -227,7 +243,7 @@ func TestVolumeBinding(t *testing.T) {
claimsToBind: []*v1.PersistentVolumeClaim{}, claimsToBind: []*v1.PersistentVolumeClaim{},
podVolumesByNode: map[string]*scheduling.PodVolumes{}, 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)`),
}, },
} }