k8s.io/kubernetes@v1.31.0-alpha.0.0.20240520171757-56147500dadc/cmd/kubeadm/app/phases/kubelet/config.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 kubelet 18 19 import ( 20 "fmt" 21 "io" 22 "os" 23 "path/filepath" 24 25 "github.com/pkg/errors" 26 27 v1 "k8s.io/api/core/v1" 28 rbac "k8s.io/api/rbac/v1" 29 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 30 clientset "k8s.io/client-go/kubernetes" 31 kubeletconfig "k8s.io/kubelet/config/v1beta1" 32 "sigs.k8s.io/yaml" 33 34 kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" 35 "k8s.io/kubernetes/cmd/kubeadm/app/componentconfigs" 36 kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants" 37 "k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient" 38 "k8s.io/kubernetes/cmd/kubeadm/app/util/patches" 39 ) 40 41 // WriteConfigToDisk writes the kubelet config object down to a file 42 // Used at "kubeadm init" and "kubeadm upgrade" time 43 func WriteConfigToDisk(cfg *kubeadmapi.ClusterConfiguration, kubeletDir, patchesDir string, output io.Writer) error { 44 kubeletCfg, ok := cfg.ComponentConfigs[componentconfigs.KubeletGroup] 45 if !ok { 46 return errors.New("no kubelet component config found") 47 } 48 49 if err := kubeletCfg.Mutate(); err != nil { 50 return err 51 } 52 53 kubeletBytes, err := kubeletCfg.Marshal() 54 if err != nil { 55 return err 56 } 57 58 // Apply patches to the KubeletConfiguration 59 if len(patchesDir) != 0 { 60 kubeletBytes, err = applyKubeletConfigPatches(kubeletBytes, patchesDir, output) 61 if err != nil { 62 return errors.Wrap(err, "could not apply patches to the KubeletConfiguration") 63 } 64 } 65 66 return writeConfigBytesToDisk(kubeletBytes, kubeletDir) 67 } 68 69 // CreateConfigMap creates a ConfigMap with the generic kubelet configuration. 70 // Used at "kubeadm init" and "kubeadm upgrade" time 71 func CreateConfigMap(cfg *kubeadmapi.ClusterConfiguration, client clientset.Interface) error { 72 configMapName := kubeadmconstants.KubeletBaseConfigurationConfigMap 73 fmt.Printf("[kubelet] Creating a ConfigMap %q in namespace %s with the configuration for the kubelets in the cluster\n", configMapName, metav1.NamespaceSystem) 74 75 kubeletCfg, ok := cfg.ComponentConfigs[componentconfigs.KubeletGroup] 76 if !ok { 77 return errors.New("no kubelet component config found in the active component config set") 78 } 79 80 kubeletBytes, err := kubeletCfg.Marshal() 81 if err != nil { 82 return err 83 } 84 85 configMap := &v1.ConfigMap{ 86 ObjectMeta: metav1.ObjectMeta{ 87 Name: configMapName, 88 Namespace: metav1.NamespaceSystem, 89 }, 90 Data: map[string]string{ 91 kubeadmconstants.KubeletBaseConfigurationConfigMapKey: string(kubeletBytes), 92 }, 93 } 94 95 if !kubeletCfg.IsUserSupplied() { 96 componentconfigs.SignConfigMap(configMap) 97 } 98 99 if err := apiclient.CreateOrUpdateConfigMap(client, configMap); err != nil { 100 return err 101 } 102 103 if err := createConfigMapRBACRules(client); err != nil { 104 return errors.Wrap(err, "error creating kubelet configuration configmap RBAC rules") 105 } 106 return nil 107 } 108 109 // createConfigMapRBACRules creates the RBAC rules for exposing the base kubelet ConfigMap in the kube-system namespace to unauthenticated users 110 func createConfigMapRBACRules(client clientset.Interface) error { 111 if err := apiclient.CreateOrUpdateRole(client, &rbac.Role{ 112 ObjectMeta: metav1.ObjectMeta{ 113 Name: kubeadmconstants.KubeletBaseConfigMapRole, 114 Namespace: metav1.NamespaceSystem, 115 }, 116 Rules: []rbac.PolicyRule{ 117 { 118 Verbs: []string{"get"}, 119 APIGroups: []string{""}, 120 Resources: []string{"configmaps"}, 121 ResourceNames: []string{kubeadmconstants.KubeletBaseConfigurationConfigMap}, 122 }, 123 }, 124 }); err != nil { 125 return err 126 } 127 128 return apiclient.CreateOrUpdateRoleBinding(client, &rbac.RoleBinding{ 129 ObjectMeta: metav1.ObjectMeta{ 130 Name: kubeadmconstants.KubeletBaseConfigMapRole, 131 Namespace: metav1.NamespaceSystem, 132 }, 133 RoleRef: rbac.RoleRef{ 134 APIGroup: rbac.GroupName, 135 Kind: "Role", 136 Name: kubeadmconstants.KubeletBaseConfigMapRole, 137 }, 138 Subjects: []rbac.Subject{ 139 { 140 Kind: rbac.GroupKind, 141 Name: kubeadmconstants.NodesGroup, 142 }, 143 { 144 Kind: rbac.GroupKind, 145 Name: kubeadmconstants.NodeBootstrapTokenAuthGroup, 146 }, 147 }, 148 }) 149 } 150 151 // writeConfigBytesToDisk writes a byte slice down to disk at the specific location of the kubelet config file 152 func writeConfigBytesToDisk(b []byte, kubeletDir string) error { 153 configFile := filepath.Join(kubeletDir, kubeadmconstants.KubeletConfigurationFileName) 154 fmt.Printf("[kubelet-start] Writing kubelet configuration to file %q\n", configFile) 155 156 // creates target folder if not already exists 157 if err := os.MkdirAll(kubeletDir, 0700); err != nil { 158 return errors.Wrapf(err, "failed to create directory %q", kubeletDir) 159 } 160 161 if err := os.WriteFile(configFile, b, 0644); err != nil { 162 return errors.Wrapf(err, "failed to write kubelet configuration to the file %q", configFile) 163 } 164 return nil 165 } 166 167 // applyKubeletConfigPatches reads patches from a directory and applies them over the input kubeletBytes 168 func applyKubeletConfigPatches(kubeletBytes []byte, patchesDir string, output io.Writer) ([]byte, error) { 169 patchManager, err := patches.GetPatchManagerForPath(patchesDir, patches.KnownTargets(), output) 170 if err != nil { 171 return nil, err 172 } 173 174 patchTarget := &patches.PatchTarget{ 175 Name: patches.KubeletConfiguration, 176 StrategicMergePatchObject: kubeletconfig.KubeletConfiguration{}, 177 Data: kubeletBytes, 178 } 179 if err := patchManager.ApplyPatchesToTarget(patchTarget); err != nil { 180 return nil, err 181 } 182 183 kubeletBytes, err = yaml.JSONToYAML(patchTarget.Data) 184 if err != nil { 185 return nil, err 186 } 187 return kubeletBytes, nil 188 }