Skip to content

Commit 243e740

Browse files
authored
Merge pull request kubernetes#74809 from oxddr/secrets-and-maps
Fix secret/configmap management for terminated pods
2 parents 50bf223 + 52913c5 commit 243e740

File tree

3 files changed

+66
-7
lines changed

3 files changed

+66
-7
lines changed

pkg/kubelet/pod/pod_manager.go

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -168,20 +168,40 @@ func (pm *basicManager) UpdatePod(pod *v1.Pod) {
168168
}
169169
}
170170

171+
func isPodInTerminatedState(pod *v1.Pod) bool {
172+
return pod.Status.Phase == v1.PodFailed || pod.Status.Phase == v1.PodSucceeded
173+
}
174+
171175
// updatePodsInternal replaces the given pods in the current state of the
172176
// manager, updating the various indices. The caller is assumed to hold the
173177
// lock.
174178
func (pm *basicManager) updatePodsInternal(pods ...*v1.Pod) {
175179
for _, pod := range pods {
176180
if pm.secretManager != nil {
177-
// TODO: Consider detecting only status update and in such case do
178-
// not register pod, as it doesn't really matter.
179-
pm.secretManager.RegisterPod(pod)
181+
if isPodInTerminatedState(pod) {
182+
// Pods that are in terminated state and no longer running can be
183+
// ignored as they no longer require access to secrets.
184+
// It is especially important in watch-based manager, to avoid
185+
// unnecessary watches for terminated pods waiting for GC.
186+
pm.secretManager.UnregisterPod(pod)
187+
} else {
188+
// TODO: Consider detecting only status update and in such case do
189+
// not register pod, as it doesn't really matter.
190+
pm.secretManager.RegisterPod(pod)
191+
}
180192
}
181193
if pm.configMapManager != nil {
182-
// TODO: Consider detecting only status update and in such case do
183-
// not register pod, as it doesn't really matter.
184-
pm.configMapManager.RegisterPod(pod)
194+
if isPodInTerminatedState(pod) {
195+
// Pods that are in terminated state and no longer running can be
196+
// ignored as they no longer require access to configmaps.
197+
// It is especially important in watch-based manager, to avoid
198+
// unnecessary watches for terminated pods waiting for GC.
199+
pm.configMapManager.UnregisterPod(pod)
200+
} else {
201+
// TODO: Consider detecting only status update and in such case do
202+
// not register pod, as it doesn't really matter.
203+
pm.configMapManager.RegisterPod(pod)
204+
}
185205
}
186206
podFullName := kubecontainer.GetPodFullName(pod)
187207
// This logic relies on a static pod and its mirror to have the same name.

pkg/kubelet/util/manager/cache_based_manager_test.go

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import (
2424
"testing"
2525
"time"
2626

27-
"k8s.io/api/core/v1"
27+
v1 "k8s.io/api/core/v1"
2828

2929
apierrors "k8s.io/apimachinery/pkg/api/errors"
3030
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -429,6 +429,41 @@ func TestCacheInvalidation(t *testing.T) {
429429
fakeClient.ClearActions()
430430
}
431431

432+
func TestRegisterIdempotence(t *testing.T) {
433+
fakeClient := &fake.Clientset{}
434+
fakeClock := clock.NewFakeClock(time.Now())
435+
store := newSecretStore(fakeClient, fakeClock, noObjectTTL, time.Minute)
436+
manager := newCacheBasedSecretManager(store)
437+
438+
s1 := secretsToAttach{
439+
imagePullSecretNames: []string{"s1"},
440+
}
441+
442+
refs := func(ns, name string) int {
443+
store.lock.Lock()
444+
defer store.lock.Unlock()
445+
item, ok := store.items[objectKey{ns, name}]
446+
if !ok {
447+
return 0
448+
}
449+
return item.refCount
450+
}
451+
452+
manager.RegisterPod(podWithSecrets("ns1", "name1", s1))
453+
assert.Equal(t, 1, refs("ns1", "s1"))
454+
manager.RegisterPod(podWithSecrets("ns1", "name1", s1))
455+
assert.Equal(t, 1, refs("ns1", "s1"))
456+
manager.RegisterPod(podWithSecrets("ns1", "name2", s1))
457+
assert.Equal(t, 2, refs("ns1", "s1"))
458+
459+
manager.UnregisterPod(podWithSecrets("ns1", "name1", s1))
460+
assert.Equal(t, 1, refs("ns1", "s1"))
461+
manager.UnregisterPod(podWithSecrets("ns1", "name1", s1))
462+
assert.Equal(t, 1, refs("ns1", "s1"))
463+
manager.UnregisterPod(podWithSecrets("ns1", "name2", s1))
464+
assert.Equal(t, 0, refs("ns1", "s1"))
465+
}
466+
432467
func TestCacheRefcounts(t *testing.T) {
433468
fakeClient := &fake.Clientset{}
434469
fakeClock := clock.NewFakeClock(time.Now())

pkg/kubelet/util/manager/manager.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,14 @@ type Manager interface {
3232
// i.e. should not block on network operations.
3333

3434
// RegisterPod registers all objects referenced from a given pod.
35+
//
36+
// NOTE: All implementations of RegisterPod should be idempotent.
3537
RegisterPod(pod *v1.Pod)
3638

3739
// UnregisterPod unregisters objects referenced from a given pod that are not
3840
// used by any other registered pod.
41+
//
42+
// NOTE: All implementations of UnregisterPod should be idempotent.
3943
UnregisterPod(pod *v1.Pod)
4044
}
4145

0 commit comments

Comments
 (0)