k8s.io/kubernetes@v1.29.3/pkg/kubelet/configmap/configmap_manager.go (about) 1 /* 2 Copyright 2017 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 configmap 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 interface provides methods for Kubelet to manage ConfigMap. 38 type Manager interface { 39 // Get configmap by configmap namespace and name. 40 GetConfigMap(namespace, name string) (*v1.ConfigMap, error) 41 42 // WARNING: Register/UnregisterPod functions should be efficient, 43 // i.e. should not block on network operations. 44 45 // RegisterPod registers all configmaps from a given pod. 46 RegisterPod(pod *v1.Pod) 47 48 // UnregisterPod unregisters configmaps from a given pod that are not 49 // used by any other registered pod. 50 UnregisterPod(pod *v1.Pod) 51 } 52 53 // simpleConfigMapManager implements ConfigMap Manager interface with 54 // simple operations to apiserver. 55 type simpleConfigMapManager struct { 56 kubeClient clientset.Interface 57 } 58 59 // NewSimpleConfigMapManager creates a new ConfigMapManager instance. 60 func NewSimpleConfigMapManager(kubeClient clientset.Interface) Manager { 61 return &simpleConfigMapManager{kubeClient: kubeClient} 62 } 63 64 func (s *simpleConfigMapManager) GetConfigMap(namespace, name string) (*v1.ConfigMap, error) { 65 return s.kubeClient.CoreV1().ConfigMaps(namespace).Get(context.TODO(), name, metav1.GetOptions{}) 66 } 67 68 func (s *simpleConfigMapManager) RegisterPod(pod *v1.Pod) { 69 } 70 71 func (s *simpleConfigMapManager) UnregisterPod(pod *v1.Pod) { 72 } 73 74 // configMapManager keeps a cache of all configmaps necessary 75 // for registered pods. Different implementation of the store 76 // may result in different semantics for freshness of configmaps 77 // (e.g. ttl-based implementation vs watch-based implementation). 78 type configMapManager struct { 79 manager manager.Manager 80 } 81 82 func (c *configMapManager) GetConfigMap(namespace, name string) (*v1.ConfigMap, error) { 83 object, err := c.manager.GetObject(namespace, name) 84 if err != nil { 85 return nil, err 86 } 87 if configmap, ok := object.(*v1.ConfigMap); ok { 88 return configmap, nil 89 } 90 return nil, fmt.Errorf("unexpected object type: %v", object) 91 } 92 93 func (c *configMapManager) RegisterPod(pod *v1.Pod) { 94 c.manager.RegisterPod(pod) 95 } 96 97 func (c *configMapManager) UnregisterPod(pod *v1.Pod) { 98 c.manager.UnregisterPod(pod) 99 } 100 101 func getConfigMapNames(pod *v1.Pod) sets.String { 102 result := sets.NewString() 103 podutil.VisitPodConfigmapNames(pod, func(name string) bool { 104 result.Insert(name) 105 return true 106 }) 107 return result 108 } 109 110 const ( 111 defaultTTL = time.Minute 112 ) 113 114 // NewCachingConfigMapManager creates a manager that keeps a cache of all configmaps 115 // necessary for registered pods. 116 // It implement the following logic: 117 // - whenever a pod is create or updated, the cached versions of all configmaps 118 // are invalidated 119 // - every GetObject() call tries to fetch the value from local cache; if it is 120 // not there, invalidated or too old, we fetch it from apiserver and refresh the 121 // value in cache; otherwise it is just fetched from cache 122 func NewCachingConfigMapManager(kubeClient clientset.Interface, getTTL manager.GetObjectTTLFunc) Manager { 123 getConfigMap := func(namespace, name string, opts metav1.GetOptions) (runtime.Object, error) { 124 return kubeClient.CoreV1().ConfigMaps(namespace).Get(context.TODO(), name, opts) 125 } 126 configMapStore := manager.NewObjectStore(getConfigMap, clock.RealClock{}, getTTL, defaultTTL) 127 return &configMapManager{ 128 manager: manager.NewCacheBasedManager(configMapStore, getConfigMapNames), 129 } 130 } 131 132 // NewWatchingConfigMapManager creates a manager that keeps a cache of all configmaps 133 // necessary for registered pods. 134 // It implements the following logic: 135 // - whenever a pod is created or updated, we start individual watches for all 136 // referenced objects that aren't referenced from other registered pods 137 // - every GetObject() returns a value from local cache propagated via watches 138 func NewWatchingConfigMapManager(kubeClient clientset.Interface, resyncInterval time.Duration) Manager { 139 listConfigMap := func(namespace string, opts metav1.ListOptions) (runtime.Object, error) { 140 return kubeClient.CoreV1().ConfigMaps(namespace).List(context.TODO(), opts) 141 } 142 watchConfigMap := func(namespace string, opts metav1.ListOptions) (watch.Interface, error) { 143 return kubeClient.CoreV1().ConfigMaps(namespace).Watch(context.TODO(), opts) 144 } 145 newConfigMap := func() runtime.Object { 146 return &v1.ConfigMap{} 147 } 148 isImmutable := func(object runtime.Object) bool { 149 if configMap, ok := object.(*v1.ConfigMap); ok { 150 return configMap.Immutable != nil && *configMap.Immutable 151 } 152 return false 153 } 154 gr := corev1.Resource("configmap") 155 return &configMapManager{ 156 manager: manager.NewWatchBasedManager(listConfigMap, watchConfigMap, newConfigMap, isImmutable, gr, resyncInterval, getConfigMapNames), 157 } 158 }