...

Source file src/k8s.io/kubernetes/pkg/kubelet/secret/secret_manager.go

Documentation: k8s.io/kubernetes/pkg/kubelet/secret

     1  /*
     2  Copyright 2016 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package secret
    18  
    19  import (
    20  	"context"
    21  	"fmt"
    22  	"time"
    23  
    24  	v1 "k8s.io/api/core/v1"
    25  	clientset "k8s.io/client-go/kubernetes"
    26  	podutil "k8s.io/kubernetes/pkg/api/v1/pod"
    27  	corev1 "k8s.io/kubernetes/pkg/apis/core/v1"
    28  	"k8s.io/kubernetes/pkg/kubelet/util/manager"
    29  
    30  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    31  	"k8s.io/apimachinery/pkg/runtime"
    32  	"k8s.io/apimachinery/pkg/util/sets"
    33  	"k8s.io/apimachinery/pkg/watch"
    34  	"k8s.io/utils/clock"
    35  )
    36  
    37  // Manager manages Kubernetes secrets. This includes retrieving
    38  // secrets or registering/unregistering them via Pods.
    39  type Manager interface {
    40  	// Get secret by secret namespace and name.
    41  	GetSecret(namespace, name string) (*v1.Secret, error)
    42  
    43  	// WARNING: Register/UnregisterPod functions should be efficient,
    44  	// i.e. should not block on network operations.
    45  
    46  	// RegisterPod registers all secrets from a given pod.
    47  	RegisterPod(pod *v1.Pod)
    48  
    49  	// UnregisterPod unregisters secrets from a given pod that are not
    50  	// used by any other registered pod.
    51  	UnregisterPod(pod *v1.Pod)
    52  }
    53  
    54  // simpleSecretManager implements SecretManager interfaces with
    55  // simple operations to apiserver.
    56  type simpleSecretManager struct {
    57  	kubeClient clientset.Interface
    58  }
    59  
    60  // NewSimpleSecretManager creates a new SecretManager instance.
    61  func NewSimpleSecretManager(kubeClient clientset.Interface) Manager {
    62  	return &simpleSecretManager{kubeClient: kubeClient}
    63  }
    64  
    65  func (s *simpleSecretManager) GetSecret(namespace, name string) (*v1.Secret, error) {
    66  	return s.kubeClient.CoreV1().Secrets(namespace).Get(context.TODO(), name, metav1.GetOptions{})
    67  }
    68  
    69  func (s *simpleSecretManager) RegisterPod(pod *v1.Pod) {
    70  }
    71  
    72  func (s *simpleSecretManager) UnregisterPod(pod *v1.Pod) {
    73  }
    74  
    75  // secretManager keeps a store with secrets necessary
    76  // for registered pods. Different implementations of the store
    77  // may result in different semantics for freshness of secrets
    78  // (e.g. ttl-based implementation vs watch-based implementation).
    79  type secretManager struct {
    80  	manager manager.Manager
    81  }
    82  
    83  func (s *secretManager) GetSecret(namespace, name string) (*v1.Secret, error) {
    84  	object, err := s.manager.GetObject(namespace, name)
    85  	if err != nil {
    86  		return nil, err
    87  	}
    88  	if secret, ok := object.(*v1.Secret); ok {
    89  		return secret, nil
    90  	}
    91  	return nil, fmt.Errorf("unexpected object type: %v", object)
    92  }
    93  
    94  func (s *secretManager) RegisterPod(pod *v1.Pod) {
    95  	s.manager.RegisterPod(pod)
    96  }
    97  
    98  func (s *secretManager) UnregisterPod(pod *v1.Pod) {
    99  	s.manager.UnregisterPod(pod)
   100  }
   101  
   102  func getSecretNames(pod *v1.Pod) sets.String {
   103  	result := sets.NewString()
   104  	podutil.VisitPodSecretNames(pod, func(name string) bool {
   105  		result.Insert(name)
   106  		return true
   107  	})
   108  	return result
   109  }
   110  
   111  const (
   112  	defaultTTL = time.Minute
   113  )
   114  
   115  // NewCachingSecretManager creates a manager that keeps a cache of all secrets
   116  // necessary for registered pods.
   117  // It implements the following logic:
   118  //   - whenever a pod is created or updated, the cached versions of all secrets
   119  //     are invalidated
   120  //   - every GetObject() call tries to fetch the value from local cache; if it is
   121  //     not there, invalidated or too old, we fetch it from apiserver and refresh the
   122  //     value in cache; otherwise it is just fetched from cache
   123  func NewCachingSecretManager(kubeClient clientset.Interface, getTTL manager.GetObjectTTLFunc) Manager {
   124  	getSecret := func(namespace, name string, opts metav1.GetOptions) (runtime.Object, error) {
   125  		return kubeClient.CoreV1().Secrets(namespace).Get(context.TODO(), name, opts)
   126  	}
   127  	secretStore := manager.NewObjectStore(getSecret, clock.RealClock{}, getTTL, defaultTTL)
   128  	return &secretManager{
   129  		manager: manager.NewCacheBasedManager(secretStore, getSecretNames),
   130  	}
   131  }
   132  
   133  // NewWatchingSecretManager creates a manager that keeps a cache of all secrets
   134  // necessary for registered pods.
   135  // It implements the following logic:
   136  //   - whenever a pod is created or updated, we start individual watches for all
   137  //     referenced objects that aren't referenced from other registered pods
   138  //   - every GetObject() returns a value from local cache propagated via watches
   139  func NewWatchingSecretManager(kubeClient clientset.Interface, resyncInterval time.Duration) Manager {
   140  	listSecret := func(namespace string, opts metav1.ListOptions) (runtime.Object, error) {
   141  		return kubeClient.CoreV1().Secrets(namespace).List(context.TODO(), opts)
   142  	}
   143  	watchSecret := func(namespace string, opts metav1.ListOptions) (watch.Interface, error) {
   144  		return kubeClient.CoreV1().Secrets(namespace).Watch(context.TODO(), opts)
   145  	}
   146  	newSecret := func() runtime.Object {
   147  		return &v1.Secret{}
   148  	}
   149  	isImmutable := func(object runtime.Object) bool {
   150  		if secret, ok := object.(*v1.Secret); ok {
   151  			return secret.Immutable != nil && *secret.Immutable
   152  		}
   153  		return false
   154  	}
   155  	gr := corev1.Resource("secret")
   156  	return &secretManager{
   157  		manager: manager.NewWatchBasedManager(listSecret, watchSecret, newSecret, isImmutable, gr, resyncInterval, getSecretNames),
   158  	}
   159  }
   160  

View as plain text