mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-10 20:42:26 +00:00
Merge pull request #127242 from SataQiu/refactor-upgrade-node
kubeadm: add addon and post-upgrade phases for 'kubeadm upgrade node'
This commit is contained in:
commit
e30d994129
@ -14,8 +14,8 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Package apply implements phases of 'kubeadm upgrade apply'.
|
||||
package apply
|
||||
// Package upgrade holds the common phases for 'kubeadm upgrade'.
|
||||
package upgrade
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@ -28,7 +28,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"
|
||||
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
|
||||
dnsaddon "k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/dns"
|
||||
proxyaddon "k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/proxy"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade"
|
||||
@ -39,7 +38,6 @@ func NewAddonPhase() workflow.Phase {
|
||||
return workflow.Phase{
|
||||
Name: "addon",
|
||||
Short: "Upgrade the default kubeadm addons",
|
||||
Long: cmdutil.MacroCommandLongDescription,
|
||||
Phases: []workflow.Phase{
|
||||
{
|
||||
Name: "all",
|
||||
@ -98,7 +96,6 @@ func runCoreDNSAddon(c workflow.RunData) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Upgrade CoreDNS
|
||||
if err := dnsaddon.EnsureDNSAddon(&cfg.ClusterConfiguration, client, patchesDir, out, dryRun); err != nil {
|
||||
return err
|
||||
}
|
||||
@ -121,7 +118,6 @@ func runKubeProxyAddon(c workflow.RunData) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Upgrade kube-proxy
|
||||
if err := proxyaddon.EnsureProxyAddon(&cfg.ClusterConfiguration, &cfg.LocalAPIEndpoint, client, out, dryRun); err != nil {
|
||||
return err
|
||||
}
|
@ -18,26 +18,14 @@ limitations under the License.
|
||||
package apply
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
clientset "k8s.io/client-go/kubernetes"
|
||||
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/upgrade"
|
||||
)
|
||||
|
||||
// Data is the interface to use for kubeadm upgrade apply phases.
|
||||
// The "applyData" type from "cmd/upgrade/apply.go" must satisfy this interface.
|
||||
type Data interface {
|
||||
EtcdUpgrade() bool
|
||||
RenewCerts() bool
|
||||
DryRun() bool
|
||||
Cfg() *kubeadmapi.UpgradeConfiguration
|
||||
InitCfg() *kubeadmapi.InitConfiguration
|
||||
Client() clientset.Interface
|
||||
IgnorePreflightErrors() sets.Set[string]
|
||||
PatchesDir() string
|
||||
OutputWriter() io.Writer
|
||||
upgrade.Data
|
||||
|
||||
SessionIsInteractive() bool
|
||||
AllowExperimentalUpgrades() bool
|
||||
AllowRCUpgrades() bool
|
||||
|
@ -28,7 +28,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"
|
||||
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
|
||||
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"
|
||||
@ -40,7 +39,6 @@ func NewUploadConfigPhase() workflow.Phase {
|
||||
Name: "upload-config",
|
||||
Aliases: []string{"uploadconfig"},
|
||||
Short: "Upload the kubeadm and kubelet configurations to ConfigMaps",
|
||||
Long: cmdutil.MacroCommandLongDescription,
|
||||
Phases: []workflow.Phase{
|
||||
{
|
||||
Name: "all",
|
||||
|
40
cmd/kubeadm/app/cmd/phases/upgrade/data.go
Normal file
40
cmd/kubeadm/app/cmd/phases/upgrade/data.go
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
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 upgrade holds the common phases for 'kubeadm upgrade'.
|
||||
package upgrade
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
clientset "k8s.io/client-go/kubernetes"
|
||||
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
)
|
||||
|
||||
// Data is the common interface to use for kubeadm upgrade phases.
|
||||
type Data interface {
|
||||
EtcdUpgrade() bool
|
||||
RenewCerts() bool
|
||||
DryRun() bool
|
||||
Cfg() *kubeadmapi.UpgradeConfiguration
|
||||
InitCfg() *kubeadmapi.InitConfiguration
|
||||
Client() clientset.Interface
|
||||
IgnorePreflightErrors() sets.Set[string]
|
||||
PatchesDir() string
|
||||
OutputWriter() io.Writer
|
||||
}
|
42
cmd/kubeadm/app/cmd/phases/upgrade/data_test.go
Normal file
42
cmd/kubeadm/app/cmd/phases/upgrade/data_test.go
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
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 upgrade
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
clientset "k8s.io/client-go/kubernetes"
|
||||
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
)
|
||||
|
||||
// a package local type for testing purposes.
|
||||
type testData struct{}
|
||||
|
||||
// testData must satisfy Data.
|
||||
var _ Data = &testData{}
|
||||
|
||||
func (t *testData) EtcdUpgrade() bool { return false }
|
||||
func (t *testData) RenewCerts() bool { return false }
|
||||
func (t *testData) DryRun() bool { return false }
|
||||
func (t *testData) Cfg() *kubeadmapi.UpgradeConfiguration { return nil }
|
||||
func (t *testData) InitCfg() *kubeadmapi.InitConfiguration { return nil }
|
||||
func (t *testData) Client() clientset.Interface { return nil }
|
||||
func (t *testData) IgnorePreflightErrors() sets.Set[string] { return nil }
|
||||
func (t *testData) PatchesDir() string { return "" }
|
||||
func (t *testData) OutputWriter() io.Writer { return nil }
|
@ -14,8 +14,8 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Package apply implements phases of 'kubeadm upgrade apply'.
|
||||
package apply
|
||||
// Package upgrade holds the common phases for 'kubeadm upgrade'.
|
||||
package upgrade
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@ -57,16 +57,14 @@ func runKubeletConfigPhase(c workflow.RunData) error {
|
||||
return errors.New("kubelet-config phase invoked with an invalid data struct")
|
||||
}
|
||||
|
||||
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 the /etc/kubernetes/tmp/ dir, so that it could be
|
||||
// recovered if anything goes wrong.
|
||||
err := upgrade.WriteKubeletConfigFiles(initCfg, data.PatchesDir(), dryRun, data.OutputWriter())
|
||||
err := upgrade.WriteKubeletConfigFiles(data.InitCfg(), data.PatchesDir(), data.DryRun(), data.OutputWriter())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Println("[upgrade/kubelet-config] The kubelet configuration for this node was successfully updated!")
|
||||
fmt.Println("[upgrade/kubelet-config] The kubelet configuration for this node was successfully upgraded!")
|
||||
return nil
|
||||
}
|
@ -14,6 +14,7 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Package node implements phases of 'kubeadm upgrade node'.
|
||||
package node
|
||||
|
||||
import (
|
||||
@ -28,13 +29,14 @@ import (
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient"
|
||||
)
|
||||
|
||||
// NewControlPlane creates a kubeadm workflow phase that implements handling of control-plane upgrade.
|
||||
// NewControlPlane returns a new control-plane phase.
|
||||
func NewControlPlane() workflow.Phase {
|
||||
phase := workflow.Phase{
|
||||
Name: "control-plane",
|
||||
Short: "Upgrade the control plane instance deployed on this node, if any",
|
||||
Run: runControlPlane(),
|
||||
InheritFlags: []string{
|
||||
options.CfgPath,
|
||||
options.DryRun,
|
||||
options.KubeconfigPath,
|
||||
options.CertificateRenewal,
|
||||
@ -54,7 +56,7 @@ func runControlPlane() func(c workflow.RunData) error {
|
||||
|
||||
// if this is not a control-plane node, this phase should not be executed
|
||||
if !data.IsControlPlaneNode() {
|
||||
fmt.Println("[upgrade] Skipping phase. Not a control plane node.")
|
||||
fmt.Println("[upgrade/control-plane] Skipping phase. Not a control plane node.")
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -67,8 +69,9 @@ func runControlPlane() func(c workflow.RunData) error {
|
||||
patchesDir := data.PatchesDir()
|
||||
|
||||
// Upgrade the control plane and etcd if installed on this node
|
||||
fmt.Printf("[upgrade] Upgrading your Static Pod-hosted control plane instance to version %q...\n", cfg.KubernetesVersion)
|
||||
fmt.Printf("[upgrade/control-plane] Upgrading your Static Pod-hosted control plane instance to version %q...\n", cfg.KubernetesVersion)
|
||||
if dryRun {
|
||||
fmt.Printf("[dryrun] Would upgrade your static Pod-hosted control plane to version %q", cfg.KubernetesVersion)
|
||||
return upgrade.DryRunStaticPodUpgrade(patchesDir, cfg)
|
||||
}
|
||||
|
||||
@ -78,11 +81,7 @@ func runControlPlane() func(c workflow.RunData) error {
|
||||
return errors.Wrap(err, "couldn't complete the static pod upgrade")
|
||||
}
|
||||
|
||||
if err := upgrade.PerformAddonsUpgrade(client, cfg, data.PatchesDir(), data.OutputWriter()); err != nil {
|
||||
return errors.Wrap(err, "failed to perform addons 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
|
||||
}
|
||||
|
@ -14,29 +14,18 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Package node implements phases of 'kubeadm upgrade node'.
|
||||
package node
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
clientset "k8s.io/client-go/kubernetes"
|
||||
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/upgrade"
|
||||
)
|
||||
|
||||
// Data is the interface to use for kubeadm upgrade node phases.
|
||||
// The "nodeData" type from "cmd/upgrade/node.go" must satisfy this interface.
|
||||
type Data interface {
|
||||
EtcdUpgrade() bool
|
||||
RenewCerts() bool
|
||||
DryRun() bool
|
||||
Cfg() *kubeadmapi.UpgradeConfiguration
|
||||
InitCfg() *kubeadmapi.InitConfiguration
|
||||
upgrade.Data
|
||||
|
||||
IsControlPlaneNode() bool
|
||||
Client() clientset.Interface
|
||||
IgnorePreflightErrors() sets.Set[string]
|
||||
PatchesDir() string
|
||||
KubeConfigPath() string
|
||||
OutputWriter() io.Writer
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Package node holds phases of "kubeadm upgrade node".
|
||||
// Package node implements phases of 'kubeadm upgrade node'.
|
||||
package node
|
||||
|
||||
import (
|
||||
@ -28,7 +28,7 @@ import (
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade"
|
||||
)
|
||||
|
||||
// NewKubeconfigPhase creates a kubeadm workflow phase that implements handling of kubeconfig upgrade.
|
||||
// NewKubeconfigPhase returns a new kubeconfig phase.
|
||||
func NewKubeconfigPhase() workflow.Phase {
|
||||
phase := workflow.Phase{
|
||||
Name: "kubeconfig",
|
||||
@ -36,6 +36,7 @@ func NewKubeconfigPhase() workflow.Phase {
|
||||
Run: runKubeconfig(),
|
||||
Hidden: true,
|
||||
InheritFlags: []string{
|
||||
options.CfgPath,
|
||||
options.DryRun,
|
||||
options.KubeconfigPath,
|
||||
},
|
||||
@ -50,23 +51,22 @@ func runKubeconfig() func(c workflow.RunData) error {
|
||||
return errors.New("kubeconfig phase invoked with an invalid data struct")
|
||||
}
|
||||
|
||||
// if this is not a control-plane node, this phase should not be executed
|
||||
// If this is not a control-plane node, this phase should not be executed.
|
||||
if !data.IsControlPlaneNode() {
|
||||
fmt.Println("[upgrade] Skipping phase. Not a control plane node.")
|
||||
fmt.Println("[upgrade/kubeconfig] Skipping phase. Not a control plane node.")
|
||||
return nil
|
||||
}
|
||||
|
||||
// otherwise, retrieve all the info required for kubeconfig upgrade
|
||||
// Otherwise, retrieve all the info required for kubeconfig upgrade.
|
||||
cfg := data.InitCfg()
|
||||
dryRun := data.DryRun()
|
||||
|
||||
if features.Enabled(cfg.FeatureGates, features.ControlPlaneKubeletLocalMode) {
|
||||
if err := upgrade.UpdateKubeletLocalMode(cfg, dryRun); err != nil {
|
||||
if err := upgrade.UpdateKubeletLocalMode(cfg, data.DryRun()); err != nil {
|
||||
return errors.Wrap(err, "failed to update kubelet local mode")
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Println("[upgrade] The kubeconfig for this node was successfully updated!")
|
||||
fmt.Println("[upgrade/kubeconfig] The kubeconfig files for this node were successfully upgraded!")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -1,75 +0,0 @@
|
||||
/*
|
||||
Copyright 2019 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 node
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/options"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow"
|
||||
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade"
|
||||
)
|
||||
|
||||
var (
|
||||
kubeletConfigLongDesc = cmdutil.LongDesc(`
|
||||
Download the kubelet configuration from the kubelet-config ConfigMap stored in the cluster
|
||||
`)
|
||||
)
|
||||
|
||||
// NewKubeletConfigPhase creates a kubeadm workflow phase that implements handling of kubelet-config upgrade.
|
||||
func NewKubeletConfigPhase() workflow.Phase {
|
||||
phase := workflow.Phase{
|
||||
Name: "kubelet-config",
|
||||
Short: "Upgrade the kubelet configuration for this node",
|
||||
Long: kubeletConfigLongDesc,
|
||||
Run: runKubeletConfigPhase(),
|
||||
InheritFlags: []string{
|
||||
options.DryRun,
|
||||
options.KubeconfigPath,
|
||||
options.Patches,
|
||||
},
|
||||
}
|
||||
return phase
|
||||
}
|
||||
|
||||
func runKubeletConfigPhase() func(c workflow.RunData) error {
|
||||
return func(c workflow.RunData) error {
|
||||
data, ok := c.(Data)
|
||||
if !ok {
|
||||
return errors.New("kubelet-config phase invoked with an invalid data struct")
|
||||
}
|
||||
|
||||
// otherwise, retrieve all the info required for kubelet config upgrade
|
||||
cfg := data.InitCfg()
|
||||
dryRun := data.DryRun()
|
||||
|
||||
// Write the configuration for the kubelet down to disk and print the generated manifests instead if dry-running.
|
||||
// If not dry-running, the kubelet config file will be backed up to /etc/kubernetes/tmp/ dir, so that it could be
|
||||
// recovered if there is anything goes wrong.
|
||||
err := upgrade.WriteKubeletConfigFiles(cfg, data.PatchesDir(), dryRun, data.OutputWriter())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Println("[upgrade] The configuration for this node was successfully updated!")
|
||||
fmt.Println("[upgrade] Now you should go ahead and upgrade the kubelet package using your package manager.")
|
||||
return nil
|
||||
}
|
||||
}
|
@ -28,7 +28,7 @@ import (
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/preflight"
|
||||
)
|
||||
|
||||
// NewPreflightPhase creates a kubeadm workflow phase that implements preflight checks for a new node join
|
||||
// NewPreflightPhase returns a new preflight phase.
|
||||
func NewPreflightPhase() workflow.Phase {
|
||||
return workflow.Phase{
|
||||
Name: "preflight",
|
||||
@ -36,6 +36,7 @@ func NewPreflightPhase() workflow.Phase {
|
||||
Long: "Run pre-flight checks for kubeadm upgrade node.",
|
||||
Run: runPreflight,
|
||||
InheritFlags: []string{
|
||||
options.CfgPath,
|
||||
options.IgnorePreflightErrors,
|
||||
},
|
||||
}
|
||||
@ -47,14 +48,14 @@ func runPreflight(c workflow.RunData) error {
|
||||
if !ok {
|
||||
return errors.New("preflight phase invoked with an invalid data struct")
|
||||
}
|
||||
fmt.Println("[preflight] Running pre-flight checks")
|
||||
fmt.Println("[upgrade/preflight] Running pre-flight checks")
|
||||
|
||||
// First, check if we're root separately from the other preflight checks and fail fast
|
||||
// First, check if we're root separately from the other preflight checks and fail fast.
|
||||
if err := preflight.RunRootCheckOnly(data.IgnorePreflightErrors()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// If this is a control-plane node, pull the basic images
|
||||
// If this is a control-plane node, pull the basic images.
|
||||
if data.IsControlPlaneNode() {
|
||||
// Update the InitConfiguration used for RunPullImagesCheck with ImagePullPolicy and ImagePullSerial
|
||||
// that come from UpgradeNodeConfiguration.
|
||||
@ -63,17 +64,17 @@ func runPreflight(c workflow.RunData) error {
|
||||
initConfig.NodeRegistration.ImagePullSerial = data.Cfg().Node.ImagePullSerial
|
||||
|
||||
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(), initConfig, data.IgnorePreflightErrors()); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
fmt.Println("[preflight] Would pull the required images (like 'kubeadm config images pull')")
|
||||
fmt.Println("[upgrade/preflight] Would pull the required images (like 'kubeadm config images pull')")
|
||||
}
|
||||
} else {
|
||||
fmt.Println("[preflight] Skipping prepull. Not a control plane node.")
|
||||
fmt.Println("[upgrade/preflight] Skipping prepull. Not a control plane node.")
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -14,8 +14,8 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Package apply implements phases of 'kubeadm upgrade apply'.
|
||||
package apply
|
||||
// Package upgrade holds the common phases for 'kubeadm upgrade'.
|
||||
package upgrade
|
||||
|
||||
import (
|
||||
"github.com/pkg/errors"
|
||||
@ -41,7 +41,7 @@ func NewPostUpgradePhase() workflow.Phase {
|
||||
func runPostUpgrade(c workflow.RunData) error {
|
||||
_, ok := c.(Data)
|
||||
if !ok {
|
||||
return errors.New("preflight phase invoked with an invalid data struct")
|
||||
return errors.New("post-upgrade phase invoked with an invalid data struct")
|
||||
}
|
||||
// PLACEHOLDER: this phase should contain any release specific post-upgrade tasks.
|
||||
|
@ -34,6 +34,7 @@ import (
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta4"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/options"
|
||||
commonphases "k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/upgrade"
|
||||
phases "k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/upgrade/apply"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow"
|
||||
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
|
||||
@ -134,10 +135,10 @@ func newCmdApply(apf *applyPlanFlags) *cobra.Command {
|
||||
applyRunner.AppendPhase(phases.NewControlPlanePhase())
|
||||
applyRunner.AppendPhase(phases.NewUploadConfigPhase())
|
||||
applyRunner.AppendPhase(phases.NewKubeconfigPhase())
|
||||
applyRunner.AppendPhase(phases.NewKubeletConfigPhase())
|
||||
applyRunner.AppendPhase(commonphases.NewKubeletConfigPhase())
|
||||
applyRunner.AppendPhase(phases.NewBootstrapTokenPhase())
|
||||
applyRunner.AppendPhase(phases.NewAddonPhase())
|
||||
applyRunner.AppendPhase(phases.NewPostUpgradePhase())
|
||||
applyRunner.AppendPhase(commonphases.NewAddonPhase())
|
||||
applyRunner.AppendPhase(commonphases.NewPostUpgradePhase())
|
||||
|
||||
// Sets the data builder function, that will be used by the runner,
|
||||
// both when running the entire workflow or single phases.
|
||||
|
@ -31,6 +31,7 @@ import (
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta4"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/options"
|
||||
commonphases "k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/upgrade"
|
||||
phases "k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/upgrade/node"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow"
|
||||
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
|
||||
@ -98,7 +99,9 @@ func newCmdNode(out io.Writer) *cobra.Command {
|
||||
nodeRunner.AppendPhase(phases.NewPreflightPhase())
|
||||
nodeRunner.AppendPhase(phases.NewControlPlane())
|
||||
nodeRunner.AppendPhase(phases.NewKubeconfigPhase())
|
||||
nodeRunner.AppendPhase(phases.NewKubeletConfigPhase())
|
||||
nodeRunner.AppendPhase(commonphases.NewKubeletConfigPhase())
|
||||
nodeRunner.AppendPhase(commonphases.NewAddonPhase())
|
||||
nodeRunner.AppendPhase(commonphases.NewPostUpgradePhase())
|
||||
|
||||
// sets the data builder function, that will be used by the runner
|
||||
// both when running the entire workflow or single phases
|
||||
|
@ -25,7 +25,6 @@ import (
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
errorsutil "k8s.io/apimachinery/pkg/util/errors"
|
||||
@ -36,79 +35,11 @@ import (
|
||||
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/dns"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/proxy"
|
||||
kubeletphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/kubelet"
|
||||
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
||||
dryrunutil "k8s.io/kubernetes/cmd/kubeadm/app/util/dryrun"
|
||||
)
|
||||
|
||||
// PerformAddonsUpgrade performs the upgrade of the coredns and kube-proxy addons.
|
||||
func PerformAddonsUpgrade(client clientset.Interface, cfg *kubeadmapi.InitConfiguration, patchesDir string, out io.Writer) error {
|
||||
unupgradedControlPlanes, err := UnupgradedControlPlaneInstances(client, cfg.NodeRegistration.Name)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to determine whether all the control plane instances have been upgraded")
|
||||
}
|
||||
if len(unupgradedControlPlanes) > 0 {
|
||||
fmt.Fprintf(out, "[upgrade/addons] skip upgrade addons because control plane instances %v have not been upgraded\n", unupgradedControlPlanes)
|
||||
return nil
|
||||
}
|
||||
|
||||
var errs []error
|
||||
|
||||
// If the coredns ConfigMap is missing, show a warning and assume that the
|
||||
// DNS addon was skipped during "kubeadm init", and that its redeployment on upgrade is not desired.
|
||||
//
|
||||
// TODO: remove this once "kubeadm upgrade apply" phases are supported:
|
||||
// https://github.com/kubernetes/kubeadm/issues/1318
|
||||
var missingCoreDNSConfigMap bool
|
||||
if _, err := client.CoreV1().ConfigMaps(metav1.NamespaceSystem).Get(
|
||||
context.TODO(),
|
||||
kubeadmconstants.CoreDNSConfigMap,
|
||||
metav1.GetOptions{},
|
||||
); err != nil && apierrors.IsNotFound(err) {
|
||||
missingCoreDNSConfigMap = true
|
||||
}
|
||||
if missingCoreDNSConfigMap {
|
||||
klog.Warningf("the ConfigMaps %q in the namespace %q were not found. "+
|
||||
"Assuming that a DNS server was not deployed for this cluster. "+
|
||||
"Note that once 'kubeadm upgrade apply' supports phases you "+
|
||||
"will have to skip the DNS upgrade manually",
|
||||
kubeadmconstants.CoreDNSConfigMap,
|
||||
metav1.NamespaceSystem)
|
||||
} else {
|
||||
// Upgrade CoreDNS
|
||||
if err := dns.EnsureDNSAddon(&cfg.ClusterConfiguration, client, patchesDir, out, false); err != nil {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
}
|
||||
|
||||
// If the kube-proxy ConfigMap is missing, show a warning and assume that kube-proxy
|
||||
// was skipped during "kubeadm init", and that its redeployment on upgrade is not desired.
|
||||
//
|
||||
// TODO: remove this once "kubeadm upgrade apply" phases are supported:
|
||||
// https://github.com/kubernetes/kubeadm/issues/1318
|
||||
if _, err := client.CoreV1().ConfigMaps(metav1.NamespaceSystem).Get(
|
||||
context.TODO(),
|
||||
kubeadmconstants.KubeProxyConfigMap,
|
||||
metav1.GetOptions{},
|
||||
); err != nil && apierrors.IsNotFound(err) {
|
||||
klog.Warningf("the ConfigMap %q in the namespace %q was not found. "+
|
||||
"Assuming that kube-proxy was not deployed for this cluster. "+
|
||||
"Note that once 'kubeadm upgrade apply' supports phases you "+
|
||||
"will have to skip the kube-proxy upgrade manually",
|
||||
kubeadmconstants.KubeProxyConfigMap,
|
||||
metav1.NamespaceSystem)
|
||||
} else {
|
||||
// Upgrade kube-proxy
|
||||
if err := proxy.EnsureProxyAddon(&cfg.ClusterConfiguration, &cfg.LocalAPIEndpoint, client, out, false); err != nil {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
}
|
||||
|
||||
return errorsutil.NewAggregate(errs)
|
||||
}
|
||||
|
||||
// UnupgradedControlPlaneInstances returns a list of control plane instances that have not yet been upgraded.
|
||||
//
|
||||
// NB. This function can only be called after the current control plane instance has been upgraded already.
|
||||
|
Loading…
Reference in New Issue
Block a user