...

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

Documentation: k8s.io/kubernetes/cmd/kubeadm/app/componentconfigs

     1  /*
     2  Copyright 2019 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 componentconfigs
    18  
    19  import (
    20  	"path/filepath"
    21  
    22  	"github.com/pkg/errors"
    23  	clientset "k8s.io/client-go/kubernetes"
    24  	"k8s.io/klog/v2"
    25  	kubeletconfig "k8s.io/kubelet/config/v1beta1"
    26  	"k8s.io/utils/ptr"
    27  
    28  	kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
    29  	kubeadmapiv1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta3"
    30  	"k8s.io/kubernetes/cmd/kubeadm/app/constants"
    31  	"k8s.io/kubernetes/cmd/kubeadm/app/util/initsystem"
    32  )
    33  
    34  const (
    35  	// KubeletGroup is a pointer to the used API group name for the kubelet config
    36  	KubeletGroup = kubeletconfig.GroupName
    37  
    38  	// kubeletReadOnlyPort specifies the default insecure http server port
    39  	// 0 will disable insecure http server.
    40  	kubeletReadOnlyPort int32 = 0
    41  
    42  	// kubeletRotateCertificates specifies the default value to enable certificate rotation
    43  	kubeletRotateCertificates = true
    44  
    45  	// kubeletAuthenticationAnonymousEnabled specifies the default value to disable anonymous access
    46  	kubeletAuthenticationAnonymousEnabled = false
    47  
    48  	// kubeletAuthenticationWebhookEnabled set the default value to enable authentication webhook
    49  	kubeletAuthenticationWebhookEnabled = true
    50  
    51  	// kubeletHealthzBindAddress specifies the default healthz bind address
    52  	kubeletHealthzBindAddress = "127.0.0.1"
    53  
    54  	// kubeletSystemdResolverConfig specifies the default resolver config when systemd service is active
    55  	kubeletSystemdResolverConfig = "/run/systemd/resolve/resolv.conf"
    56  )
    57  
    58  // kubeletHandler is the handler instance for the kubelet component config
    59  var kubeletHandler = handler{
    60  	GroupVersion: kubeletconfig.SchemeGroupVersion,
    61  	AddToScheme:  kubeletconfig.AddToScheme,
    62  	CreateEmpty: func() kubeadmapi.ComponentConfig {
    63  		return &kubeletConfig{
    64  			configBase: configBase{
    65  				GroupVersion: kubeletconfig.SchemeGroupVersion,
    66  			},
    67  		}
    68  	},
    69  	fromCluster: kubeletConfigFromCluster,
    70  }
    71  
    72  func kubeletConfigFromCluster(h *handler, clientset clientset.Interface, _ *kubeadmapi.ClusterConfiguration) (kubeadmapi.ComponentConfig, error) {
    73  	configMapName := constants.KubeletBaseConfigurationConfigMap
    74  	klog.V(1).Infof("attempting to download the KubeletConfiguration from ConfigMap %q", configMapName)
    75  	cm, err := h.fromConfigMap(clientset, configMapName, constants.KubeletBaseConfigurationConfigMapKey, true)
    76  	if err != nil {
    77  		return nil, errors.Wrapf(err, "could not download the kubelet configuration from ConfigMap %q",
    78  			configMapName)
    79  	}
    80  	return cm, nil
    81  }
    82  
    83  // kubeletConfig implements the kubeadmapi.ComponentConfig interface for kubelet
    84  type kubeletConfig struct {
    85  	configBase
    86  	config kubeletconfig.KubeletConfiguration
    87  }
    88  
    89  func (kc *kubeletConfig) DeepCopy() kubeadmapi.ComponentConfig {
    90  	result := &kubeletConfig{}
    91  	kc.configBase.DeepCopyInto(&result.configBase)
    92  	kc.config.DeepCopyInto(&result.config)
    93  	return result
    94  }
    95  
    96  func (kc *kubeletConfig) Marshal() ([]byte, error) {
    97  	return kc.configBase.Marshal(&kc.config)
    98  }
    99  
   100  func (kc *kubeletConfig) Unmarshal(docmap kubeadmapi.DocumentMap) error {
   101  	return kc.configBase.Unmarshal(docmap, &kc.config)
   102  }
   103  
   104  func (kc *kubeletConfig) Get() interface{} {
   105  	return &kc.config
   106  }
   107  
   108  func (kc *kubeletConfig) Set(cfg interface{}) {
   109  	kc.config = *cfg.(*kubeletconfig.KubeletConfiguration)
   110  }
   111  
   112  func (kc *kubeletConfig) Default(cfg *kubeadmapi.ClusterConfiguration, _ *kubeadmapi.APIEndpoint, nodeRegOpts *kubeadmapi.NodeRegistrationOptions) {
   113  	const kind = "KubeletConfiguration"
   114  
   115  	if kc.config.FeatureGates == nil {
   116  		kc.config.FeatureGates = map[string]bool{}
   117  	}
   118  
   119  	if kc.config.StaticPodPath == "" {
   120  		kc.config.StaticPodPath = kubeadmapiv1.DefaultManifestsDir
   121  	} else if kc.config.StaticPodPath != kubeadmapiv1.DefaultManifestsDir {
   122  		warnDefaultComponentConfigValue(kind, "staticPodPath", kubeadmapiv1.DefaultManifestsDir, kc.config.StaticPodPath)
   123  	}
   124  
   125  	clusterDNS := ""
   126  	dnsIP, err := constants.GetDNSIP(cfg.Networking.ServiceSubnet)
   127  	if err != nil {
   128  		clusterDNS = kubeadmapiv1.DefaultClusterDNSIP
   129  	} else {
   130  		clusterDNS = dnsIP.String()
   131  	}
   132  
   133  	if kc.config.ClusterDNS == nil {
   134  		kc.config.ClusterDNS = []string{clusterDNS}
   135  	} else if len(kc.config.ClusterDNS) != 1 || kc.config.ClusterDNS[0] != clusterDNS {
   136  		warnDefaultComponentConfigValue(kind, "clusterDNS", []string{clusterDNS}, kc.config.ClusterDNS)
   137  	}
   138  
   139  	if kc.config.ClusterDomain == "" {
   140  		kc.config.ClusterDomain = cfg.Networking.DNSDomain
   141  	} else if cfg.Networking.DNSDomain != "" && kc.config.ClusterDomain != cfg.Networking.DNSDomain {
   142  		warnDefaultComponentConfigValue(kind, "clusterDomain", cfg.Networking.DNSDomain, kc.config.ClusterDomain)
   143  	}
   144  
   145  	// Require all clients to the kubelet API to have client certs signed by the cluster CA
   146  	clientCAFile := filepath.Join(cfg.CertificatesDir, constants.CACertName)
   147  	if kc.config.Authentication.X509.ClientCAFile == "" {
   148  		kc.config.Authentication.X509.ClientCAFile = clientCAFile
   149  	} else if kc.config.Authentication.X509.ClientCAFile != clientCAFile {
   150  		warnDefaultComponentConfigValue(kind, "authentication.x509.clientCAFile", clientCAFile, kc.config.Authentication.X509.ClientCAFile)
   151  	}
   152  
   153  	if kc.config.Authentication.Anonymous.Enabled == nil {
   154  		kc.config.Authentication.Anonymous.Enabled = ptr.To(kubeletAuthenticationAnonymousEnabled)
   155  	} else if *kc.config.Authentication.Anonymous.Enabled {
   156  		warnDefaultComponentConfigValue(kind, "authentication.anonymous.enabled", kubeletAuthenticationAnonymousEnabled, *kc.config.Authentication.Anonymous.Enabled)
   157  	}
   158  
   159  	// On every client request to the kubelet API, execute a webhook (SubjectAccessReview request) to the API server
   160  	// and ask it whether the client is authorized to access the kubelet API
   161  	if kc.config.Authorization.Mode == "" {
   162  		kc.config.Authorization.Mode = kubeletconfig.KubeletAuthorizationModeWebhook
   163  	} else if kc.config.Authorization.Mode != kubeletconfig.KubeletAuthorizationModeWebhook {
   164  		warnDefaultComponentConfigValue(kind, "authorization.mode", kubeletconfig.KubeletAuthorizationModeWebhook, kc.config.Authorization.Mode)
   165  	}
   166  
   167  	// Let clients using other authentication methods like ServiceAccount tokens also access the kubelet API
   168  	if kc.config.Authentication.Webhook.Enabled == nil {
   169  		kc.config.Authentication.Webhook.Enabled = ptr.To(kubeletAuthenticationWebhookEnabled)
   170  	} else if !*kc.config.Authentication.Webhook.Enabled {
   171  		warnDefaultComponentConfigValue(kind, "authentication.webhook.enabled", kubeletAuthenticationWebhookEnabled, *kc.config.Authentication.Webhook.Enabled)
   172  	}
   173  
   174  	// Serve a /healthz webserver on localhost:10248 that kubeadm can talk to
   175  	if kc.config.HealthzBindAddress == "" {
   176  		kc.config.HealthzBindAddress = kubeletHealthzBindAddress
   177  	} else if kc.config.HealthzBindAddress != kubeletHealthzBindAddress {
   178  		warnDefaultComponentConfigValue(kind, "healthzBindAddress", kubeletHealthzBindAddress, kc.config.HealthzBindAddress)
   179  	}
   180  
   181  	if kc.config.HealthzPort == nil {
   182  		kc.config.HealthzPort = ptr.To[int32](constants.KubeletHealthzPort)
   183  	} else if *kc.config.HealthzPort != constants.KubeletHealthzPort {
   184  		warnDefaultComponentConfigValue(kind, "healthzPort", constants.KubeletHealthzPort, *kc.config.HealthzPort)
   185  	}
   186  
   187  	if kc.config.ReadOnlyPort != kubeletReadOnlyPort {
   188  		warnDefaultComponentConfigValue(kind, "readOnlyPort", kubeletReadOnlyPort, kc.config.ReadOnlyPort)
   189  	}
   190  
   191  	// We cannot show a warning for RotateCertificates==false and we must hardcode it to true.
   192  	// There is no way to determine if the user has set this or not, given the field is a non-pointer.
   193  	kc.config.RotateCertificates = kubeletRotateCertificates
   194  
   195  	if len(kc.config.CgroupDriver) == 0 {
   196  		klog.V(1).Infof("the value of KubeletConfiguration.cgroupDriver is empty; setting it to %q", constants.CgroupDriverSystemd)
   197  		kc.config.CgroupDriver = constants.CgroupDriverSystemd
   198  	}
   199  
   200  	ok, err := isServiceActive("systemd-resolved")
   201  	if err != nil {
   202  		klog.Warningf("cannot determine if systemd-resolved is active: %v", err)
   203  	}
   204  	if ok {
   205  		if kc.config.ResolverConfig == nil {
   206  			kc.config.ResolverConfig = ptr.To(kubeletSystemdResolverConfig)
   207  		} else {
   208  			if *kc.config.ResolverConfig != kubeletSystemdResolverConfig {
   209  				warnDefaultComponentConfigValue(kind, "resolvConf", kubeletSystemdResolverConfig, *kc.config.ResolverConfig)
   210  			}
   211  		}
   212  	}
   213  }
   214  
   215  // isServiceActive checks whether the given service exists and is running
   216  func isServiceActive(name string) (bool, error) {
   217  	initSystem, err := initsystem.GetInitSystem()
   218  	if err != nil {
   219  		return false, err
   220  	}
   221  	return initSystem.ServiceIsActive(name), nil
   222  }
   223  

View as plain text