mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-14 06:15:45 +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.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Package apply implements phases of 'kubeadm upgrade apply'.
|
// Package upgrade holds the common phases for 'kubeadm upgrade'.
|
||||||
package apply
|
package upgrade
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
@ -28,7 +28,6 @@ import (
|
|||||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||||
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/options"
|
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/options"
|
||||||
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow"
|
"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"
|
dnsaddon "k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/dns"
|
||||||
proxyaddon "k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/proxy"
|
proxyaddon "k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/proxy"
|
||||||
"k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade"
|
"k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade"
|
||||||
@ -39,7 +38,6 @@ func NewAddonPhase() workflow.Phase {
|
|||||||
return workflow.Phase{
|
return workflow.Phase{
|
||||||
Name: "addon",
|
Name: "addon",
|
||||||
Short: "Upgrade the default kubeadm addons",
|
Short: "Upgrade the default kubeadm addons",
|
||||||
Long: cmdutil.MacroCommandLongDescription,
|
|
||||||
Phases: []workflow.Phase{
|
Phases: []workflow.Phase{
|
||||||
{
|
{
|
||||||
Name: "all",
|
Name: "all",
|
||||||
@ -98,7 +96,6 @@ func runCoreDNSAddon(c workflow.RunData) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Upgrade CoreDNS
|
|
||||||
if err := dnsaddon.EnsureDNSAddon(&cfg.ClusterConfiguration, client, patchesDir, out, dryRun); err != nil {
|
if err := dnsaddon.EnsureDNSAddon(&cfg.ClusterConfiguration, client, patchesDir, out, dryRun); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -121,7 +118,6 @@ func runKubeProxyAddon(c workflow.RunData) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Upgrade kube-proxy
|
|
||||||
if err := proxyaddon.EnsureProxyAddon(&cfg.ClusterConfiguration, &cfg.LocalAPIEndpoint, client, out, dryRun); err != nil {
|
if err := proxyaddon.EnsureProxyAddon(&cfg.ClusterConfiguration, &cfg.LocalAPIEndpoint, client, out, dryRun); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
@ -18,26 +18,14 @@ limitations under the License.
|
|||||||
package apply
|
package apply
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/upgrade"
|
||||||
|
|
||||||
"k8s.io/apimachinery/pkg/util/sets"
|
|
||||||
clientset "k8s.io/client-go/kubernetes"
|
|
||||||
|
|
||||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Data is the interface to use for kubeadm upgrade apply phases.
|
// Data is the interface to use for kubeadm upgrade apply phases.
|
||||||
// The "applyData" type from "cmd/upgrade/apply.go" must satisfy this interface.
|
// The "applyData" type from "cmd/upgrade/apply.go" must satisfy this interface.
|
||||||
type Data interface {
|
type Data interface {
|
||||||
EtcdUpgrade() bool
|
upgrade.Data
|
||||||
RenewCerts() bool
|
|
||||||
DryRun() bool
|
|
||||||
Cfg() *kubeadmapi.UpgradeConfiguration
|
|
||||||
InitCfg() *kubeadmapi.InitConfiguration
|
|
||||||
Client() clientset.Interface
|
|
||||||
IgnorePreflightErrors() sets.Set[string]
|
|
||||||
PatchesDir() string
|
|
||||||
OutputWriter() io.Writer
|
|
||||||
SessionIsInteractive() bool
|
SessionIsInteractive() bool
|
||||||
AllowExperimentalUpgrades() bool
|
AllowExperimentalUpgrades() bool
|
||||||
AllowRCUpgrades() bool
|
AllowRCUpgrades() bool
|
||||||
|
@ -28,7 +28,6 @@ import (
|
|||||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||||
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/options"
|
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/options"
|
||||||
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow"
|
"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"
|
kubeletphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/kubelet"
|
||||||
patchnodephase "k8s.io/kubernetes/cmd/kubeadm/app/phases/patchnode"
|
patchnodephase "k8s.io/kubernetes/cmd/kubeadm/app/phases/patchnode"
|
||||||
"k8s.io/kubernetes/cmd/kubeadm/app/phases/uploadconfig"
|
"k8s.io/kubernetes/cmd/kubeadm/app/phases/uploadconfig"
|
||||||
@ -40,7 +39,6 @@ func NewUploadConfigPhase() workflow.Phase {
|
|||||||
Name: "upload-config",
|
Name: "upload-config",
|
||||||
Aliases: []string{"uploadconfig"},
|
Aliases: []string{"uploadconfig"},
|
||||||
Short: "Upload the kubeadm and kubelet configurations to ConfigMaps",
|
Short: "Upload the kubeadm and kubelet configurations to ConfigMaps",
|
||||||
Long: cmdutil.MacroCommandLongDescription,
|
|
||||||
Phases: []workflow.Phase{
|
Phases: []workflow.Phase{
|
||||||
{
|
{
|
||||||
Name: "all",
|
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.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Package apply implements phases of 'kubeadm upgrade apply'.
|
// Package upgrade holds the common phases for 'kubeadm upgrade'.
|
||||||
package apply
|
package upgrade
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
@ -57,16 +57,14 @@ func runKubeletConfigPhase(c workflow.RunData) error {
|
|||||||
return errors.New("kubelet-config phase invoked with an invalid data struct")
|
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.
|
// 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
|
// 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.
|
// 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 {
|
if err != nil {
|
||||||
return err
|
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
|
return nil
|
||||||
}
|
}
|
@ -14,6 +14,7 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// Package node implements phases of 'kubeadm upgrade node'.
|
||||||
package node
|
package node
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -28,13 +29,14 @@ import (
|
|||||||
"k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient"
|
"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 {
|
func NewControlPlane() workflow.Phase {
|
||||||
phase := workflow.Phase{
|
phase := workflow.Phase{
|
||||||
Name: "control-plane",
|
Name: "control-plane",
|
||||||
Short: "Upgrade the control plane instance deployed on this node, if any",
|
Short: "Upgrade the control plane instance deployed on this node, if any",
|
||||||
Run: runControlPlane(),
|
Run: runControlPlane(),
|
||||||
InheritFlags: []string{
|
InheritFlags: []string{
|
||||||
|
options.CfgPath,
|
||||||
options.DryRun,
|
options.DryRun,
|
||||||
options.KubeconfigPath,
|
options.KubeconfigPath,
|
||||||
options.CertificateRenewal,
|
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 this is not a control-plane node, this phase should not be executed
|
||||||
if !data.IsControlPlaneNode() {
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,8 +69,9 @@ func runControlPlane() func(c workflow.RunData) error {
|
|||||||
patchesDir := data.PatchesDir()
|
patchesDir := data.PatchesDir()
|
||||||
|
|
||||||
// Upgrade the control plane and etcd if installed on this node
|
// 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 {
|
if dryRun {
|
||||||
|
fmt.Printf("[dryrun] Would upgrade your static Pod-hosted control plane to version %q", cfg.KubernetesVersion)
|
||||||
return upgrade.DryRunStaticPodUpgrade(patchesDir, cfg)
|
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")
|
return errors.Wrap(err, "couldn't complete the static pod upgrade")
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := upgrade.PerformAddonsUpgrade(client, cfg, data.PatchesDir(), data.OutputWriter()); err != nil {
|
fmt.Println("[upgrade/control-plane] The control plane instance for this node was successfully upgraded!")
|
||||||
return errors.Wrap(err, "failed to perform addons upgrade")
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Println("[upgrade] The control plane instance for this node was successfully updated!")
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -14,29 +14,18 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// Package node implements phases of 'kubeadm upgrade node'.
|
||||||
package node
|
package node
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/upgrade"
|
||||||
|
|
||||||
"k8s.io/apimachinery/pkg/util/sets"
|
|
||||||
clientset "k8s.io/client-go/kubernetes"
|
|
||||||
|
|
||||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Data is the interface to use for kubeadm upgrade node phases.
|
// Data is the interface to use for kubeadm upgrade node phases.
|
||||||
// The "nodeData" type from "cmd/upgrade/node.go" must satisfy this interface.
|
// The "nodeData" type from "cmd/upgrade/node.go" must satisfy this interface.
|
||||||
type Data interface {
|
type Data interface {
|
||||||
EtcdUpgrade() bool
|
upgrade.Data
|
||||||
RenewCerts() bool
|
|
||||||
DryRun() bool
|
|
||||||
Cfg() *kubeadmapi.UpgradeConfiguration
|
|
||||||
InitCfg() *kubeadmapi.InitConfiguration
|
|
||||||
IsControlPlaneNode() bool
|
IsControlPlaneNode() bool
|
||||||
Client() clientset.Interface
|
|
||||||
IgnorePreflightErrors() sets.Set[string]
|
|
||||||
PatchesDir() string
|
|
||||||
KubeConfigPath() string
|
KubeConfigPath() string
|
||||||
OutputWriter() io.Writer
|
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Package node holds phases of "kubeadm upgrade node".
|
// Package node implements phases of 'kubeadm upgrade node'.
|
||||||
package node
|
package node
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -28,7 +28,7 @@ import (
|
|||||||
"k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade"
|
"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 {
|
func NewKubeconfigPhase() workflow.Phase {
|
||||||
phase := workflow.Phase{
|
phase := workflow.Phase{
|
||||||
Name: "kubeconfig",
|
Name: "kubeconfig",
|
||||||
@ -36,6 +36,7 @@ func NewKubeconfigPhase() workflow.Phase {
|
|||||||
Run: runKubeconfig(),
|
Run: runKubeconfig(),
|
||||||
Hidden: true,
|
Hidden: true,
|
||||||
InheritFlags: []string{
|
InheritFlags: []string{
|
||||||
|
options.CfgPath,
|
||||||
options.DryRun,
|
options.DryRun,
|
||||||
options.KubeconfigPath,
|
options.KubeconfigPath,
|
||||||
},
|
},
|
||||||
@ -50,23 +51,22 @@ func runKubeconfig() func(c workflow.RunData) error {
|
|||||||
return errors.New("kubeconfig phase invoked with an invalid data struct")
|
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() {
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// otherwise, retrieve all the info required for kubeconfig upgrade
|
// Otherwise, retrieve all the info required for kubeconfig upgrade.
|
||||||
cfg := data.InitCfg()
|
cfg := data.InitCfg()
|
||||||
dryRun := data.DryRun()
|
|
||||||
|
|
||||||
if features.Enabled(cfg.FeatureGates, features.ControlPlaneKubeletLocalMode) {
|
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")
|
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
|
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"
|
"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 {
|
func NewPreflightPhase() workflow.Phase {
|
||||||
return workflow.Phase{
|
return workflow.Phase{
|
||||||
Name: "preflight",
|
Name: "preflight",
|
||||||
@ -36,6 +36,7 @@ func NewPreflightPhase() workflow.Phase {
|
|||||||
Long: "Run pre-flight checks for kubeadm upgrade node.",
|
Long: "Run pre-flight checks for kubeadm upgrade node.",
|
||||||
Run: runPreflight,
|
Run: runPreflight,
|
||||||
InheritFlags: []string{
|
InheritFlags: []string{
|
||||||
|
options.CfgPath,
|
||||||
options.IgnorePreflightErrors,
|
options.IgnorePreflightErrors,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -47,14 +48,14 @@ func runPreflight(c workflow.RunData) error {
|
|||||||
if !ok {
|
if !ok {
|
||||||
return errors.New("preflight phase invoked with an invalid data struct")
|
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 {
|
if err := preflight.RunRootCheckOnly(data.IgnorePreflightErrors()); err != nil {
|
||||||
return err
|
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() {
|
if data.IsControlPlaneNode() {
|
||||||
// Update the InitConfiguration used for RunPullImagesCheck with ImagePullPolicy and ImagePullSerial
|
// Update the InitConfiguration used for RunPullImagesCheck with ImagePullPolicy and ImagePullSerial
|
||||||
// that come from UpgradeNodeConfiguration.
|
// that come from UpgradeNodeConfiguration.
|
||||||
@ -63,17 +64,17 @@ func runPreflight(c workflow.RunData) error {
|
|||||||
initConfig.NodeRegistration.ImagePullSerial = data.Cfg().Node.ImagePullSerial
|
initConfig.NodeRegistration.ImagePullSerial = data.Cfg().Node.ImagePullSerial
|
||||||
|
|
||||||
if !data.DryRun() {
|
if !data.DryRun() {
|
||||||
fmt.Println("[preflight] Pulling images required for setting up a Kubernetes cluster")
|
fmt.Println("[upgrade/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("[upgrade/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] You can also perform this action beforehand using 'kubeadm config images pull'")
|
||||||
if err := preflight.RunPullImagesCheck(utilsexec.New(), initConfig, data.IgnorePreflightErrors()); err != nil {
|
if err := preflight.RunPullImagesCheck(utilsexec.New(), initConfig, data.IgnorePreflightErrors()); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
} 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 {
|
} else {
|
||||||
fmt.Println("[preflight] Skipping prepull. Not a control plane node.")
|
fmt.Println("[upgrade/preflight] Skipping prepull. Not a control plane node.")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,8 +14,8 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Package apply implements phases of 'kubeadm upgrade apply'.
|
// Package upgrade holds the common phases for 'kubeadm upgrade'.
|
||||||
package apply
|
package upgrade
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
@ -41,7 +41,7 @@ func NewPostUpgradePhase() workflow.Phase {
|
|||||||
func runPostUpgrade(c workflow.RunData) error {
|
func runPostUpgrade(c workflow.RunData) error {
|
||||||
_, ok := c.(Data)
|
_, ok := c.(Data)
|
||||||
if !ok {
|
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.
|
// 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/v1beta4"
|
||||||
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation"
|
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation"
|
||||||
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/options"
|
"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"
|
phases "k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/upgrade/apply"
|
||||||
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow"
|
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow"
|
||||||
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
|
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.NewControlPlanePhase())
|
||||||
applyRunner.AppendPhase(phases.NewUploadConfigPhase())
|
applyRunner.AppendPhase(phases.NewUploadConfigPhase())
|
||||||
applyRunner.AppendPhase(phases.NewKubeconfigPhase())
|
applyRunner.AppendPhase(phases.NewKubeconfigPhase())
|
||||||
applyRunner.AppendPhase(phases.NewKubeletConfigPhase())
|
applyRunner.AppendPhase(commonphases.NewKubeletConfigPhase())
|
||||||
applyRunner.AppendPhase(phases.NewBootstrapTokenPhase())
|
applyRunner.AppendPhase(phases.NewBootstrapTokenPhase())
|
||||||
applyRunner.AppendPhase(phases.NewAddonPhase())
|
applyRunner.AppendPhase(commonphases.NewAddonPhase())
|
||||||
applyRunner.AppendPhase(phases.NewPostUpgradePhase())
|
applyRunner.AppendPhase(commonphases.NewPostUpgradePhase())
|
||||||
|
|
||||||
// Sets the data builder function, that will be used by the runner,
|
// Sets the data builder function, that will be used by the runner,
|
||||||
// both when running the entire workflow or single phases.
|
// 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/v1beta4"
|
||||||
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation"
|
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation"
|
||||||
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/options"
|
"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"
|
phases "k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/upgrade/node"
|
||||||
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow"
|
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow"
|
||||||
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
|
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.NewPreflightPhase())
|
||||||
nodeRunner.AppendPhase(phases.NewControlPlane())
|
nodeRunner.AppendPhase(phases.NewControlPlane())
|
||||||
nodeRunner.AppendPhase(phases.NewKubeconfigPhase())
|
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
|
// sets the data builder function, that will be used by the runner
|
||||||
// both when running the entire workflow or single phases
|
// both when running the entire workflow or single phases
|
||||||
|
@ -25,7 +25,6 @@ import (
|
|||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/labels"
|
"k8s.io/apimachinery/pkg/labels"
|
||||||
errorsutil "k8s.io/apimachinery/pkg/util/errors"
|
errorsutil "k8s.io/apimachinery/pkg/util/errors"
|
||||||
@ -36,79 +35,11 @@ import (
|
|||||||
|
|
||||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||||
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
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"
|
kubeletphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/kubelet"
|
||||||
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
||||||
dryrunutil "k8s.io/kubernetes/cmd/kubeadm/app/util/dryrun"
|
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.
|
// 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.
|
// 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