diff --git a/cmd/kubeadm/app/cmd/phases/upgrade/apply/addons.go b/cmd/kubeadm/app/cmd/phases/upgrade/apply/addons.go index e51f6700863..fe3305b0f76 100644 --- a/cmd/kubeadm/app/cmd/phases/upgrade/apply/addons.go +++ b/cmd/kubeadm/app/cmd/phases/upgrade/apply/addons.go @@ -38,24 +38,24 @@ import ( func NewAddonPhase() workflow.Phase { return workflow.Phase{ Name: "addon", - Short: "Install the default kubeadm addons", + Short: "Upgrade the default kubeadm addons", Long: cmdutil.MacroCommandLongDescription, Phases: []workflow.Phase{ { Name: "all", - Short: "Install all the addons", + Short: "Upgrade all the addons", InheritFlags: getAddonPhaseFlags("all"), RunAllSiblings: true, }, { Name: "coredns", - Short: "Install the CoreDNS addon", + Short: "Upgrade the CoreDNS addon", InheritFlags: getAddonPhaseFlags("coredns"), Run: runCoreDNSAddon, }, { Name: "kube-proxy", - Short: "Install the kube-proxy addon", + Short: "Upgrade the kube-proxy addon", InheritFlags: getAddonPhaseFlags("kube-proxy"), Run: runKubeProxyAddon, }, @@ -69,7 +69,7 @@ func shouldUpgradeAddons(client clientset.Interface, cfg *kubeadmapi.InitConfigu return false, errors.Wrapf(err, "failed to determine whether all the control plane instances have been upgraded") } if len(unupgradedControlPlanes) > 0 { - fmt.Fprintf(out, "[upgrade/addons] Skipping upgrade of addons because control plane instances %v have not been upgraded\n", unupgradedControlPlanes) + fmt.Fprintf(out, "[upgrade/addon] Skipping upgrade of addons because control plane instances %v have not been upgraded\n", unupgradedControlPlanes) return false, nil } return true, nil @@ -83,7 +83,7 @@ func getInitData(c workflow.RunData) (*kubeadmapi.InitConfiguration, clientset.I return data.InitCfg(), data.Client(), data.PatchesDir(), data.OutputWriter(), data.DryRun(), nil } -// runCoreDNSAddon installs the CoreDNS addon. +// runCoreDNSAddon upgrades the CoreDNS addon. func runCoreDNSAddon(c workflow.RunData) error { cfg, client, patchesDir, out, dryRun, err := getInitData(c) if err != nil { @@ -106,7 +106,7 @@ func runCoreDNSAddon(c workflow.RunData) error { return nil } -// runKubeProxyAddon installs the KubeProxy addon. +// runKubeProxyAddon upgrades the KubeProxy addon. func runKubeProxyAddon(c workflow.RunData) error { cfg, client, _, out, dryRun, err := getInitData(c) if err != nil { diff --git a/cmd/kubeadm/app/cmd/phases/upgrade/apply/bootstraptoken.go b/cmd/kubeadm/app/cmd/phases/upgrade/apply/bootstraptoken.go index 953bfabf89c..2e8a6564595 100644 --- a/cmd/kubeadm/app/cmd/phases/upgrade/apply/bootstraptoken.go +++ b/cmd/kubeadm/app/cmd/phases/upgrade/apply/bootstraptoken.go @@ -51,11 +51,11 @@ func runBootstrapToken(c workflow.RunData) error { } if data.DryRun() { - fmt.Println("[dryrun] Would config cluster-info ConfigMap, RBAC Roles") + fmt.Println("[dryrun] Would configure bootstrap token and cluster-info RBAC rules") return nil } - fmt.Println("[bootstrap-token] Configuring the cluster-info ConfigMap and RBAC roles") + fmt.Println("[upgrade/bootstrap-token] Configuring bootstrap token and cluster-info RBAC rules") client := data.Client() diff --git a/cmd/kubeadm/app/cmd/phases/upgrade/apply/controlplane.go b/cmd/kubeadm/app/cmd/phases/upgrade/apply/controlplane.go index 36f9721d356..c0c3fb25344 100644 --- a/cmd/kubeadm/app/cmd/phases/upgrade/apply/controlplane.go +++ b/cmd/kubeadm/app/cmd/phases/upgrade/apply/controlplane.go @@ -56,11 +56,11 @@ func runControlPlane(c workflow.RunData) error { initCfg, upgradeCfg, client, patchesDir := data.InitCfg(), data.Cfg(), data.Client(), data.PatchesDir() if data.DryRun() { - fmt.Printf("[dryrun] Would upgrade your Static Pod-hosted control plane to version %q", initCfg.KubernetesVersion) + fmt.Printf("[dryrun] Would upgrade your static Pod-hosted control plane to version %q", initCfg.KubernetesVersion) return upgrade.DryRunStaticPodUpgrade(patchesDir, initCfg) } - fmt.Printf("[upgrade/apply] Upgrading your Static Pod-hosted control plane to version %q (timeout: %v)...\n", + fmt.Printf("[upgrade/control-plane] Upgrading your static Pod-hosted control plane to version %q (timeout: %v)...\n", initCfg.KubernetesVersion, upgradeCfg.Timeouts.UpgradeManifests.Duration) waiter := apiclient.NewKubeWaiter(client, upgradeCfg.Timeouts.UpgradeManifests.Duration, os.Stdout) @@ -68,7 +68,7 @@ func runControlPlane(c workflow.RunData) error { return errors.Wrap(err, "couldn't complete the static pod upgrade") } - fmt.Println("[upgrade] The control plane instance for this node was successfully updated!") + fmt.Println("[upgrade/control-plane] The control plane instance for this node was successfully upgraded!") return nil } diff --git a/cmd/kubeadm/app/cmd/phases/upgrade/apply/kubeconfig.go b/cmd/kubeadm/app/cmd/phases/upgrade/apply/kubeconfig.go index 6a931e61ccf..a13667b1d01 100644 --- a/cmd/kubeadm/app/cmd/phases/upgrade/apply/kubeconfig.go +++ b/cmd/kubeadm/app/cmd/phases/upgrade/apply/kubeconfig.go @@ -59,7 +59,7 @@ func runKubeconfig() func(c workflow.RunData) error { } } - fmt.Println("[upgrade] The kubeconfig files for this node were successfully updated!") + fmt.Println("[upgrad/kubeconfig] The kubeconfig files for this node were successfully upgraded!") return nil } diff --git a/cmd/kubeadm/app/cmd/phases/upgrade/apply/kubeletconfig.go b/cmd/kubeadm/app/cmd/phases/upgrade/apply/kubeletconfig.go index 21f058d52d7..a5b2d7490a9 100644 --- a/cmd/kubeadm/app/cmd/phases/upgrade/apply/kubeletconfig.go +++ b/cmd/kubeadm/app/cmd/phases/upgrade/apply/kubeletconfig.go @@ -60,13 +60,13 @@ func runKubeletConfigPhase(c workflow.RunData) error { initCfg, dryRun := data.InitCfg(), data.DryRun() // Write the configuration for the kubelet down to disk and print the generated manifests instead of dry-running. - // If not dry-running, the kubelet config file will be backed up to /etc/kubernetes/tmp/ dir, so that it could be + // If not dry-running, the kubelet config file will be backed up to the /etc/kubernetes/tmp/ dir, so that it could be // recovered if anything goes wrong. err := upgrade.WriteKubeletConfigFiles(initCfg, data.PatchesDir(), dryRun, data.OutputWriter()) if err != nil { return err } - fmt.Println("[upgrade] The kubelet configuration for this node was successfully updated!") + fmt.Println("[upgrade/kubelet-config] The kubelet configuration for this node was successfully updated!") return nil } diff --git a/cmd/kubeadm/app/cmd/phases/upgrade/apply/postupgrade.go b/cmd/kubeadm/app/cmd/phases/upgrade/apply/postupgrade.go new file mode 100644 index 00000000000..0ab43fa2926 --- /dev/null +++ b/cmd/kubeadm/app/cmd/phases/upgrade/apply/postupgrade.go @@ -0,0 +1,49 @@ +/* +Copyright 2024 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package apply implements phases of 'kubeadm upgrade apply'. +package apply + +import ( + "github.com/pkg/errors" + + "k8s.io/kubernetes/cmd/kubeadm/app/cmd/options" + "k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow" +) + +// NewPostUpgradePhase returns a new post-upgrade phase. +func NewPostUpgradePhase() workflow.Phase { + return workflow.Phase{ + Name: "post-upgrade", + Short: "Run the post upgrade tasks", + Run: runPostUpgrade, + InheritFlags: []string{ + options.CfgPath, + options.KubeconfigPath, + options.DryRun, + }, + } +} + +func runPostUpgrade(c workflow.RunData) error { + _, ok := c.(Data) + if !ok { + return errors.New("preflight phase invoked with an invalid data struct") + } + // TODO: add the post upgrade tasks here when needed + + return nil +} diff --git a/cmd/kubeadm/app/cmd/phases/upgrade/apply/preflight.go b/cmd/kubeadm/app/cmd/phases/upgrade/apply/preflight.go index 22775635102..7c97d8bba3e 100644 --- a/cmd/kubeadm/app/cmd/phases/upgrade/apply/preflight.go +++ b/cmd/kubeadm/app/cmd/phases/upgrade/apply/preflight.go @@ -42,8 +42,7 @@ import ( func NewPreflightPhase() workflow.Phase { return workflow.Phase{ Name: "preflight", - Short: "Run upgrade apply preflight checks", - Long: "Run preflight checks for kubeadm upgrade apply.", + Short: "Run preflight checks before upgrade", Run: runPreflight, InheritFlags: []string{ options.CfgPath, @@ -63,7 +62,7 @@ func runPreflight(c workflow.RunData) error { if !ok { return errors.New("preflight phase invoked with an invalid data struct") } - fmt.Println("[preflight] Running preflight checks") + fmt.Println("[upgrade/preflight] Running preflight checks") printer := &output.TextPrinter{} @@ -80,7 +79,7 @@ func runPreflight(c workflow.RunData) error { } // Run healthchecks against the cluster - klog.V(1).Infoln("[upgrade/apply] Verifying the cluster health") + klog.V(1).Infoln("[upgrade/preflight] Verifying the cluster health") if err := upgrade.CheckClusterHealth(client, &initCfg.ClusterConfiguration, ignorePreflightErrors, printer); err != nil { return err } @@ -88,12 +87,12 @@ func runPreflight(c workflow.RunData) error { // Check if feature gate flags used in the cluster are consistent with the set of features currently supported by kubeadm if msg := features.CheckDeprecatedFlags(&features.InitFeatureGates, initCfg.FeatureGates); len(msg) > 0 { for _, m := range msg { - _, _ = printer.Printf("[upgrade/config] %s\n", m) + _, _ = printer.Printf("[upgrade/preflight] %s\n", m) } } // Validate requested and validate actual version - klog.V(1).Infoln("[upgrade/apply] Validating requested and actual version") + klog.V(1).Infoln("[upgrade/preflight] Validating requested and actual version") if err := configutil.NormalizeKubernetesVersion(&initCfg.ClusterConfiguration); err != nil { return err } @@ -120,14 +119,14 @@ func runPreflight(c workflow.RunData) error { } if !data.DryRun() { - fmt.Println("[preflight] Pulling images required for setting up a Kubernetes cluster") - fmt.Println("[preflight] This might take a minute or two, depending on the speed of your internet connection") - fmt.Println("[preflight] You can also perform this action beforehand using 'kubeadm config images pull'") + fmt.Println("[upgrade/preflight] Pulling images required for setting up a Kubernetes cluster") + fmt.Println("[upgrade/preflight] This might take a minute or two, depending on the speed of your internet connection") + fmt.Println("[upgrade/preflight] You can also perform this action beforehand using 'kubeadm config images pull'") if err := preflight.RunPullImagesCheck(utilsexec.New(), initCfg, ignorePreflightErrors); err != nil { return err } } else { - fmt.Println("[preflight] Would pull the required images (like 'kubeadm config images pull')") + fmt.Println("[dryrun] Would pull the required images (like 'kubeadm config images pull')") } return nil @@ -136,7 +135,7 @@ func runPreflight(c workflow.RunData) error { // enforceVersionPolicies makes sure that the version the user specified is valid to upgrade to // There are both fatal and skippable (with --force) errors func enforceVersionPolicies(newK8sVersionStr string, newK8sVersion *version.Version, allowExperimentalUpgrades, allowRCUpgrades, force bool, versionGetter upgrade.VersionGetter) error { - fmt.Printf("[upgrade/version] You have chosen to upgrade the cluster version to %q\n", newK8sVersionStr) + fmt.Printf("[upgrade/preflight] You have chosen to upgrade the cluster version to %q\n", newK8sVersionStr) versionSkewErrs := upgrade.EnforceVersionPolicies(versionGetter, newK8sVersionStr, newK8sVersion, allowExperimentalUpgrades, allowRCUpgrades) if versionSkewErrs != nil { @@ -153,7 +152,7 @@ func enforceVersionPolicies(newK8sVersionStr string, newK8sVersion *version.Vers kubeadmutil.FormatErrMsg(versionSkewErrs.Skippable)) } // Soft errors found, but --force was specified - fmt.Printf("[upgrade/version] Found %d potential version compatibility errors but skipping since the --force flag is set: \n\n%v", len(versionSkewErrs.Skippable), kubeadmutil.FormatErrMsg(versionSkewErrs.Skippable)) + fmt.Printf("[upgrade/preflight] Found %d potential version compatibility errors but skipping since the --force flag is set: \n\n%v", len(versionSkewErrs.Skippable), kubeadmutil.FormatErrMsg(versionSkewErrs.Skippable)) } } 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 912b4731d0e..16e6470ebc0 100644 --- a/cmd/kubeadm/app/cmd/phases/upgrade/apply/uploadconfig.go +++ b/cmd/kubeadm/app/cmd/phases/upgrade/apply/uploadconfig.go @@ -34,12 +34,12 @@ import ( "k8s.io/kubernetes/cmd/kubeadm/app/phases/uploadconfig" ) -// NewUploadConfigPhase returns the phase to uploadConfig +// NewUploadConfigPhase returns a new upload-config phase. func NewUploadConfigPhase() workflow.Phase { return workflow.Phase{ Name: "upload-config", Aliases: []string{"uploadconfig"}, - Short: "Upload the kubeadm and kubelet configurations to a ConfigMaps", + Short: "Upload the kubeadm and kubelet configurations to ConfigMaps", Long: cmdutil.MacroCommandLongDescription, Phases: []workflow.Phase{ { @@ -56,7 +56,7 @@ func NewUploadConfigPhase() workflow.Phase { }, { Name: "kubelet", - Short: "Upload the kubelet configuration config to a ConfigMap", + Short: "Upload the kubelet configuration to a ConfigMap", Run: runUploadKubeletConfig, InheritFlags: getUploadConfigPhaseFlags(), }, @@ -84,7 +84,7 @@ func runUploadKubeadmConfig(c workflow.RunData) error { return nil } - klog.V(1).Infoln("[upload-config] Uploading the kubeadm ClusterConfiguration to a ConfigMap") + klog.V(1).Infoln("[upgrade/upload-config] Uploading the kubeadm ClusterConfiguration to a ConfigMap") if err := uploadconfig.UploadConfiguration(cfg, client); err != nil { return errors.Wrap(err, "error uploading the kubeadm ClusterConfiguration") } @@ -104,12 +104,12 @@ func runUploadKubeletConfig(c workflow.RunData) error { return nil } - klog.V(1).Infoln("[upload-config] Uploading the kubelet configuration to a ConfigMap") + klog.V(1).Infoln("[upgrade/upload-config] Uploading the kubelet configuration to a ConfigMap") if err = kubeletphase.CreateConfigMap(&cfg.ClusterConfiguration, client); err != nil { return errors.Wrap(err, "error creating kubelet configuration ConfigMap") } - klog.V(1).Infoln("[upload-config] Preserving the CRISocket information for the control-plane node") + klog.V(1).Infoln("[upgrade/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 information for the control-plane node") } diff --git a/cmd/kubeadm/app/cmd/upgrade/apply.go b/cmd/kubeadm/app/cmd/upgrade/apply.go index 4cfa5f86c9c..41b81ec5eef 100644 --- a/cmd/kubeadm/app/cmd/upgrade/apply.go +++ b/cmd/kubeadm/app/cmd/upgrade/apply.go @@ -112,8 +112,8 @@ func newCmdApply(apf *applyPlanFlags) *cobra.Command { } fmt.Println("") - fmt.Printf("[upgrade/successful] SUCCESS! A control plane node of your cluster was upgraded to %q.\n\n", applyData.InitCfg().KubernetesVersion) - fmt.Println("[upgrade/kubelet] Now please proceed with upgrading the rest of the nodes by following the right order.") + fmt.Printf("[upgrade] SUCCESS! A control plane node of your cluster was upgraded to %q.\n\n", applyData.InitCfg().KubernetesVersion) + fmt.Println("[upgrade] Now please proceed with upgrading the rest of the nodes by following the right order.") return nil }, @@ -137,6 +137,7 @@ func newCmdApply(apf *applyPlanFlags) *cobra.Command { applyRunner.AppendPhase(phases.NewKubeletConfigPhase()) applyRunner.AppendPhase(phases.NewBootstrapTokenPhase()) applyRunner.AppendPhase(phases.NewAddonPhase()) + applyRunner.AppendPhase(phases.NewPostUpgradePhase()) // Sets the data builder function, that will be used by the runner // both when running the entire workflow or single phases @@ -229,12 +230,12 @@ func newApplyData(cmd *cobra.Command, args []string, applyFlags *applyFlags) (*a printer := &output.TextPrinter{} // Fetches the cluster configuration - klog.V(1).Infoln("[upgrade/apply] retrieving configuration from cluster") + klog.V(1).Infoln("[upgrade] retrieving configuration from cluster") initCfg, err := configutil.FetchInitConfigurationFromCluster(client, nil, "upgrade", false, false) if err != nil { if apierrors.IsNotFound(err) { - _, _ = printer.Printf("[upgrade/config] In order to upgrade, a ConfigMap called %q in the %q namespace must exist.\n", constants.KubeadmConfigConfigMap, metav1.NamespaceSystem) - _, _ = printer.Printf("[upgrade/config] Use 'kubeadm init phase upload-config --config your-config.yaml' to re-upload it.\n") + _, _ = printer.Printf("[upgrade] In order to upgrade, a ConfigMap called %q in the %q namespace must exist.\n", constants.KubeadmConfigConfigMap, metav1.NamespaceSystem) + _, _ = printer.Printf("[upgrade] Use 'kubeadm init phase upload-config --config your-config.yaml' to re-upload it.\n") err = errors.Errorf("the ConfigMap %q in the %q namespace was not found", constants.KubeadmConfigConfigMap, metav1.NamespaceSystem) } return nil, errors.Wrap(err, "[upgrade/init config] FATAL") diff --git a/cmd/kubeadm/app/cmd/upgrade/apply_test.go b/cmd/kubeadm/app/cmd/upgrade/apply_test.go index 5c16784f211..d5a80f23c08 100644 --- a/cmd/kubeadm/app/cmd/upgrade/apply_test.go +++ b/cmd/kubeadm/app/cmd/upgrade/apply_test.go @@ -28,48 +28,6 @@ import ( kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants" ) -func TestSessionIsInteractive(t *testing.T) { - var tcases = []struct { - name string - data *applyData - expected bool - }{ - { - name: "Explicitly non-interactive", - data: &applyData{ - nonInteractiveMode: true, - }, - expected: false, - }, - { - name: "Implicitly non-interactive since --dryRun is used", - data: &applyData{ - dryRun: true, - }, - expected: false, - }, - { - name: "Implicitly non-interactive since --force is used", - data: &applyData{ - force: true, - }, - expected: false, - }, - { - name: "Interactive session", - data: &applyData{}, - expected: true, - }, - } - for _, tt := range tcases { - t.Run(tt.name, func(t *testing.T) { - if tt.data.SessionIsInteractive() != tt.expected { - t.Error("unexpected result") - } - }) - } -} - var testApplyConfig = fmt.Sprintf(`--- apiVersion: %s apply: