mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-28 14:07:14 +00:00
kubeadm: add pull images check in upgrade apply and upgrade node
Signed-off-by: Xianglin Gao <xianglin.gxl@alibaba-inc.com>
This commit is contained in:
parent
6c6a702a99
commit
a169305207
@ -6,6 +6,7 @@ go_library(
|
|||||||
"controlplane.go",
|
"controlplane.go",
|
||||||
"data.go",
|
"data.go",
|
||||||
"kubeletconfig.go",
|
"kubeletconfig.go",
|
||||||
|
"preflight.go",
|
||||||
],
|
],
|
||||||
importpath = "k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/upgrade/node",
|
importpath = "k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/upgrade/node",
|
||||||
visibility = ["//visibility:public"],
|
visibility = ["//visibility:public"],
|
||||||
@ -17,11 +18,14 @@ go_library(
|
|||||||
"//cmd/kubeadm/app/constants:go_default_library",
|
"//cmd/kubeadm/app/constants:go_default_library",
|
||||||
"//cmd/kubeadm/app/phases/kubelet:go_default_library",
|
"//cmd/kubeadm/app/phases/kubelet:go_default_library",
|
||||||
"//cmd/kubeadm/app/phases/upgrade:go_default_library",
|
"//cmd/kubeadm/app/phases/upgrade:go_default_library",
|
||||||
|
"//cmd/kubeadm/app/preflight:go_default_library",
|
||||||
"//cmd/kubeadm/app/util/apiclient:go_default_library",
|
"//cmd/kubeadm/app/util/apiclient:go_default_library",
|
||||||
"//cmd/kubeadm/app/util/dryrun:go_default_library",
|
"//cmd/kubeadm/app/util/dryrun:go_default_library",
|
||||||
|
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/util/version:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/util/version:go_default_library",
|
||||||
"//staging/src/k8s.io/client-go/kubernetes:go_default_library",
|
"//staging/src/k8s.io/client-go/kubernetes:go_default_library",
|
||||||
"//vendor/github.com/pkg/errors:go_default_library",
|
"//vendor/github.com/pkg/errors:go_default_library",
|
||||||
|
"//vendor/k8s.io/utils/exec:go_default_library",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -17,6 +17,7 @@ limitations under the License.
|
|||||||
package node
|
package node
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"k8s.io/apimachinery/pkg/util/sets"
|
||||||
clientset "k8s.io/client-go/kubernetes"
|
clientset "k8s.io/client-go/kubernetes"
|
||||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||||
)
|
)
|
||||||
@ -31,5 +32,6 @@ type Data interface {
|
|||||||
Cfg() *kubeadmapi.InitConfiguration
|
Cfg() *kubeadmapi.InitConfiguration
|
||||||
IsControlPlaneNode() bool
|
IsControlPlaneNode() bool
|
||||||
Client() clientset.Interface
|
Client() clientset.Interface
|
||||||
|
IgnorePreflightErrors() sets.String
|
||||||
KustomizeDir() string
|
KustomizeDir() string
|
||||||
}
|
}
|
||||||
|
73
cmd/kubeadm/app/cmd/phases/upgrade/node/preflight.go
Normal file
73
cmd/kubeadm/app/cmd/phases/upgrade/node/preflight.go
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2017 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"
|
||||||
|
"k8s.io/kubernetes/cmd/kubeadm/app/preflight"
|
||||||
|
utilsexec "k8s.io/utils/exec"
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewPreflightPhase creates a kubeadm workflow phase that implements preflight checks for a new node join
|
||||||
|
func NewPreflightPhase() workflow.Phase {
|
||||||
|
return workflow.Phase{
|
||||||
|
Name: "preflight",
|
||||||
|
Short: "Run upgrade node pre-flight checks",
|
||||||
|
Long: "Run pre-flight checks for kubeadm upgrade node.",
|
||||||
|
Run: runPreflight,
|
||||||
|
InheritFlags: []string{
|
||||||
|
options.IgnorePreflightErrors,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// runPreflight executes preflight checks logic.
|
||||||
|
func runPreflight(c workflow.RunData) error {
|
||||||
|
data, ok := c.(Data)
|
||||||
|
if !ok {
|
||||||
|
return errors.New("preflight phase invoked with an invalid data struct")
|
||||||
|
}
|
||||||
|
fmt.Println("[preflight] Running pre-flight checks")
|
||||||
|
|
||||||
|
// 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 data.IsControlPlaneNode() {
|
||||||
|
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 in beforehand using 'kubeadm config images pull'")
|
||||||
|
if err := preflight.RunPullImagesCheck(utilsexec.New(), data.Cfg(), data.IgnorePreflightErrors()); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fmt.Println("[preflight] Would pull the required images (like 'kubeadm config images pull')")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fmt.Println("[preflight] Skipping prepull. Not a control plane node.")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
@ -42,6 +42,7 @@ go_library(
|
|||||||
"//vendor/github.com/spf13/cobra:go_default_library",
|
"//vendor/github.com/spf13/cobra:go_default_library",
|
||||||
"//vendor/github.com/spf13/pflag:go_default_library",
|
"//vendor/github.com/spf13/pflag:go_default_library",
|
||||||
"//vendor/k8s.io/klog:go_default_library",
|
"//vendor/k8s.io/klog:go_default_library",
|
||||||
|
"//vendor/k8s.io/utils/exec:go_default_library",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -18,9 +18,11 @@ package upgrade
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
"k8s.io/apimachinery/pkg/util/sets"
|
||||||
"k8s.io/apimachinery/pkg/util/version"
|
"k8s.io/apimachinery/pkg/util/version"
|
||||||
clientset "k8s.io/client-go/kubernetes"
|
clientset "k8s.io/client-go/kubernetes"
|
||||||
"k8s.io/klog"
|
"k8s.io/klog"
|
||||||
@ -28,9 +30,15 @@ import (
|
|||||||
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/options"
|
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/options"
|
||||||
"k8s.io/kubernetes/cmd/kubeadm/app/features"
|
"k8s.io/kubernetes/cmd/kubeadm/app/features"
|
||||||
"k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade"
|
"k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade"
|
||||||
|
"k8s.io/kubernetes/cmd/kubeadm/app/preflight"
|
||||||
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
||||||
"k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient"
|
"k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient"
|
||||||
configutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config"
|
configutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config"
|
||||||
|
utilsexec "k8s.io/utils/exec"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
defaultImagePullTimeout = 15 * time.Minute
|
||||||
)
|
)
|
||||||
|
|
||||||
// applyFlags holds the information about the flags that can be passed to apply
|
// applyFlags holds the information about the flags that can be passed to apply
|
||||||
@ -42,6 +50,7 @@ type applyFlags struct {
|
|||||||
dryRun bool
|
dryRun bool
|
||||||
etcdUpgrade bool
|
etcdUpgrade bool
|
||||||
renewCerts bool
|
renewCerts bool
|
||||||
|
imagePullTimeout time.Duration
|
||||||
kustomizeDir string
|
kustomizeDir string
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -53,9 +62,10 @@ func (f *applyFlags) sessionIsInteractive() bool {
|
|||||||
// NewCmdApply returns the cobra command for `kubeadm upgrade apply`
|
// NewCmdApply returns the cobra command for `kubeadm upgrade apply`
|
||||||
func NewCmdApply(apf *applyPlanFlags) *cobra.Command {
|
func NewCmdApply(apf *applyPlanFlags) *cobra.Command {
|
||||||
flags := &applyFlags{
|
flags := &applyFlags{
|
||||||
applyPlanFlags: apf,
|
applyPlanFlags: apf,
|
||||||
etcdUpgrade: true,
|
imagePullTimeout: defaultImagePullTimeout,
|
||||||
renewCerts: true,
|
etcdUpgrade: true,
|
||||||
|
renewCerts: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
@ -80,6 +90,9 @@ func NewCmdApply(apf *applyPlanFlags) *cobra.Command {
|
|||||||
cmd.Flags().BoolVar(&flags.dryRun, options.DryRun, flags.dryRun, "Do not change any state, just output what actions would be performed.")
|
cmd.Flags().BoolVar(&flags.dryRun, options.DryRun, flags.dryRun, "Do not change any state, just output what actions would be performed.")
|
||||||
cmd.Flags().BoolVar(&flags.etcdUpgrade, "etcd-upgrade", flags.etcdUpgrade, "Perform the upgrade of etcd.")
|
cmd.Flags().BoolVar(&flags.etcdUpgrade, "etcd-upgrade", flags.etcdUpgrade, "Perform the upgrade of etcd.")
|
||||||
cmd.Flags().BoolVar(&flags.renewCerts, options.CertificateRenewal, flags.renewCerts, "Perform the renewal of certificates used by component changed during upgrades.")
|
cmd.Flags().BoolVar(&flags.renewCerts, options.CertificateRenewal, flags.renewCerts, "Perform the renewal of certificates used by component changed during upgrades.")
|
||||||
|
cmd.Flags().DurationVar(&flags.imagePullTimeout, "image-pull-timeout", flags.imagePullTimeout, "The maximum amount of time to wait for the control plane pods to be downloaded.")
|
||||||
|
// TODO: The flag was deprecated in 1.19; remove the flag following a GA deprecation policy of 12 months or 2 releases (whichever is longer)
|
||||||
|
cmd.Flags().MarkDeprecated("image-pull-timeout", "This flag is deprecated and will be removed in a future version.")
|
||||||
options.AddKustomizePodsFlag(cmd.Flags(), &flags.kustomizeDir)
|
options.AddKustomizePodsFlag(cmd.Flags(), &flags.kustomizeDir)
|
||||||
|
|
||||||
return cmd
|
return cmd
|
||||||
@ -136,6 +149,17 @@ func runApply(flags *applyFlags, userVersion string) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !flags.dryRun {
|
||||||
|
fmt.Println("[upgrade/prepull] Pulling images required for setting up a Kubernetes cluster")
|
||||||
|
fmt.Println("[upgrade/prepull] This might take a minute or two, depending on the speed of your internet connection")
|
||||||
|
fmt.Println("[upgrade/prepull] You can also perform this action in beforehand using 'kubeadm config images pull'")
|
||||||
|
if err := preflight.RunPullImagesCheck(utilsexec.New(), cfg, sets.NewString(cfg.NodeRegistration.IgnorePreflightErrors...)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fmt.Println("[upgrade/prepull] Would pull the required images (like 'kubeadm config images pull')")
|
||||||
|
}
|
||||||
|
|
||||||
waiter := getWaiter(flags.dryRun, client, upgrade.UpgradeManifestTimeout)
|
waiter := getWaiter(flags.dryRun, client, upgrade.UpgradeManifestTimeout)
|
||||||
|
|
||||||
// Now; perform the upgrade procedure
|
// Now; perform the upgrade procedure
|
||||||
|
@ -23,8 +23,10 @@ import (
|
|||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
flag "github.com/spf13/pflag"
|
flag "github.com/spf13/pflag"
|
||||||
|
|
||||||
|
"k8s.io/apimachinery/pkg/util/sets"
|
||||||
clientset "k8s.io/client-go/kubernetes"
|
clientset "k8s.io/client-go/kubernetes"
|
||||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||||
|
"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"
|
||||||
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"
|
||||||
@ -36,12 +38,13 @@ import (
|
|||||||
// Please note that this structure includes the public kubeadm config API, but only a subset of the options
|
// Please note that this structure includes the public kubeadm config API, but only a subset of the options
|
||||||
// supported by this api will be exposed as a flag.
|
// supported by this api will be exposed as a flag.
|
||||||
type nodeOptions struct {
|
type nodeOptions struct {
|
||||||
kubeConfigPath string
|
kubeConfigPath string
|
||||||
kubeletVersion string
|
kubeletVersion string
|
||||||
etcdUpgrade bool
|
etcdUpgrade bool
|
||||||
renewCerts bool
|
renewCerts bool
|
||||||
dryRun bool
|
dryRun bool
|
||||||
kustomizeDir string
|
kustomizeDir string
|
||||||
|
ignorePreflightErrors []string
|
||||||
}
|
}
|
||||||
|
|
||||||
// compile-time assert that the local data object satisfies the phases data interface.
|
// compile-time assert that the local data object satisfies the phases data interface.
|
||||||
@ -50,14 +53,15 @@ var _ phases.Data = &nodeData{}
|
|||||||
// nodeData defines all the runtime information used when running the kubeadm upgrade node worklow;
|
// nodeData defines all the runtime information used when running the kubeadm upgrade node worklow;
|
||||||
// this data is shared across all the phases that are included in the workflow.
|
// this data is shared across all the phases that are included in the workflow.
|
||||||
type nodeData struct {
|
type nodeData struct {
|
||||||
etcdUpgrade bool
|
etcdUpgrade bool
|
||||||
renewCerts bool
|
renewCerts bool
|
||||||
dryRun bool
|
dryRun bool
|
||||||
kubeletVersion string
|
kubeletVersion string
|
||||||
cfg *kubeadmapi.InitConfiguration
|
cfg *kubeadmapi.InitConfiguration
|
||||||
isControlPlaneNode bool
|
isControlPlaneNode bool
|
||||||
client clientset.Interface
|
client clientset.Interface
|
||||||
kustomizeDir string
|
kustomizeDir string
|
||||||
|
ignorePreflightErrors sets.String
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewCmdNode returns the cobra command for `kubeadm upgrade node`
|
// NewCmdNode returns the cobra command for `kubeadm upgrade node`
|
||||||
@ -80,6 +84,7 @@ func NewCmdNode() *cobra.Command {
|
|||||||
options.AddKustomizePodsFlag(cmd.Flags(), &nodeOptions.kustomizeDir)
|
options.AddKustomizePodsFlag(cmd.Flags(), &nodeOptions.kustomizeDir)
|
||||||
|
|
||||||
// initialize the workflow runner with the list of phases
|
// initialize the workflow runner with the list of phases
|
||||||
|
nodeRunner.AppendPhase(phases.NewPreflightPhase())
|
||||||
nodeRunner.AppendPhase(phases.NewControlPlane())
|
nodeRunner.AppendPhase(phases.NewControlPlane())
|
||||||
nodeRunner.AppendPhase(phases.NewKubeletConfigPhase())
|
nodeRunner.AppendPhase(phases.NewKubeletConfigPhase())
|
||||||
|
|
||||||
@ -113,6 +118,7 @@ func addUpgradeNodeFlags(flagSet *flag.FlagSet, nodeOptions *nodeOptions) {
|
|||||||
flagSet.MarkDeprecated(options.KubeletVersion, "This flag is deprecated and will be removed in a future version.")
|
flagSet.MarkDeprecated(options.KubeletVersion, "This flag is deprecated and will be removed in a future version.")
|
||||||
flagSet.BoolVar(&nodeOptions.renewCerts, options.CertificateRenewal, nodeOptions.renewCerts, "Perform the renewal of certificates used by component changed during upgrades.")
|
flagSet.BoolVar(&nodeOptions.renewCerts, options.CertificateRenewal, nodeOptions.renewCerts, "Perform the renewal of certificates used by component changed during upgrades.")
|
||||||
flagSet.BoolVar(&nodeOptions.etcdUpgrade, options.EtcdUpgrade, nodeOptions.etcdUpgrade, "Perform the upgrade of etcd.")
|
flagSet.BoolVar(&nodeOptions.etcdUpgrade, options.EtcdUpgrade, nodeOptions.etcdUpgrade, "Perform the upgrade of etcd.")
|
||||||
|
flagSet.StringSliceVar(&nodeOptions.ignorePreflightErrors, options.IgnorePreflightErrors, nodeOptions.ignorePreflightErrors, "A list of checks whose errors will be shown as warnings. Example: 'IsPrivilegedUser,Swap'. Value 'all' ignores errors from all checks.")
|
||||||
}
|
}
|
||||||
|
|
||||||
// newNodeData returns a new nodeData struct to be used for the execution of the kubeadm upgrade node workflow.
|
// newNodeData returns a new nodeData struct to be used for the execution of the kubeadm upgrade node workflow.
|
||||||
@ -140,15 +146,23 @@ func newNodeData(cmd *cobra.Command, args []string, options *nodeOptions) (*node
|
|||||||
return nil, errors.Wrap(err, "unable to fetch the kubeadm-config ConfigMap")
|
return nil, errors.Wrap(err, "unable to fetch the kubeadm-config ConfigMap")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ignorePreflightErrorsSet, err := validation.ValidateIgnorePreflightErrors(options.ignorePreflightErrors, cfg.NodeRegistration.IgnorePreflightErrors)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
// Also set the union of pre-flight errors to JoinConfiguration, to provide a consistent view of the runtime configuration:
|
||||||
|
cfg.NodeRegistration.IgnorePreflightErrors = ignorePreflightErrorsSet.List()
|
||||||
|
|
||||||
return &nodeData{
|
return &nodeData{
|
||||||
etcdUpgrade: options.etcdUpgrade,
|
etcdUpgrade: options.etcdUpgrade,
|
||||||
renewCerts: options.renewCerts,
|
renewCerts: options.renewCerts,
|
||||||
dryRun: options.dryRun,
|
dryRun: options.dryRun,
|
||||||
kubeletVersion: options.kubeletVersion,
|
kubeletVersion: options.kubeletVersion,
|
||||||
cfg: cfg,
|
cfg: cfg,
|
||||||
client: client,
|
client: client,
|
||||||
isControlPlaneNode: isControlPlaneNode,
|
isControlPlaneNode: isControlPlaneNode,
|
||||||
kustomizeDir: options.kustomizeDir,
|
kustomizeDir: options.kustomizeDir,
|
||||||
|
ignorePreflightErrors: ignorePreflightErrorsSet,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -191,3 +205,8 @@ func (d *nodeData) Client() clientset.Interface {
|
|||||||
func (d *nodeData) KustomizeDir() string {
|
func (d *nodeData) KustomizeDir() string {
|
||||||
return d.kustomizeDir
|
return d.kustomizeDir
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IgnorePreflightErrors returns the list of preflight errors to ignore.
|
||||||
|
func (d *nodeData) IgnorePreflightErrors() sets.String {
|
||||||
|
return d.ignorePreflightErrors
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user