diff --git a/cmd/kubeadm/app/cmd/phases/init/uploadconfig.go b/cmd/kubeadm/app/cmd/phases/init/uploadconfig.go index 5d681519260..33317a5e284 100644 --- a/cmd/kubeadm/app/cmd/phases/init/uploadconfig.go +++ b/cmd/kubeadm/app/cmd/phases/init/uploadconfig.go @@ -28,9 +28,7 @@ import ( "k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow" cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util" kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants" - "k8s.io/kubernetes/cmd/kubeadm/app/features" kubeletphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/kubelet" - patchnodephase "k8s.io/kubernetes/cmd/kubeadm/app/phases/patchnode" "k8s.io/kubernetes/cmd/kubeadm/app/phases/uploadconfig" "k8s.io/kubernetes/cmd/kubeadm/app/util/errors" ) @@ -127,12 +125,6 @@ func runUploadKubeletConfig(c workflow.RunData) error { return errors.Wrap(err, "error creating kubelet configuration ConfigMap") } - if !features.Enabled(cfg.FeatureGates, features.NodeLocalCRISocket) { - klog.V(1).Infoln("[upload-config] Preserving the CRISocket information for the control-plane node") - if err := patchnodephase.AnnotateCRISocket(client, cfg.NodeRegistration.Name, cfg.NodeRegistration.CRISocket); err != nil { - return errors.Wrap(err, "error writing CRISocket for this node") - } - } return nil } diff --git a/cmd/kubeadm/app/cmd/phases/join/kubelet.go b/cmd/kubeadm/app/cmd/phases/join/kubelet.go index 822bf7a509f..7cb22a83abe 100644 --- a/cmd/kubeadm/app/cmd/phases/join/kubelet.go +++ b/cmd/kubeadm/app/cmd/phases/join/kubelet.go @@ -40,7 +40,6 @@ import ( kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants" "k8s.io/kubernetes/cmd/kubeadm/app/features" kubeletphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/kubelet" - patchnodephase "k8s.io/kubernetes/cmd/kubeadm/app/phases/patchnode" kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util" "k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient" dryrunutil "k8s.io/kubernetes/cmd/kubeadm/app/util/dryrun" @@ -244,68 +243,50 @@ func runKubeletWaitBootstrapPhase(c workflow.RunData) (returnErr error) { if !ok { return errors.New("kubelet-start phase invoked with an invalid data struct") } + + if data.DryRun() { + fmt.Println("[kubelet-wait] Would wait for the kubelet to be bootstrapped") + return nil + } + cfg := data.Cfg() initCfg, err := data.InitCfg() if err != nil { return err } - var client clientset.Interface + bootstrapKubeConfigFile := filepath.Join(data.KubeConfigDir(), kubeadmconstants.KubeletBootstrapKubeConfigFileName) + // Deletes the bootstrapKubeConfigFile, so the credential used for TLS bootstrap is removed from disk + defer func() { + _ = os.Remove(bootstrapKubeConfigFile) + }() - if data.DryRun() { - fmt.Println("[kubelet-wait] Would wait for the kubelet to be bootstrapped") - - // Use the dry-run client. - if client, err = data.Client(); err != nil { - return errors.Wrap(err, "could not get client for dry-run") - } - } else { - bootstrapKubeConfigFile := filepath.Join(data.KubeConfigDir(), kubeadmconstants.KubeletBootstrapKubeConfigFileName) - // Deletes the bootstrapKubeConfigFile, so the credential used for TLS bootstrap is removed from disk - defer func() { - _ = os.Remove(bootstrapKubeConfigFile) - }() - - // Apply patches to the in-memory kubelet configuration so that any configuration changes like kubelet healthz - // address and port options are respected during the wait below. WriteConfigToDisk already applied patches to - // the kubelet.yaml written to disk. This should be done after WriteConfigToDisk because both use the same config - // in memory and we don't want patches to be applied two times to the config that is written to disk. - if err := kubeletphase.ApplyPatchesToConfig(&initCfg.ClusterConfiguration, data.PatchesDir()); err != nil { - return errors.Wrap(err, "could not apply patches to the in-memory kubelet configuration") - } - - // Now the kubelet will perform the TLS Bootstrap, transforming /etc/kubernetes/bootstrap-kubelet.conf to /etc/kubernetes/kubelet.conf - // Wait for the kubelet to create the /etc/kubernetes/kubelet.conf kubeconfig file. If this process - // times out, display a somewhat user-friendly message. - waiter := apiclient.NewKubeWaiter(nil, 0, os.Stdout) - waiter.SetTimeout(cfg.Timeouts.KubeletHealthCheck.Duration) - kubeletConfig := initCfg.ClusterConfiguration.ComponentConfigs[componentconfigs.KubeletGroup].Get() - kubeletConfigTyped, ok := kubeletConfig.(*kubeletconfig.KubeletConfiguration) - if !ok { - return errors.New("could not convert the KubeletConfiguration to a typed object") - } - if err := waiter.WaitForKubelet(kubeletConfigTyped.HealthzBindAddress, *kubeletConfigTyped.HealthzPort); err != nil { - apiclient.PrintKubeletErrorHelpScreen(data.OutputWriter()) - return errors.Wrap(err, "failed while waiting for the kubelet to start") - } - - if err := waitForTLSBootstrappedClient(cfg.Timeouts.TLSBootstrap.Duration); err != nil { - apiclient.PrintKubeletErrorHelpScreen(data.OutputWriter()) - return errors.Wrap(err, "failed while waiting for TLS bootstrap") - } - - // When we know the /etc/kubernetes/kubelet.conf file is available, get the client - client, err = kubeconfigutil.ClientSetFromFile(kubeadmconstants.GetKubeletKubeConfigPath()) - if err != nil { - return err - } + // Apply patches to the in-memory kubelet configuration so that any configuration changes like kubelet healthz + // address and port options are respected during the wait below. WriteConfigToDisk already applied patches to + // the kubelet.yaml written to disk. This should be done after WriteConfigToDisk because both use the same config + // in memory and we don't want patches to be applied two times to the config that is written to disk. + if err := kubeletphase.ApplyPatchesToConfig(&initCfg.ClusterConfiguration, data.PatchesDir()); err != nil { + return errors.Wrap(err, "could not apply patches to the in-memory kubelet configuration") } - if !features.Enabled(initCfg.ClusterConfiguration.FeatureGates, features.NodeLocalCRISocket) { - klog.V(1).Infoln("[kubelet-start] preserving the crisocket information for the node") - if err := patchnodephase.AnnotateCRISocket(client, cfg.NodeRegistration.Name, cfg.NodeRegistration.CRISocket); err != nil { - return errors.Wrap(err, "error writing CRISocket for this node") - } + // Now the kubelet will perform the TLS Bootstrap, transforming /etc/kubernetes/bootstrap-kubelet.conf to /etc/kubernetes/kubelet.conf + // Wait for the kubelet to create the /etc/kubernetes/kubelet.conf kubeconfig file. If this process + // times out, display a somewhat user-friendly message. + waiter := apiclient.NewKubeWaiter(nil, 0, os.Stdout) + waiter.SetTimeout(cfg.Timeouts.KubeletHealthCheck.Duration) + kubeletConfig := initCfg.ClusterConfiguration.ComponentConfigs[componentconfigs.KubeletGroup].Get() + kubeletConfigTyped, ok := kubeletConfig.(*kubeletconfig.KubeletConfiguration) + if !ok { + return errors.New("could not convert the KubeletConfiguration to a typed object") + } + if err := waiter.WaitForKubelet(kubeletConfigTyped.HealthzBindAddress, *kubeletConfigTyped.HealthzPort); err != nil { + apiclient.PrintKubeletErrorHelpScreen(data.OutputWriter()) + return errors.Wrap(err, "failed while waiting for the kubelet to start") + } + + if err := waitForTLSBootstrappedClient(cfg.Timeouts.TLSBootstrap.Duration); err != nil { + apiclient.PrintKubeletErrorHelpScreen(data.OutputWriter()) + return errors.Wrap(err, "failed while waiting for TLS bootstrap") } return nil diff --git a/cmd/kubeadm/app/cmd/phases/upgrade/apply/uploadconfig.go b/cmd/kubeadm/app/cmd/phases/upgrade/apply/uploadconfig.go index 52a56c11812..da036d76542 100644 --- a/cmd/kubeadm/app/cmd/phases/upgrade/apply/uploadconfig.go +++ b/cmd/kubeadm/app/cmd/phases/upgrade/apply/uploadconfig.go @@ -26,7 +26,6 @@ import ( kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" "k8s.io/kubernetes/cmd/kubeadm/app/cmd/options" "k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow" - "k8s.io/kubernetes/cmd/kubeadm/app/features" kubeletphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/kubelet" patchnodephase "k8s.io/kubernetes/cmd/kubeadm/app/phases/patchnode" "k8s.io/kubernetes/cmd/kubeadm/app/phases/uploadconfig" @@ -107,15 +106,9 @@ func runUploadKubeletConfig(c workflow.RunData) error { return errors.Wrap(err, "error creating kubelet configuration ConfigMap") } - if !features.Enabled(cfg.ClusterConfiguration.FeatureGates, features.NodeLocalCRISocket) { - klog.V(1).Infoln("[upgrade/upload-config] Preserving the CRISocket information for this control-plane node") - if err := patchnodephase.AnnotateCRISocket(client, cfg.NodeRegistration.Name, cfg.NodeRegistration.CRISocket); err != nil { - return errors.Wrap(err, "error writing CRISocket for this node") - } - } else { - if err := patchnodephase.RemoveCRISocketAnnotation(client, cfg.NodeRegistration.Name); err != nil { - return err - } + // TODO Remove once NodeLocalCRISocket is removed in 1.37. + if err := patchnodephase.RemoveCRISocketAnnotation(client, cfg.NodeRegistration.Name); err != nil { + return err } return nil diff --git a/cmd/kubeadm/app/features/features.go b/cmd/kubeadm/app/features/features.go index 9026c0e5162..85fc067b072 100644 --- a/cmd/kubeadm/app/features/features.go +++ b/cmd/kubeadm/app/features/features.go @@ -55,7 +55,7 @@ var InitFeatureGates = FeatureList{ DeprecationMessage: "Deprecated in favor of the core kubelet feature UserNamespacesSupport which is beta since 1.30." + " Once UserNamespacesSupport graduates to GA, kubeadm will start using it and RootlessControlPlane will be removed.", }, - NodeLocalCRISocket: {FeatureSpec: featuregate.FeatureSpec{Default: true, PreRelease: featuregate.Beta}}, + NodeLocalCRISocket: {FeatureSpec: featuregate.FeatureSpec{Default: true, PreRelease: featuregate.GA, LockToDefault: true}}, } // Feature represents a feature being gated