1
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
36 KubeletGroup = kubeletconfig.GroupName
37
38
39
40 kubeletReadOnlyPort int32 = 0
41
42
43 kubeletRotateCertificates = true
44
45
46 kubeletAuthenticationAnonymousEnabled = false
47
48
49 kubeletAuthenticationWebhookEnabled = true
50
51
52 kubeletHealthzBindAddress = "127.0.0.1"
53
54
55 kubeletSystemdResolverConfig = "/run/systemd/resolve/resolv.conf"
56 )
57
58
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
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
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
160
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
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
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
192
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
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