...

Source file src/k8s.io/kubernetes/cmd/kubeadm/app/phases/kubelet/config.go

Documentation: k8s.io/kubernetes/cmd/kubeadm/app/phases/kubelet

     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  }
   189  

View as plain text