1/*
2Copyright 2019 The Kubernetes Authors.
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8    http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
15*/
16
17package constants
18
19import (
20	"fmt"
21	"io/ioutil"
22	"net"
23	"os"
24	"path"
25	"path/filepath"
26	"strings"
27	"time"
28
29	v1 "k8s.io/api/core/v1"
30	"k8s.io/apimachinery/pkg/util/version"
31	"k8s.io/apimachinery/pkg/util/wait"
32	bootstrapapi "k8s.io/cluster-bootstrap/token/api"
33	utilnet "k8s.io/utils/net"
34
35	"github.com/pkg/errors"
36)
37
38const (
39	// KubernetesDir is the directory Kubernetes owns for storing various configuration files
40	KubernetesDir = "/etc/kubernetes"
41	// ManifestsSubDirName defines directory name to store manifests
42	ManifestsSubDirName = "manifests"
43	// TempDirForKubeadm defines temporary directory for kubeadm
44	// should be joined with KubernetesDir.
45	TempDirForKubeadm = "tmp"
46
47	// CertificateValidity defines the validity for all the signed certificates generated by kubeadm
48	CertificateValidity = time.Hour * 24 * 365
49
50	// CACertAndKeyBaseName defines certificate authority base name
51	CACertAndKeyBaseName = "ca"
52	// CACertName defines certificate name
53	CACertName = "ca.crt"
54	// CAKeyName defines certificate name
55	CAKeyName = "ca.key"
56
57	// APIServerCertAndKeyBaseName defines API's server certificate and key base name
58	APIServerCertAndKeyBaseName = "apiserver"
59	// APIServerCertName defines API's server certificate name
60	APIServerCertName = "apiserver.crt"
61	// APIServerKeyName defines API's server key name
62	APIServerKeyName = "apiserver.key"
63	// APIServerCertCommonName defines API's server certificate common name (CN)
64	APIServerCertCommonName = "kube-apiserver"
65
66	// APIServerKubeletClientCertAndKeyBaseName defines kubelet client certificate and key base name
67	APIServerKubeletClientCertAndKeyBaseName = "apiserver-kubelet-client"
68	// APIServerKubeletClientCertName defines kubelet client certificate name
69	APIServerKubeletClientCertName = "apiserver-kubelet-client.crt"
70	// APIServerKubeletClientKeyName defines kubelet client key name
71	APIServerKubeletClientKeyName = "apiserver-kubelet-client.key"
72	// APIServerKubeletClientCertCommonName defines kubelet client certificate common name (CN)
73	APIServerKubeletClientCertCommonName = "kube-apiserver-kubelet-client"
74
75	// EtcdCACertAndKeyBaseName defines etcd's CA certificate and key base name
76	EtcdCACertAndKeyBaseName = "etcd/ca"
77	// EtcdCACertName defines etcd's CA certificate name
78	EtcdCACertName = "etcd/ca.crt"
79	// EtcdCAKeyName defines etcd's CA key name
80	EtcdCAKeyName = "etcd/ca.key"
81
82	// EtcdServerCertAndKeyBaseName defines etcd's server certificate and key base name
83	EtcdServerCertAndKeyBaseName = "etcd/server"
84	// EtcdServerCertName defines etcd's server certificate name
85	EtcdServerCertName = "etcd/server.crt"
86	// EtcdServerKeyName defines etcd's server key name
87	EtcdServerKeyName = "etcd/server.key"
88
89	// EtcdListenClientPort defines the port etcd listen on for client traffic
90	EtcdListenClientPort = 2379
91	// EtcdMetricsPort is the port at which to obtain etcd metrics and health status
92	EtcdMetricsPort = 2381
93
94	// EtcdPeerCertAndKeyBaseName defines etcd's peer certificate and key base name
95	EtcdPeerCertAndKeyBaseName = "etcd/peer"
96	// EtcdPeerCertName defines etcd's peer certificate name
97	EtcdPeerCertName = "etcd/peer.crt"
98	// EtcdPeerKeyName defines etcd's peer key name
99	EtcdPeerKeyName = "etcd/peer.key"
100
101	// EtcdListenPeerPort defines the port etcd listen on for peer traffic
102	EtcdListenPeerPort = 2380
103
104	// EtcdHealthcheckClientCertAndKeyBaseName defines etcd's healthcheck client certificate and key base name
105	EtcdHealthcheckClientCertAndKeyBaseName = "etcd/healthcheck-client"
106	// EtcdHealthcheckClientCertName defines etcd's healthcheck client certificate name
107	EtcdHealthcheckClientCertName = "etcd/healthcheck-client.crt"
108	// EtcdHealthcheckClientKeyName defines etcd's healthcheck client key name
109	EtcdHealthcheckClientKeyName = "etcd/healthcheck-client.key"
110	// EtcdHealthcheckClientCertCommonName defines etcd's healthcheck client certificate common name (CN)
111	EtcdHealthcheckClientCertCommonName = "kube-etcd-healthcheck-client"
112
113	// APIServerEtcdClientCertAndKeyBaseName defines apiserver's etcd client certificate and key base name
114	APIServerEtcdClientCertAndKeyBaseName = "apiserver-etcd-client"
115	// APIServerEtcdClientCertName defines apiserver's etcd client certificate name
116	APIServerEtcdClientCertName = "apiserver-etcd-client.crt"
117	// APIServerEtcdClientKeyName defines apiserver's etcd client key name
118	APIServerEtcdClientKeyName = "apiserver-etcd-client.key"
119	// APIServerEtcdClientCertCommonName defines apiserver's etcd client certificate common name (CN)
120	APIServerEtcdClientCertCommonName = "kube-apiserver-etcd-client"
121
122	// ServiceAccountKeyBaseName defines SA key base name
123	ServiceAccountKeyBaseName = "sa"
124	// ServiceAccountPublicKeyName defines SA public key base name
125	ServiceAccountPublicKeyName = "sa.pub"
126	// ServiceAccountPrivateKeyName defines SA private key base name
127	ServiceAccountPrivateKeyName = "sa.key"
128
129	// FrontProxyCACertAndKeyBaseName defines front proxy CA certificate and key base name
130	FrontProxyCACertAndKeyBaseName = "front-proxy-ca"
131	// FrontProxyCACertName defines front proxy CA certificate name
132	FrontProxyCACertName = "front-proxy-ca.crt"
133	// FrontProxyCAKeyName defines front proxy CA key name
134	FrontProxyCAKeyName = "front-proxy-ca.key"
135
136	// FrontProxyClientCertAndKeyBaseName defines front proxy certificate and key base name
137	FrontProxyClientCertAndKeyBaseName = "front-proxy-client"
138	// FrontProxyClientCertName defines front proxy certificate name
139	FrontProxyClientCertName = "front-proxy-client.crt"
140	// FrontProxyClientKeyName defines front proxy key name
141	FrontProxyClientKeyName = "front-proxy-client.key"
142	// FrontProxyClientCertCommonName defines front proxy certificate common name
143	FrontProxyClientCertCommonName = "front-proxy-client" //used as subject.commonname attribute (CN)
144
145	// AdminKubeConfigFileName defines name for the kubeconfig aimed to be used by the superuser/admin of the cluster
146	AdminKubeConfigFileName = "admin.conf"
147	// KubeletBootstrapKubeConfigFileName defines the file name for the kubeconfig that the kubelet will use to do
148	// the TLS bootstrap to get itself an unique credential
149	KubeletBootstrapKubeConfigFileName = "bootstrap-kubelet.conf"
150
151	// KubeletKubeConfigFileName defines the file name for the kubeconfig that the control-plane kubelet will use for talking
152	// to the API server
153	KubeletKubeConfigFileName = "kubelet.conf"
154	// ControllerManagerKubeConfigFileName defines the file name for the controller manager's kubeconfig file
155	ControllerManagerKubeConfigFileName = "controller-manager.conf"
156	// SchedulerKubeConfigFileName defines the file name for the scheduler's kubeconfig file
157	SchedulerKubeConfigFileName = "scheduler.conf"
158
159	// Some well-known users and groups in the core Kubernetes authorization system
160
161	// ControllerManagerUser defines the well-known user the controller-manager should be authenticated as
162	ControllerManagerUser = "system:kube-controller-manager"
163	// SchedulerUser defines the well-known user the scheduler should be authenticated as
164	SchedulerUser = "system:kube-scheduler"
165	// SystemPrivilegedGroup defines the well-known group for the apiservers. This group is also superuser by default
166	// (i.e. bound to the cluster-admin ClusterRole)
167	SystemPrivilegedGroup = "system:masters"
168	// NodesGroup defines the well-known group for all nodes.
169	NodesGroup = "system:nodes"
170	// NodesUserPrefix defines the user name prefix as requested by the Node authorizer.
171	NodesUserPrefix = "system:node:"
172	// NodesClusterRoleBinding defines the well-known ClusterRoleBinding which binds the too permissive system:node
173	// ClusterRole to the system:nodes group. Since kubeadm is using the Node Authorizer, this ClusterRoleBinding's
174	// system:nodes group subject is removed if present.
175	NodesClusterRoleBinding = "system:node"
176
177	// APICallRetryInterval defines how long kubeadm should wait before retrying a failed API operation
178	APICallRetryInterval = 500 * time.Millisecond
179	// DiscoveryRetryInterval specifies how long kubeadm should wait before retrying to connect to the control-plane when doing discovery
180	DiscoveryRetryInterval = 5 * time.Second
181	// PatchNodeTimeout specifies how long kubeadm should wait for applying the label and taint on the control-plane before timing out
182	PatchNodeTimeout = 2 * time.Minute
183	// TLSBootstrapTimeout specifies how long kubeadm should wait for the kubelet to perform the TLS Bootstrap
184	TLSBootstrapTimeout = 5 * time.Minute
185	// TLSBootstrapRetryInterval specifies how long kubeadm should wait before retrying the TLS Bootstrap check
186	TLSBootstrapRetryInterval = 5 * time.Second
187	// APICallWithWriteTimeout specifies how long kubeadm should wait for api calls with at least one write
188	APICallWithWriteTimeout = 40 * time.Second
189	// APICallWithReadTimeout specifies how long kubeadm should wait for api calls with only reads
190	APICallWithReadTimeout = 15 * time.Second
191	// PullImageRetry specifies how many times ContainerRuntime retries when pulling image failed
192	PullImageRetry = 5
193
194	// DefaultControlPlaneTimeout specifies the default control plane (actually API Server) timeout for use by kubeadm
195	DefaultControlPlaneTimeout = 4 * time.Minute
196
197	// MinimumAddressesInServiceSubnet defines minimum amount of nodes the Service subnet should allow.
198	// We need at least ten, because the DNS service is always at the tenth cluster clusterIP
199	MinimumAddressesInServiceSubnet = 10
200
201	// MaximumBitsForServiceSubnet defines maximum possible size of the service subnet in terms of bits.
202	// For example, if the value is 20, then the largest supported service subnet is /12 for IPv4 and /108 for IPv6.
203	// Note however that anything in between /108 and /112 will be clamped to /112 due to the limitations of the underlying allocation logic.
204	// TODO: https://github.com/kubernetes/enhancements/pull/1881
205	MaximumBitsForServiceSubnet = 20
206
207	// MinimumAddressesInPodSubnet defines minimum amount of pods in the cluster.
208	// We need at least more than services, an IPv4 /28 or IPv6 /128 subnet means 14 util addresses
209	MinimumAddressesInPodSubnet = 14
210
211	// PodSubnetNodeMaskMaxDiff is limited to 16 due to an issue with uncompressed IP bitmap in core:
212	// xref: #44918
213	// The node subnet mask size must be no more than the pod subnet mask size + 16
214	PodSubnetNodeMaskMaxDiff = 16
215
216	// DefaultTokenDuration specifies the default amount of time that a bootstrap token will be valid
217	// Default behaviour is 24 hours
218	DefaultTokenDuration = 24 * time.Hour
219
220	// DefaultCertTokenDuration specifies the default amount of time that the token used by upload certs will be valid
221	// Default behaviour is 2 hours
222	DefaultCertTokenDuration = 2 * time.Hour
223
224	// CertificateKeySize specifies the size of the key used to encrypt certificates on uploadcerts phase
225	CertificateKeySize = 32
226
227	// LabelNodeRoleOldControlPlane specifies that a node hosts control-plane components
228	// DEPRECATED: https://github.com/kubernetes/kubeadm/issues/2200
229	LabelNodeRoleOldControlPlane = "node-role.kubernetes.io/master"
230
231	// LabelNodeRoleControlPlane specifies that a node hosts control-plane components
232	LabelNodeRoleControlPlane = "node-role.kubernetes.io/control-plane"
233
234	// LabelExcludeFromExternalLB can be set on a node to exclude it from external load balancers.
235	// This is added to control plane nodes to preserve backwards compatibility with a legacy behavior.
236	LabelExcludeFromExternalLB = "node.kubernetes.io/exclude-from-external-load-balancers"
237
238	// AnnotationKubeadmCRISocket specifies the annotation kubeadm uses to preserve the crisocket information given to kubeadm at
239	// init/join time for use later. kubeadm annotates the node object with this information
240	AnnotationKubeadmCRISocket = "kubeadm.alpha.kubernetes.io/cri-socket"
241
242	// UnknownCRISocket defines the undetected or unknown CRI socket
243	UnknownCRISocket = "/var/run/unknown.sock"
244
245	// KubeadmConfigConfigMap specifies in what ConfigMap in the kube-system namespace the `kubeadm init` configuration should be stored
246	KubeadmConfigConfigMap = "kubeadm-config"
247
248	// ClusterConfigurationConfigMapKey specifies in what ConfigMap key the cluster configuration should be stored
249	ClusterConfigurationConfigMapKey = "ClusterConfiguration"
250
251	// KubeProxyConfigMap specifies in what ConfigMap in the kube-system namespace the kube-proxy configuration should be stored
252	KubeProxyConfigMap = "kube-proxy"
253
254	// KubeProxyConfigMapKey specifies in what ConfigMap key the component config of kube-proxy should be stored
255	KubeProxyConfigMapKey = "config.conf"
256
257	// KubeletBaseConfigurationConfigMapPrefix specifies in what ConfigMap in the kube-system namespace the initial remote configuration of kubelet should be stored
258	KubeletBaseConfigurationConfigMapPrefix = "kubelet-config-"
259
260	// KubeletBaseConfigurationConfigMapKey specifies in what ConfigMap key the initial remote configuration of kubelet should be stored
261	KubeletBaseConfigurationConfigMapKey = "kubelet"
262
263	// KubeletBaseConfigMapRolePrefix defines the base kubelet configuration ConfigMap.
264	KubeletBaseConfigMapRolePrefix = "kubeadm:kubelet-config-"
265
266	// KubeletRunDirectory specifies the directory where the kubelet runtime information is stored.
267	KubeletRunDirectory = "/var/lib/kubelet"
268
269	// KubeletConfigurationFileName specifies the file name on the node which stores initial remote configuration of kubelet
270	// This file should exist under KubeletRunDirectory
271	KubeletConfigurationFileName = "config.yaml"
272
273	// KubeletEnvFileName is a file "kubeadm init" writes at runtime. Using that interface, kubeadm can customize certain
274	// kubelet flags conditionally based on the environment at runtime. Also, parameters given to the configuration file
275	// might be passed through this file. "kubeadm init" writes one variable, with the name ${KubeletEnvFileVariableName}.
276	// This file should exist under KubeletRunDirectory
277	KubeletEnvFileName = "kubeadm-flags.env"
278
279	// KubeletEnvFileVariableName specifies the shell script variable name "kubeadm init" should write a value to in KubeletEnvFile
280	KubeletEnvFileVariableName = "KUBELET_KUBEADM_ARGS"
281
282	// KubeletHealthzPort is the port of the kubelet healthz endpoint
283	KubeletHealthzPort = 10248
284
285	// MinExternalEtcdVersion indicates minimum external etcd version which kubeadm supports
286	MinExternalEtcdVersion = "3.2.18"
287
288	// DefaultEtcdVersion indicates the default etcd version that kubeadm uses
289	DefaultEtcdVersion = "3.5.0-0"
290
291	// Etcd defines variable used internally when referring to etcd component
292	Etcd = "etcd"
293	// KubeAPIServer defines variable used internally when referring to kube-apiserver component
294	KubeAPIServer = "kube-apiserver"
295	// KubeControllerManager defines variable used internally when referring to kube-controller-manager component
296	KubeControllerManager = "kube-controller-manager"
297	// KubeScheduler defines variable used internally when referring to kube-scheduler component
298	KubeScheduler = "kube-scheduler"
299	// KubeProxy defines variable used internally when referring to kube-proxy component
300	KubeProxy = "kube-proxy"
301	// CoreDNS defines variable used internally when referring to the CoreDNS component
302	CoreDNS = "CoreDNS"
303	// Kubelet defines variable used internally when referring to the Kubelet
304	Kubelet = "kubelet"
305
306	// KubeCertificatesVolumeName specifies the name for the Volume that is used for injecting certificates to control plane components (can be both a hostPath volume or a projected, all-in-one volume)
307	KubeCertificatesVolumeName = "k8s-certs"
308
309	// KubeConfigVolumeName specifies the name for the Volume that is used for injecting the kubeconfig to talk securely to the api server for a control plane component if applicable
310	KubeConfigVolumeName = "kubeconfig"
311
312	// NodeBootstrapTokenAuthGroup specifies which group a Node Bootstrap Token should be authenticated in
313	NodeBootstrapTokenAuthGroup = "system:bootstrappers:kubeadm:default-node-token"
314
315	// DefaultCIImageRepository points to image registry where CI uploads images from ci-cross build job
316	DefaultCIImageRepository = "gcr.io/k8s-staging-ci-images"
317
318	// CoreDNSConfigMap specifies in what ConfigMap in the kube-system namespace the CoreDNS config should be stored
319	CoreDNSConfigMap = "coredns"
320
321	// CoreDNSDeploymentName specifies the name of the Deployment for CoreDNS add-on
322	CoreDNSDeploymentName = "coredns"
323
324	// CoreDNSImageName specifies the name of the image for CoreDNS add-on
325	CoreDNSImageName = "coredns"
326
327	// CoreDNSVersion is the version of CoreDNS to be deployed if it is used
328	CoreDNSVersion = "v1.8.4"
329
330	// ClusterConfigurationKind is the string kind value for the ClusterConfiguration struct
331	ClusterConfigurationKind = "ClusterConfiguration"
332
333	// InitConfigurationKind is the string kind value for the InitConfiguration struct
334	InitConfigurationKind = "InitConfiguration"
335
336	// JoinConfigurationKind is the string kind value for the JoinConfiguration struct
337	JoinConfigurationKind = "JoinConfiguration"
338
339	// YAMLDocumentSeparator is the separator for YAML documents
340	// TODO: Find a better place for this constant
341	YAMLDocumentSeparator = "---\n"
342
343	// DefaultAPIServerBindAddress is the default bind address for the API Server
344	DefaultAPIServerBindAddress = "0.0.0.0"
345
346	// ControlPlaneNumCPU is the number of CPUs required on control-plane
347	ControlPlaneNumCPU = 2
348
349	// ControlPlaneMem is the number of megabytes of memory required on the control-plane
350	// Below that amount of RAM running a stable control plane would be difficult.
351	ControlPlaneMem = 1700
352
353	// KubeadmCertsSecret specifies in what Secret in the kube-system namespace the certificates should be stored
354	KubeadmCertsSecret = "kubeadm-certs"
355
356	// KubeletPort is the default port for the kubelet server on each host machine.
357	// May be overridden by a flag at startup.
358	KubeletPort = 10250
359	// KubeSchedulerPort is the default port for the scheduler status server.
360	// May be overridden by a flag at startup.
361	KubeSchedulerPort = 10259
362	// KubeControllerManagerPort is the default port for the controller manager status server.
363	// May be overridden by a flag at startup.
364	KubeControllerManagerPort = 10257
365
366	// EtcdAdvertiseClientUrlsAnnotationKey is the annotation key on every etcd pod, describing the
367	// advertise client URLs
368	EtcdAdvertiseClientUrlsAnnotationKey = "kubeadm.kubernetes.io/etcd.advertise-client-urls"
369	// KubeAPIServerAdvertiseAddressEndpointAnnotationKey is the annotation key on every apiserver pod,
370	// describing the API endpoint (advertise address and bind port of the api server)
371	KubeAPIServerAdvertiseAddressEndpointAnnotationKey = "kubeadm.kubernetes.io/kube-apiserver.advertise-address.endpoint"
372	// ComponentConfigHashAnnotationKey holds the config map annotation key that kubeadm uses to store
373	// a SHA256 sum to check for user changes
374	ComponentConfigHashAnnotationKey = "kubeadm.kubernetes.io/component-config.hash"
375
376	// ControlPlaneTier is the value used in the tier label to identify control plane components
377	ControlPlaneTier = "control-plane"
378
379	// Mode* constants were copied from pkg/kubeapiserver/authorizer/modes
380	// to avoid kubeadm dependency on the internal module
381	// TODO: share Mode* constants in component config
382
383	// ModeAlwaysAllow is the mode to set all requests as authorized
384	ModeAlwaysAllow string = "AlwaysAllow"
385	// ModeAlwaysDeny is the mode to set no requests as authorized
386	ModeAlwaysDeny string = "AlwaysDeny"
387	// ModeABAC is the mode to use Attribute Based Access Control to authorize
388	ModeABAC string = "ABAC"
389	// ModeWebhook is the mode to make an external webhook call to authorize
390	ModeWebhook string = "Webhook"
391	// ModeRBAC is the mode to use Role Based Access Control to authorize
392	ModeRBAC string = "RBAC"
393	// ModeNode is an authorization mode that authorizes API requests made by kubelets.
394	ModeNode string = "Node"
395
396	// PauseVersion indicates the default pause image version for kubeadm
397	PauseVersion = "3.5"
398
399	// CgroupDriverSystemd holds the systemd driver type
400	CgroupDriverSystemd = "systemd"
401
402	// The username of the user that kube-controller-manager runs as.
403	KubeControllerManagerUserName string = "kubeadm-kcm"
404	// The username of the user that kube-apiserver runs as.
405	KubeAPIServerUserName string = "kubeadm-kas"
406	// The username of the user that kube-scheduler runs as.
407	KubeSchedulerUserName string = "kubeadm-ks"
408	// The username of the user that etcd runs as.
409	EtcdUserName string = "kubeadm-etcd"
410	// The group of users that are allowed to read the service account private key.
411	ServiceAccountKeyReadersGroupName string = "kubeadm-sa-key-readers"
412)
413
414var (
415	// OldControlPlaneTaint is the taint to apply on the PodSpec for being able to run that Pod on the control-plane
416	// DEPRECATED: https://github.com/kubernetes/kubeadm/issues/2200
417	OldControlPlaneTaint = v1.Taint{
418		Key:    LabelNodeRoleOldControlPlane,
419		Effect: v1.TaintEffectNoSchedule,
420	}
421
422	// OldControlPlaneToleration is the toleration to apply on the PodSpec for being able to run that Pod on the control-plane
423	// DEPRECATED: https://github.com/kubernetes/kubeadm/issues/2200
424	OldControlPlaneToleration = v1.Toleration{
425		Key:    LabelNodeRoleOldControlPlane,
426		Effect: v1.TaintEffectNoSchedule,
427	}
428
429	// ControlPlaneTaint is the taint to apply on the PodSpec for being able to run that Pod on the control-plane
430	ControlPlaneTaint = v1.Taint{
431		Key:    LabelNodeRoleControlPlane,
432		Effect: v1.TaintEffectNoSchedule,
433	}
434
435	// ControlPlaneToleration is the toleration to apply on the PodSpec for being able to run that Pod on the control-plane
436	ControlPlaneToleration = v1.Toleration{
437		Key:    LabelNodeRoleControlPlane,
438		Effect: v1.TaintEffectNoSchedule,
439	}
440
441	// DefaultTokenUsages specifies the default functions a token will get
442	DefaultTokenUsages = bootstrapapi.KnownTokenUsages
443
444	// DefaultTokenGroups specifies the default groups that this token will authenticate as when used for authentication
445	DefaultTokenGroups = []string{NodeBootstrapTokenAuthGroup}
446
447	// ControlPlaneComponents defines the control-plane component names
448	ControlPlaneComponents = []string{KubeAPIServer, KubeControllerManager, KubeScheduler}
449
450	// MinimumControlPlaneVersion specifies the minimum control plane version kubeadm can deploy
451	MinimumControlPlaneVersion = version.MustParseSemantic("v1.21.0")
452
453	// MinimumKubeletVersion specifies the minimum version of kubelet which kubeadm supports
454	MinimumKubeletVersion = version.MustParseSemantic("v1.21.0")
455
456	// CurrentKubernetesVersion specifies current Kubernetes version supported by kubeadm
457	CurrentKubernetesVersion = version.MustParseSemantic("v1.22.0")
458
459	// SupportedEtcdVersion lists officially supported etcd versions with corresponding Kubernetes releases
460	SupportedEtcdVersion = map[uint8]string{
461		13: "3.2.24",
462		14: "3.3.10",
463		15: "3.3.10",
464		16: "3.3.17-0",
465		17: "3.4.3-0",
466		18: "3.4.3-0",
467		19: "3.4.13-0",
468		20: "3.4.13-0",
469		21: "3.4.13-0",
470		22: "3.5.0-0",
471		23: "3.5.0-0",
472	}
473
474	// KubeadmCertsClusterRoleName sets the name for the ClusterRole that allows
475	// the bootstrap tokens to access the kubeadm-certs Secret during the join of a new control-plane
476	KubeadmCertsClusterRoleName = fmt.Sprintf("kubeadm:%s", KubeadmCertsSecret)
477
478	// StaticPodMirroringDefaultRetry is used a backoff strategy for
479	// waiting for static pods to be mirrored to the apiserver.
480	StaticPodMirroringDefaultRetry = wait.Backoff{
481		Steps:    30,
482		Duration: 1 * time.Second,
483		Factor:   1.0,
484		Jitter:   0.1,
485	}
486)
487
488// EtcdSupportedVersion returns officially supported version of etcd for a specific Kubernetes release
489// If passed version is not in the given list, the function returns the nearest version with a warning
490func EtcdSupportedVersion(supportedEtcdVersion map[uint8]string, versionString string) (etcdVersion *version.Version, warning, err error) {
491	kubernetesVersion, err := version.ParseSemantic(versionString)
492	if err != nil {
493		return nil, nil, err
494	}
495	desiredVersion, etcdStringVersion := uint8(kubernetesVersion.Minor()), ""
496
497	min, max := ^uint8(0), uint8(0)
498	for k, v := range supportedEtcdVersion {
499		if desiredVersion == k {
500			etcdStringVersion = v
501			break
502		}
503		if k < min {
504			min = k
505		}
506		if k > max {
507			max = k
508		}
509	}
510
511	if len(etcdStringVersion) == 0 {
512		if desiredVersion < min {
513			etcdStringVersion = supportedEtcdVersion[min]
514		}
515		if desiredVersion > max {
516			etcdStringVersion = supportedEtcdVersion[max]
517		}
518		warning = fmt.Errorf("could not find officially supported version of etcd for Kubernetes %s, falling back to the nearest etcd version (%s)",
519			versionString, etcdStringVersion)
520	}
521
522	etcdVersion, err = version.ParseSemantic(etcdStringVersion)
523	if err != nil {
524		return nil, nil, err
525	}
526
527	return etcdVersion, warning, nil
528}
529
530// GetStaticPodDirectory returns the location on the disk where the Static Pod should be present
531func GetStaticPodDirectory() string {
532	return filepath.Join(KubernetesDir, ManifestsSubDirName)
533}
534
535// GetStaticPodFilepath returns the location on the disk where the Static Pod should be present
536func GetStaticPodFilepath(componentName, manifestsDir string) string {
537	return filepath.Join(manifestsDir, componentName+".yaml")
538}
539
540// GetAdminKubeConfigPath returns the location on the disk where admin kubeconfig is located by default
541func GetAdminKubeConfigPath() string {
542	return filepath.Join(KubernetesDir, AdminKubeConfigFileName)
543}
544
545// GetBootstrapKubeletKubeConfigPath returns the location on the disk where bootstrap kubelet kubeconfig is located by default
546func GetBootstrapKubeletKubeConfigPath() string {
547	return filepath.Join(KubernetesDir, KubeletBootstrapKubeConfigFileName)
548}
549
550// GetKubeletKubeConfigPath returns the location on the disk where kubelet kubeconfig is located by default
551func GetKubeletKubeConfigPath() string {
552	return filepath.Join(KubernetesDir, KubeletKubeConfigFileName)
553}
554
555// CreateTempDirForKubeadm is a function that creates a temporary directory under /etc/kubernetes/tmp (not using /tmp as that would potentially be dangerous)
556func CreateTempDirForKubeadm(kubernetesDir, dirName string) (string, error) {
557	tempDir := path.Join(KubernetesDir, TempDirForKubeadm)
558	if len(kubernetesDir) != 0 {
559		tempDir = path.Join(kubernetesDir, TempDirForKubeadm)
560	}
561
562	// creates target folder if not already exists
563	if err := os.MkdirAll(tempDir, 0700); err != nil {
564		return "", errors.Wrapf(err, "failed to create directory %q", tempDir)
565	}
566
567	tempDir, err := ioutil.TempDir(tempDir, dirName)
568	if err != nil {
569		return "", errors.Wrap(err, "couldn't create a temporary directory")
570	}
571	return tempDir, nil
572}
573
574// CreateTimestampDirForKubeadm is a function that creates a temporary directory under /etc/kubernetes/tmp formatted with the current date
575func CreateTimestampDirForKubeadm(kubernetesDir, dirName string) (string, error) {
576	tempDir := path.Join(KubernetesDir, TempDirForKubeadm)
577	if len(kubernetesDir) != 0 {
578		tempDir = path.Join(kubernetesDir, TempDirForKubeadm)
579	}
580
581	// creates target folder if not already exists
582	if err := os.MkdirAll(tempDir, 0700); err != nil {
583		return "", errors.Wrapf(err, "failed to create directory %q", tempDir)
584	}
585
586	timestampDirName := fmt.Sprintf("%s-%s", dirName, time.Now().Format("2006-01-02-15-04-05"))
587	timestampDir := path.Join(tempDir, timestampDirName)
588	if err := os.Mkdir(timestampDir, 0700); err != nil {
589		return "", errors.Wrap(err, "could not create timestamp directory")
590	}
591
592	return timestampDir, nil
593}
594
595// GetDNSIP returns a dnsIP, which is 10th IP in svcSubnet CIDR range
596func GetDNSIP(svcSubnetList string, isDualStack bool) (net.IP, error) {
597	// Get the service subnet CIDR
598	svcSubnetCIDR, err := GetKubernetesServiceCIDR(svcSubnetList, isDualStack)
599	if err != nil {
600		return nil, errors.Wrapf(err, "unable to get internal Kubernetes Service IP from the given service CIDR (%s)", svcSubnetList)
601	}
602
603	// Selects the 10th IP in service subnet CIDR range as dnsIP
604	dnsIP, err := utilnet.GetIndexedIP(svcSubnetCIDR, 10)
605	if err != nil {
606		return nil, errors.Wrap(err, "unable to get internal Kubernetes Service IP from the given service CIDR")
607	}
608
609	return dnsIP, nil
610}
611
612// GetKubernetesServiceCIDR returns the default Service CIDR for the Kubernetes internal service
613func GetKubernetesServiceCIDR(svcSubnetList string, isDualStack bool) (*net.IPNet, error) {
614	if isDualStack {
615		// The default service address family for the cluster is the address family of the first
616		// service cluster IP range configured via the `--service-cluster-ip-range` flag
617		// of the kube-controller-manager and kube-apiserver.
618		svcSubnets, err := utilnet.ParseCIDRs(strings.Split(svcSubnetList, ","))
619		if err != nil {
620			return nil, errors.Wrapf(err, "unable to parse ServiceSubnet %v", svcSubnetList)
621		}
622		if len(svcSubnets) == 0 {
623			return nil, errors.New("received empty ServiceSubnet for dual-stack")
624		}
625		return svcSubnets[0], nil
626	}
627	// internal IP address for the API server
628	_, svcSubnet, err := net.ParseCIDR(svcSubnetList)
629	if err != nil {
630		return nil, errors.Wrapf(err, "unable to parse ServiceSubnet %v", svcSubnetList)
631	}
632	return svcSubnet, nil
633}
634
635// GetAPIServerVirtualIP returns the IP of the internal Kubernetes API service
636func GetAPIServerVirtualIP(svcSubnetList string, isDualStack bool) (net.IP, error) {
637	svcSubnet, err := GetKubernetesServiceCIDR(svcSubnetList, isDualStack)
638	if err != nil {
639		return nil, errors.Wrap(err, "unable to get internal Kubernetes Service IP from the given service CIDR")
640	}
641	internalAPIServerVirtualIP, err := utilnet.GetIndexedIP(svcSubnet, 1)
642	if err != nil {
643		return nil, errors.Wrapf(err, "unable to get the first IP address from the given CIDR: %s", svcSubnet.String())
644	}
645	return internalAPIServerVirtualIP, nil
646}
647
648// GetKubeletConfigMapName returns the right ConfigMap name for the right branch of k8s
649func GetKubeletConfigMapName(k8sVersion *version.Version) string {
650	return fmt.Sprintf("%s%d.%d", KubeletBaseConfigurationConfigMapPrefix, k8sVersion.Major(), k8sVersion.Minor())
651}
652