From bf7138652f7695cae801ecaaa5d1d99ef17f8529 Mon Sep 17 00:00:00 2001 From: Wojciech Tyczynski Date: Fri, 20 Jan 2017 09:12:01 +0100 Subject: [PATCH 1/2] SecretVolume using secret manager --- .../attachdetach/attach_detach_controller.go | 6 +++++ .../volume/persistentvolume/volume_host.go | 6 +++++ pkg/kubelet/kubelet.go | 2 +- pkg/kubelet/kubelet_test.go | 2 +- pkg/kubelet/runonce_test.go | 5 ++-- pkg/kubelet/volume_host.go | 8 ++++++ pkg/volume/plugins.go | 5 +++- pkg/volume/secret/BUILD | 1 - pkg/volume/secret/secret.go | 26 +++++++++---------- pkg/volume/testing/testing.go | 6 +++++ 10 files changed, 47 insertions(+), 20 deletions(-) diff --git a/pkg/controller/volume/attachdetach/attach_detach_controller.go b/pkg/controller/volume/attachdetach/attach_detach_controller.go index a679f34db8..af7d65a995 100644 --- a/pkg/controller/volume/attachdetach/attach_detach_controller.go +++ b/pkg/controller/volume/attachdetach/attach_detach_controller.go @@ -620,3 +620,9 @@ func (adc *attachDetachController) GetHostIP() (net.IP, error) { func (adc *attachDetachController) GetNodeAllocatable() (v1.ResourceList, error) { return v1.ResourceList{}, nil } + +func (adc *attachDetachController) GetSecretFunc() func(namespace, name string) (*v1.Secret, error) { + return func(_, _ string) (*v1.Secret, error) { + return nil, fmt.Errorf("GetSecret unsupported in attachDetachController") + } +} diff --git a/pkg/controller/volume/persistentvolume/volume_host.go b/pkg/controller/volume/persistentvolume/volume_host.go index f00dd23c49..c495c00215 100644 --- a/pkg/controller/volume/persistentvolume/volume_host.go +++ b/pkg/controller/volume/persistentvolume/volume_host.go @@ -80,3 +80,9 @@ func (ctrl *PersistentVolumeController) GetHostIP() (net.IP, error) { func (ctrl *PersistentVolumeController) GetNodeAllocatable() (v1.ResourceList, error) { return v1.ResourceList{}, nil } + +func (adc *PersistentVolumeController) GetSecretFunc() func(namespace, name string) (*v1.Secret, error) { + return func(_, _ string) (*v1.Secret, error) { + return nil, fmt.Errorf("GetSecret unsupported in PersistentVolumeController") + } +} diff --git a/pkg/kubelet/kubelet.go b/pkg/kubelet/kubelet.go index 851401b166..d114eea150 100644 --- a/pkg/kubelet/kubelet.go +++ b/pkg/kubelet/kubelet.go @@ -727,7 +727,7 @@ func NewMainKubelet(kubeCfg *componentconfig.KubeletConfiguration, kubeDeps *Kub kubeDeps.Recorder) klet.volumePluginMgr, err = - NewInitializedVolumePluginMgr(klet, kubeDeps.VolumePlugins) + NewInitializedVolumePluginMgr(klet, secretManager, kubeDeps.VolumePlugins) if err != nil { return nil, err } diff --git a/pkg/kubelet/kubelet_test.go b/pkg/kubelet/kubelet_test.go index c8e6b437f1..0ffcd416d6 100644 --- a/pkg/kubelet/kubelet_test.go +++ b/pkg/kubelet/kubelet_test.go @@ -249,7 +249,7 @@ func newTestKubeletWithImageList( plug := &volumetest.FakeVolumePlugin{PluginName: "fake", Host: nil} kubelet.volumePluginMgr, err = - NewInitializedVolumePluginMgr(kubelet, []volume.VolumePlugin{plug}) + NewInitializedVolumePluginMgr(kubelet, fakeSecretManager, []volume.VolumePlugin{plug}) require.NoError(t, err, "Failed to initialize VolumePluginMgr") kubelet.mounter = &mount.FakeMounter{} diff --git a/pkg/kubelet/runonce_test.go b/pkg/kubelet/runonce_test.go index 91bff360bf..50bf546df5 100644 --- a/pkg/kubelet/runonce_test.go +++ b/pkg/kubelet/runonce_test.go @@ -60,8 +60,9 @@ func TestRunOnce(t *testing.T) { Usage: 9 * mb, Capacity: 10 * mb, }, nil) + fakeSecretManager := secret.NewFakeManager() podManager := kubepod.NewBasicPodManager( - podtest.NewFakeMirrorClient(), secret.NewFakeManager()) + podtest.NewFakeMirrorClient(), fakeSecretManager) diskSpaceManager, _ := newDiskSpaceManager(cadvisor, DiskSpacePolicy{}) fakeRuntime := &containertest.FakeRuntime{} basePath, err := utiltesting.MkTmpdir("kubelet") @@ -92,7 +93,7 @@ func TestRunOnce(t *testing.T) { plug := &volumetest.FakeVolumePlugin{PluginName: "fake", Host: nil} kb.volumePluginMgr, err = - NewInitializedVolumePluginMgr(kb, []volume.VolumePlugin{plug}) + NewInitializedVolumePluginMgr(kb, fakeSecretManager, []volume.VolumePlugin{plug}) if err != nil { t.Fatalf("failed to initialize VolumePluginMgr: %v", err) } diff --git a/pkg/kubelet/volume_host.go b/pkg/kubelet/volume_host.go index 626a339d3f..547bf9b0cc 100644 --- a/pkg/kubelet/volume_host.go +++ b/pkg/kubelet/volume_host.go @@ -24,6 +24,7 @@ import ( "k8s.io/kubernetes/pkg/api/v1" "k8s.io/kubernetes/pkg/client/clientset_generated/clientset" "k8s.io/kubernetes/pkg/cloudprovider" + "k8s.io/kubernetes/pkg/kubelet/secret" "k8s.io/kubernetes/pkg/util/io" "k8s.io/kubernetes/pkg/util/mount" "k8s.io/kubernetes/pkg/volume" @@ -37,10 +38,12 @@ import ( // plugins - used to initialize volumePluginMgr func NewInitializedVolumePluginMgr( kubelet *Kubelet, + secretManager secret.Manager, plugins []volume.VolumePlugin) (*volume.VolumePluginMgr, error) { kvh := &kubeletVolumeHost{ kubelet: kubelet, volumePluginMgr: volume.VolumePluginMgr{}, + secretManager: secretManager, } if err := kvh.volumePluginMgr.InitPlugins(plugins, kvh); err != nil { @@ -62,6 +65,7 @@ func (kvh *kubeletVolumeHost) GetPluginDir(pluginName string) string { type kubeletVolumeHost struct { kubelet *Kubelet volumePluginMgr volume.VolumePluginMgr + secretManager secret.Manager } func (kvh *kubeletVolumeHost) GetPodVolumeDir(podUID types.UID, pluginName string, volumeName string) string { @@ -132,3 +136,7 @@ func (kvh *kubeletVolumeHost) GetNodeAllocatable() (v1.ResourceList, error) { } return node.Status.Allocatable, nil } + +func (kvh *kubeletVolumeHost) GetSecretFunc() func(namespace, name string) (*v1.Secret, error) { + return kvh.secretManager.GetSecret +} diff --git a/pkg/volume/plugins.go b/pkg/volume/plugins.go index 58af1ac52f..574419612c 100644 --- a/pkg/volume/plugins.go +++ b/pkg/volume/plugins.go @@ -213,8 +213,11 @@ type VolumeHost interface { // Returns host IP or nil in the case of error. GetHostIP() (net.IP, error) - // Returns node allocatable + // Returns node allocatable. GetNodeAllocatable() (v1.ResourceList, error) + + // Returns a function that returns a secret. + GetSecretFunc() func(namespace, name string) (*v1.Secret, error) } // VolumePluginMgr tracks registered plugins. diff --git a/pkg/volume/secret/BUILD b/pkg/volume/secret/BUILD index 7b23fa7b37..c324db545d 100644 --- a/pkg/volume/secret/BUILD +++ b/pkg/volume/secret/BUILD @@ -23,7 +23,6 @@ go_library( "//pkg/volume:go_default_library", "//pkg/volume/util:go_default_library", "//vendor:github.com/golang/glog", - "//vendor:k8s.io/apimachinery/pkg/apis/meta/v1", "//vendor:k8s.io/apimachinery/pkg/types", ], ) diff --git a/pkg/volume/secret/secret.go b/pkg/volume/secret/secret.go index 7daf0d436e..9d35e8918f 100644 --- a/pkg/volume/secret/secret.go +++ b/pkg/volume/secret/secret.go @@ -22,7 +22,6 @@ import ( "runtime" "github.com/golang/glog" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" "k8s.io/kubernetes/pkg/api/v1" ioutil "k8s.io/kubernetes/pkg/util/io" @@ -43,7 +42,8 @@ const ( // secretPlugin implements the VolumePlugin interface. type secretPlugin struct { - host volume.VolumeHost + host volume.VolumeHost + getSecret func(namespace, name string) (*v1.Secret, error) } var _ volume.VolumePlugin = &secretPlugin{} @@ -60,6 +60,7 @@ func getPath(uid types.UID, volName string, host volume.VolumeHost) string { func (plugin *secretPlugin) Init(host volume.VolumeHost) error { plugin.host = host + plugin.getSecret = host.GetSecretFunc() return nil } @@ -94,9 +95,10 @@ func (plugin *secretPlugin) NewMounter(spec *volume.Spec, pod *v1.Pod, opts volu plugin.host.GetWriter(), volume.NewCachedMetrics(volume.NewMetricsDu(getPath(pod.UID, spec.Name(), plugin.host))), }, - source: *spec.Volume.Secret, - pod: *pod, - opts: &opts, + source: *spec.Volume.Secret, + pod: *pod, + opts: &opts, + getSecret: plugin.getSecret, }, nil } @@ -145,9 +147,10 @@ func (sv *secretVolume) GetPath() string { type secretVolumeMounter struct { *secretVolume - source v1.SecretVolumeSource - pod v1.Pod - opts *volume.VolumeOptions + source v1.SecretVolumeSource + pod v1.Pod + opts *volume.VolumeOptions + getSecret func(namespace, name string) (*v1.Secret, error) } var _ volume.Mounter = &secretVolumeMounter{} @@ -188,12 +191,7 @@ func (b *secretVolumeMounter) SetUpAt(dir string, fsGroup *int64) error { return err } - kubeClient := b.plugin.host.GetKubeClient() - if kubeClient == nil { - return fmt.Errorf("Cannot setup secret volume %v because kube client is not configured", b.volName) - } - - secret, err := kubeClient.Core().Secrets(b.pod.Namespace).Get(b.source.SecretName, metav1.GetOptions{}) + secret, err := b.getSecret(b.pod.Namespace, b.source.SecretName) if err != nil { glog.Errorf("Couldn't get secret %v/%v", b.pod.Namespace, b.source.SecretName) return err diff --git a/pkg/volume/testing/testing.go b/pkg/volume/testing/testing.go index 5d2894e523..69620c1973 100644 --- a/pkg/volume/testing/testing.go +++ b/pkg/volume/testing/testing.go @@ -127,6 +127,12 @@ func (f *fakeVolumeHost) GetNodeAllocatable() (v1.ResourceList, error) { return v1.ResourceList{}, nil } +func (f *fakeVolumeHost) GetSecretFunc() func(namespace, name string) (*v1.Secret, error) { + return func(namespace, name string) (*v1.Secret, error) { + return f.kubeClient.Core().Secrets(namespace).Get(name, metav1.GetOptions{}) + } +} + func ProbeVolumePlugins(config VolumeConfig) []VolumePlugin { if _, ok := config.OtherAttributes["fake-property"]; ok { return []VolumePlugin{ From e0784f2e00e1aa7f5a89309b1220982354fe9597 Mon Sep 17 00:00:00 2001 From: Wojciech Tyczynski Date: Fri, 20 Jan 2017 11:31:29 +0100 Subject: [PATCH 2/2] Propage secret volumes in secret manager --- pkg/kubelet/secret/secret_manager.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/pkg/kubelet/secret/secret_manager.go b/pkg/kubelet/secret/secret_manager.go index eb9f8dec3c..1ca703c040 100644 --- a/pkg/kubelet/secret/secret_manager.go +++ b/pkg/kubelet/secret/secret_manager.go @@ -212,8 +212,6 @@ func (c *cachingSecretManager) GetSecret(namespace, name string) (*v1.Secret, er return c.secretStore.Get(namespace, name) } -// TODO: Before we will use secretManager in other places (e.g. for secret volumes) -// we should update this function to also get secrets from those places. func getSecretNames(pod *v1.Pod) sets.String { result := sets.NewString() for _, reference := range pod.Spec.ImagePullSecrets { @@ -226,6 +224,11 @@ func getSecretNames(pod *v1.Pod) sets.String { } } } + for i := range pod.Spec.Volumes { + if source := pod.Spec.Volumes[i].Secret; source != nil { + result.Insert(source.SecretName) + } + } return result }