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"
// 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,

View File

@ -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},

View File

@ -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)`),
},
}