k8s.io/kubernetes@v1.31.0-alpha.0.0.20240520171757-56147500dadc/cmd/kubeadm/app/componentconfigs/kubelet.go (about)

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