Skip to content

Commit 17af029

Browse files
committed
do not create StatefulSet pods when PVC is being deleted
Pod with PVC will not be scheduled if the PVC is being deleted. This can happen when the PVC has finalizers of storage plugins. Such a pod becomes pending. Unfortunately, after the finalizer finishes and PVC is deleted, the pod remains pending forever. The StatefulSet controller does nothing for this pending pod. This commit prevents the StatefulSet controller from creating such pods when PVC is to be deleted.
1 parent 6c2d183 commit 17af029

File tree

2 files changed

+43
-1
lines changed

2 files changed

+43
-1
lines changed

pkg/controller/statefulset/stateful_pod_control.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ func (spc *realStatefulPodControl) recordClaimEvent(verb string, set *apps.State
181181
func (spc *realStatefulPodControl) createPersistentVolumeClaims(set *apps.StatefulSet, pod *v1.Pod) error {
182182
var errs []error
183183
for _, claim := range getPersistentVolumeClaims(set, pod) {
184-
_, err := spc.pvcLister.PersistentVolumeClaims(claim.Namespace).Get(claim.Name)
184+
pvc, err := spc.pvcLister.PersistentVolumeClaims(claim.Namespace).Get(claim.Name)
185185
switch {
186186
case apierrors.IsNotFound(err):
187187
_, err := spc.client.CoreV1().PersistentVolumeClaims(claim.Namespace).Create(context.TODO(), &claim, metav1.CreateOptions{})
@@ -194,6 +194,10 @@ func (spc *realStatefulPodControl) createPersistentVolumeClaims(set *apps.Statef
194194
case err != nil:
195195
errs = append(errs, fmt.Errorf("failed to retrieve PVC %s: %s", claim.Name, err))
196196
spc.recordClaimEvent("create", set, pod, &claim, err)
197+
case err == nil:
198+
if pvc.DeletionTimestamp != nil {
199+
errs = append(errs, fmt.Errorf("pvc %s is being deleted", claim.Name))
200+
}
197201
}
198202
// TODO: Check resource requirements and accessmodes, update if necessary
199203
}

pkg/controller/statefulset/stateful_pod_control_test.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"errors"
2121
"strings"
2222
"testing"
23+
"time"
2324

2425
apierrors "k8s.io/apimachinery/pkg/api/errors"
2526
"k8s.io/apimachinery/pkg/runtime"
@@ -29,6 +30,7 @@ import (
2930
"k8s.io/client-go/tools/record"
3031

3132
"k8s.io/api/core/v1"
33+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
3234
"k8s.io/client-go/kubernetes/fake"
3335
corelisters "k8s.io/client-go/listers/core/v1"
3436
_ "k8s.io/kubernetes/pkg/apis/apps/install"
@@ -128,6 +130,42 @@ func TestStatefulPodControlCreatePodPvcCreateFailure(t *testing.T) {
128130
}
129131
}
130132
}
133+
func TestStatefulPodControlCreatePodPvcDeleting(t *testing.T) {
134+
recorder := record.NewFakeRecorder(10)
135+
set := newStatefulSet(3)
136+
pod := newStatefulSetPod(set, 0)
137+
fakeClient := &fake.Clientset{}
138+
pvcs := getPersistentVolumeClaims(set, pod)
139+
pvcIndexer := cache.NewIndexer(cache.MetaNamespaceKeyFunc, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc})
140+
deleteTime := time.Date(2019, time.January, 1, 0, 0, 0, 0, time.UTC)
141+
for k := range pvcs {
142+
pvc := pvcs[k]
143+
pvc.DeletionTimestamp = &metav1.Time{Time: deleteTime}
144+
pvcIndexer.Add(&pvc)
145+
}
146+
pvcLister := corelisters.NewPersistentVolumeClaimLister(pvcIndexer)
147+
control := NewRealStatefulPodControl(fakeClient, nil, nil, pvcLister, recorder)
148+
fakeClient.AddReactor("create", "persistentvolumeclaims", func(action core.Action) (bool, runtime.Object, error) {
149+
create := action.(core.CreateAction)
150+
return true, create.GetObject(), nil
151+
})
152+
fakeClient.AddReactor("create", "pods", func(action core.Action) (bool, runtime.Object, error) {
153+
create := action.(core.CreateAction)
154+
return true, create.GetObject(), nil
155+
})
156+
if err := control.CreateStatefulPod(set, pod); err == nil {
157+
t.Error("Failed to produce error on deleting PVC")
158+
}
159+
events := collectEvents(recorder.Events)
160+
if eventCount := len(events); eventCount != 1 {
161+
t.Errorf("Deleting PVC: got %d events, but want 1", eventCount)
162+
}
163+
for i := range events {
164+
if !strings.Contains(events[i], v1.EventTypeWarning) {
165+
t.Errorf("Found unexpected non-warning event %s", events[i])
166+
}
167+
}
168+
}
131169

132170
type fakeIndexer struct {
133171
cache.Indexer

0 commit comments

Comments
 (0)