Skip to content

Commit 69f5f5e

Browse files
authored
Merge pull request kubernetes#67978 from WanLinghao/token_controller_improve
remove idle tokens in kubelet token manager
2 parents 023892a + 060f3a8 commit 69f5f5e

File tree

10 files changed

+240
-5
lines changed

10 files changed

+240
-5
lines changed

pkg/controller/volume/attachdetach/attach_detach_controller.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -729,6 +729,12 @@ func (adc *attachDetachController) GetServiceAccountTokenFunc() func(_, _ string
729729
}
730730
}
731731

732+
func (adc *attachDetachController) DeleteServiceAccountTokenFunc() func(types.UID) {
733+
return func(types.UID) {
734+
glog.Errorf("DeleteServiceAccountToken unsupported in attachDetachController")
735+
}
736+
}
737+
732738
func (adc *attachDetachController) GetExec(pluginName string) mount.Exec {
733739
return mount.NewOsExec()
734740
}

pkg/controller/volume/expand/expand_controller.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,12 @@ func (expc *expandController) GetServiceAccountTokenFunc() func(_, _ string, _ *
317317
}
318318
}
319319

320+
func (expc *expandController) DeleteServiceAccountTokenFunc() func(types.UID) {
321+
return func(types.UID) {
322+
glog.Errorf("DeleteServiceAccountToken unsupported in expandController")
323+
}
324+
}
325+
320326
func (expc *expandController) GetNodeLabels() (map[string]string, error) {
321327
return nil, fmt.Errorf("GetNodeLabels unsupported in expandController")
322328
}

pkg/controller/volume/persistentvolume/volume_host.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"fmt"
2121
"net"
2222

23+
"github.com/golang/glog"
2324
authenticationv1 "k8s.io/api/authentication/v1"
2425
"k8s.io/api/core/v1"
2526
"k8s.io/apimachinery/pkg/types"
@@ -109,6 +110,12 @@ func (ctrl *PersistentVolumeController) GetServiceAccountTokenFunc() func(_, _ s
109110
}
110111
}
111112

113+
func (ctrl *PersistentVolumeController) DeleteServiceAccountTokenFunc() func(types.UID) {
114+
return func(types.UID) {
115+
glog.Errorf("DeleteServiceAccountToken unsupported in PersistentVolumeController")
116+
}
117+
}
118+
112119
func (adc *PersistentVolumeController) GetExec(pluginName string) mount.Exec {
113120
return mount.NewOsExec()
114121
}

pkg/kubelet/token/BUILD

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ go_library(
2121
visibility = ["//visibility:public"],
2222
deps = [
2323
"//staging/src/k8s.io/api/authentication/v1:go_default_library",
24+
"//staging/src/k8s.io/apimachinery/pkg/types:go_default_library",
2425
"//staging/src/k8s.io/apimachinery/pkg/util/clock:go_default_library",
2526
"//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library",
2627
"//staging/src/k8s.io/client-go/kubernetes:go_default_library",
@@ -35,6 +36,7 @@ go_test(
3536
deps = [
3637
"//staging/src/k8s.io/api/authentication/v1:go_default_library",
3738
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
39+
"//staging/src/k8s.io/apimachinery/pkg/types:go_default_library",
3840
"//staging/src/k8s.io/apimachinery/pkg/util/clock:go_default_library",
3941
],
4042
)

pkg/kubelet/token/token_manager.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import (
2626

2727
"github.com/golang/glog"
2828
authenticationv1 "k8s.io/api/authentication/v1"
29+
"k8s.io/apimachinery/pkg/types"
2930
"k8s.io/apimachinery/pkg/util/clock"
3031
"k8s.io/apimachinery/pkg/util/wait"
3132
clientset "k8s.io/client-go/kubernetes"
@@ -98,6 +99,18 @@ func (m *Manager) GetServiceAccountToken(namespace, name string, tr *authenticat
9899
return tr, nil
99100
}
100101

102+
// DeleteServiceAccountToken should be invoked when pod got deleted. It simply
103+
// clean token manager cache.
104+
func (m *Manager) DeleteServiceAccountToken(podUID types.UID) {
105+
m.cacheMutex.Lock()
106+
defer m.cacheMutex.Unlock()
107+
for k, tr := range m.cache {
108+
if tr.Spec.BoundObjectRef.UID == podUID {
109+
delete(m.cache, k)
110+
}
111+
}
112+
}
113+
101114
func (m *Manager) cleanup() {
102115
m.cacheMutex.Lock()
103116
defer m.cacheMutex.Unlock()

pkg/kubelet/token/token_manager_test.go

Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323

2424
authenticationv1 "k8s.io/api/authentication/v1"
2525
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
26+
"k8s.io/apimachinery/pkg/types"
2627
"k8s.io/apimachinery/pkg/util/clock"
2728
)
2829

@@ -175,6 +176,189 @@ func TestRequiresRefresh(t *testing.T) {
175176
}
176177
}
177178

179+
func TestDeleteServiceAccountToken(t *testing.T) {
180+
type request struct {
181+
name, namespace string
182+
tr authenticationv1.TokenRequest
183+
shouldFail bool
184+
}
185+
186+
cases := []struct {
187+
name string
188+
requestIndex []int
189+
deletePodUID []types.UID
190+
expLeftIndex []int
191+
}{
192+
{
193+
name: "delete none with all success requests",
194+
requestIndex: []int{0, 1, 2},
195+
expLeftIndex: []int{0, 1, 2},
196+
},
197+
{
198+
name: "delete one with all success requests",
199+
requestIndex: []int{0, 1, 2},
200+
deletePodUID: []types.UID{"fake-uid-1"},
201+
expLeftIndex: []int{1, 2},
202+
},
203+
{
204+
name: "delete two with all success requests",
205+
requestIndex: []int{0, 1, 2},
206+
deletePodUID: []types.UID{"fake-uid-1", "fake-uid-3"},
207+
expLeftIndex: []int{1},
208+
},
209+
{
210+
name: "delete all with all suceess requests",
211+
requestIndex: []int{0, 1, 2},
212+
deletePodUID: []types.UID{"fake-uid-1", "fake-uid-2", "fake-uid-3"},
213+
},
214+
{
215+
name: "delete no pod with failed requests",
216+
requestIndex: []int{0, 1, 2, 3},
217+
deletePodUID: []types.UID{},
218+
expLeftIndex: []int{0, 1, 2},
219+
},
220+
{
221+
name: "delete other pod with failed requests",
222+
requestIndex: []int{0, 1, 2, 3},
223+
deletePodUID: []types.UID{"fake-uid-2"},
224+
expLeftIndex: []int{0, 2},
225+
},
226+
{
227+
name: "delete no pod with request which success after failure",
228+
requestIndex: []int{0, 1, 2, 3, 4},
229+
deletePodUID: []types.UID{},
230+
expLeftIndex: []int{0, 1, 2, 4},
231+
},
232+
{
233+
name: "delete the pod which success after failure",
234+
requestIndex: []int{0, 1, 2, 3, 4},
235+
deletePodUID: []types.UID{"fake-uid-4"},
236+
expLeftIndex: []int{0, 1, 2},
237+
},
238+
{
239+
name: "delete other pod with request which success after failure",
240+
requestIndex: []int{0, 1, 2, 3, 4},
241+
deletePodUID: []types.UID{"fake-uid-1"},
242+
expLeftIndex: []int{1, 2, 4},
243+
},
244+
{
245+
name: "delete some pod not in the set",
246+
requestIndex: []int{0, 1, 2},
247+
deletePodUID: []types.UID{"fake-uid-100", "fake-uid-200"},
248+
expLeftIndex: []int{0, 1, 2},
249+
},
250+
}
251+
252+
for _, c := range cases {
253+
t.Run(c.name, func(t *testing.T) {
254+
requests := []request{
255+
{
256+
name: "fake-name-1",
257+
namespace: "fake-namespace-1",
258+
tr: authenticationv1.TokenRequest{
259+
Spec: authenticationv1.TokenRequestSpec{
260+
BoundObjectRef: &authenticationv1.BoundObjectReference{
261+
UID: "fake-uid-1",
262+
Name: "fake-name-1",
263+
},
264+
},
265+
},
266+
shouldFail: false,
267+
},
268+
{
269+
name: "fake-name-2",
270+
namespace: "fake-namespace-2",
271+
tr: authenticationv1.TokenRequest{
272+
Spec: authenticationv1.TokenRequestSpec{
273+
BoundObjectRef: &authenticationv1.BoundObjectReference{
274+
UID: "fake-uid-2",
275+
Name: "fake-name-2",
276+
},
277+
},
278+
},
279+
shouldFail: false,
280+
},
281+
{
282+
name: "fake-name-3",
283+
namespace: "fake-namespace-3",
284+
tr: authenticationv1.TokenRequest{
285+
Spec: authenticationv1.TokenRequestSpec{
286+
BoundObjectRef: &authenticationv1.BoundObjectReference{
287+
UID: "fake-uid-3",
288+
Name: "fake-name-3",
289+
},
290+
},
291+
},
292+
shouldFail: false,
293+
},
294+
{
295+
name: "fake-name-4",
296+
namespace: "fake-namespace-4",
297+
tr: authenticationv1.TokenRequest{
298+
Spec: authenticationv1.TokenRequestSpec{
299+
BoundObjectRef: &authenticationv1.BoundObjectReference{
300+
UID: "fake-uid-4",
301+
Name: "fake-name-4",
302+
},
303+
},
304+
},
305+
shouldFail: true,
306+
},
307+
{
308+
//exactly the same with last one, besides it will success
309+
name: "fake-name-4",
310+
namespace: "fake-namespace-4",
311+
tr: authenticationv1.TokenRequest{
312+
Spec: authenticationv1.TokenRequestSpec{
313+
BoundObjectRef: &authenticationv1.BoundObjectReference{
314+
UID: "fake-uid-4",
315+
Name: "fake-name-4",
316+
},
317+
},
318+
},
319+
shouldFail: false,
320+
},
321+
}
322+
testMgr := NewManager(nil)
323+
testMgr.clock = clock.NewFakeClock(time.Time{}.Add(30 * 24 * time.Hour))
324+
325+
successGetToken := func(_, _ string, tr *authenticationv1.TokenRequest) (*authenticationv1.TokenRequest, error) {
326+
tr.Status = authenticationv1.TokenRequestStatus{
327+
ExpirationTimestamp: metav1.Time{Time: testMgr.clock.Now().Add(10 * time.Hour)},
328+
}
329+
return tr, nil
330+
}
331+
failGetToken := func(_, _ string, tr *authenticationv1.TokenRequest) (*authenticationv1.TokenRequest, error) {
332+
return nil, fmt.Errorf("fail tr")
333+
}
334+
335+
for _, index := range c.requestIndex {
336+
req := requests[index]
337+
if req.shouldFail {
338+
testMgr.getToken = failGetToken
339+
} else {
340+
testMgr.getToken = successGetToken
341+
}
342+
testMgr.GetServiceAccountToken(req.namespace, req.name, &req.tr)
343+
}
344+
345+
for _, uid := range c.deletePodUID {
346+
testMgr.DeleteServiceAccountToken(uid)
347+
}
348+
if len(c.expLeftIndex) != len(testMgr.cache) {
349+
t.Errorf("%s got unexpected result: expected left cache size is %d, got %d", c.name, len(c.expLeftIndex), len(testMgr.cache))
350+
}
351+
for _, leftIndex := range c.expLeftIndex {
352+
r := requests[leftIndex]
353+
_, ok := testMgr.get(keyFunc(r.name, r.namespace, &r.tr))
354+
if !ok {
355+
t.Errorf("%s got unexpected result: expected token request %v exist in cache, but not", c.name, r)
356+
}
357+
}
358+
})
359+
}
360+
}
361+
178362
type fakeTokenGetter struct {
179363
count int
180364
tr *authenticationv1.TokenRequest

pkg/kubelet/volume_host.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,10 @@ func (kvh *kubeletVolumeHost) GetServiceAccountTokenFunc() func(namespace, name
200200
return kvh.tokenManager.GetServiceAccountToken
201201
}
202202

203+
func (kvh *kubeletVolumeHost) DeleteServiceAccountTokenFunc() func(podUID types.UID) {
204+
return kvh.tokenManager.DeleteServiceAccountToken
205+
}
206+
203207
func (kvh *kubeletVolumeHost) GetNodeLabels() (map[string]string, error) {
204208
node, err := kvh.kubelet.GetNode()
205209
if err != nil {

pkg/volume/plugins.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,8 @@ type VolumeHost interface {
354354

355355
GetServiceAccountTokenFunc() func(namespace, name string, tr *authenticationv1.TokenRequest) (*authenticationv1.TokenRequest, error)
356356

357+
DeleteServiceAccountTokenFunc() func(podUID types.UID)
358+
357359
// Returns an interface that should be used to execute any utilities in volume plugins
358360
GetExec(pluginName string) mount.Exec
359361

pkg/volume/projected/projected.go

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,11 @@ const (
4747
)
4848

4949
type projectedPlugin struct {
50-
host volume.VolumeHost
51-
getSecret func(namespace, name string) (*v1.Secret, error)
52-
getConfigMap func(namespace, name string) (*v1.ConfigMap, error)
53-
getServiceAccountToken func(namespace, name string, tr *authenticationv1.TokenRequest) (*authenticationv1.TokenRequest, error)
50+
host volume.VolumeHost
51+
getSecret func(namespace, name string) (*v1.Secret, error)
52+
getConfigMap func(namespace, name string) (*v1.ConfigMap, error)
53+
getServiceAccountToken func(namespace, name string, tr *authenticationv1.TokenRequest) (*authenticationv1.TokenRequest, error)
54+
deleteServiceAccountToken func(podUID types.UID)
5455
}
5556

5657
var _ volume.VolumePlugin = &projectedPlugin{}
@@ -74,6 +75,7 @@ func (plugin *projectedPlugin) Init(host volume.VolumeHost) error {
7475
plugin.getSecret = host.GetSecretFunc()
7576
plugin.getConfigMap = host.GetConfigMapFunc()
7677
plugin.getServiceAccountToken = host.GetServiceAccountTokenFunc()
78+
plugin.deleteServiceAccountToken = host.DeleteServiceAccountTokenFunc()
7779
return nil
7880
}
7981

@@ -368,7 +370,12 @@ func (c *projectedVolumeUnmounter) TearDownAt(dir string) error {
368370
if err != nil {
369371
return err
370372
}
371-
return wrapped.TearDownAt(dir)
373+
if err = wrapped.TearDownAt(dir); err != nil {
374+
return err
375+
}
376+
377+
c.plugin.deleteServiceAccountToken(c.podUID)
378+
return nil
372379
}
373380

374381
func getVolumeSource(spec *volume.Spec) (*v1.ProjectedVolumeSource, bool, error) {

pkg/volume/testing/testing.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,10 @@ func (f *fakeVolumeHost) GetServiceAccountTokenFunc() func(string, string, *auth
201201
}
202202
}
203203

204+
func (f *fakeVolumeHost) DeleteServiceAccountTokenFunc() func(types.UID) {
205+
return func(types.UID) {}
206+
}
207+
204208
func (f *fakeVolumeHost) GetNodeLabels() (map[string]string, error) {
205209
if f.nodeLabels == nil {
206210
f.nodeLabels = map[string]string{"test-label": "test-value"}

0 commit comments

Comments
 (0)