mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-31 23:37:01 +00:00
kubeadm graduate preflight phase
This commit is contained in:
parent
ce7e7e3c34
commit
abac950cd7
@ -37,6 +37,7 @@ import (
|
||||
kubeadmapiv1beta1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta1"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/options"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow"
|
||||
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
|
||||
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||
@ -126,6 +127,9 @@ type initData struct {
|
||||
skipTokenPrint bool
|
||||
dryRun bool
|
||||
ignorePreflightErrors sets.String
|
||||
certificatesDir string
|
||||
dryRunDir string
|
||||
client clientset.Interface
|
||||
}
|
||||
|
||||
// NewCmdInit returns "kubeadm init" command.
|
||||
@ -160,7 +164,8 @@ func NewCmdInit(out io.Writer) *cobra.Command {
|
||||
options.bto.AddTTLFlag(cmd.PersistentFlags())
|
||||
|
||||
// initialize the workflow runner with the list of phases
|
||||
// TODO: add the phases to the runner. e.g. initRunner.AppendPhase(phases.PreflightMaster)
|
||||
initRunner.AppendPhase(phases.NewPreflightMasterPhase())
|
||||
// TODO: add other phases to the runner.
|
||||
|
||||
// sets the data builder function, that will be used by the runner
|
||||
// both when running the entire workflow or single phases
|
||||
@ -297,31 +302,113 @@ func newInitData(cmd *cobra.Command, options *initOptions) (initData, error) {
|
||||
return initData{}, err
|
||||
}
|
||||
|
||||
// if dry running creates a temporary folder for saving kubeadm generated files
|
||||
dryRunDir := ""
|
||||
if options.dryRun {
|
||||
if dryRunDir, err = ioutil.TempDir("", "kubeadm-init-dryrun"); err != nil {
|
||||
return initData{}, fmt.Errorf("couldn't create a temporary directory: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
return initData{
|
||||
cfg: cfg,
|
||||
certificatesDir: cfg.CertificatesDir,
|
||||
skipTokenPrint: options.skipTokenPrint,
|
||||
dryRun: options.dryRun,
|
||||
dryRunDir: dryRunDir,
|
||||
ignorePreflightErrors: ignorePreflightErrorsSet,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Cfg returns initConfiguration.
|
||||
func (d initData) Cfg() *kubeadmapi.InitConfiguration {
|
||||
return d.cfg
|
||||
}
|
||||
|
||||
// DryRun returns the DryRun flag.
|
||||
func (d initData) DryRun() bool {
|
||||
return d.dryRun
|
||||
}
|
||||
|
||||
// SkipTokenPrint returns the SkipTokenPrint flag.
|
||||
func (d initData) SkipTokenPrint() bool {
|
||||
return d.skipTokenPrint
|
||||
}
|
||||
|
||||
// IgnorePreflightErrors returns the IgnorePreflightErrors flag.
|
||||
func (d initData) IgnorePreflightErrors() sets.String {
|
||||
return d.ignorePreflightErrors
|
||||
}
|
||||
|
||||
// CertificateWriteDir returns the path to the certificate folder or the temporary folder path in case of DryRun.
|
||||
func (d initData) CertificateWriteDir() string {
|
||||
if d.dryRun {
|
||||
return d.dryRunDir
|
||||
}
|
||||
return d.certificatesDir
|
||||
}
|
||||
|
||||
// CertificateDir returns the CertificateDir as originally specified by the user.
|
||||
func (d initData) CertificateDir() string {
|
||||
return d.certificatesDir
|
||||
}
|
||||
|
||||
// KubeConfigDir returns the path of the kubernetes configuration folder or the temporary folder path in case of DryRun.
|
||||
func (d initData) KubeConfigDir() string {
|
||||
if d.dryRun {
|
||||
return d.dryRunDir
|
||||
}
|
||||
return kubeadmconstants.KubernetesDir
|
||||
}
|
||||
|
||||
// KubeConfigDir returns the path where manifest should be stored or the temporary folder path in case of DryRun.
|
||||
func (d initData) ManifestDir() string {
|
||||
if d.dryRun {
|
||||
return d.dryRunDir
|
||||
}
|
||||
return kubeadmconstants.GetStaticPodDirectory()
|
||||
}
|
||||
|
||||
// KubeletDir returns path of the kubelet configuration folder or the temporary folder in case of DryRun.
|
||||
func (d initData) KubeletDir() string {
|
||||
if d.dryRun {
|
||||
return d.dryRunDir
|
||||
}
|
||||
return kubeadmconstants.KubeletRunDirectory
|
||||
}
|
||||
|
||||
// Client returns a Kubernetes client to be used by kubeadm.
|
||||
// This function is implemented as a singleton, thus avoiding to recreate the client when it is used by different phases.
|
||||
// Important. This function must be called after the admin.conf kubeconfig file is created.
|
||||
func (d initData) Client() (clientset.Interface, error) {
|
||||
if d.client == nil {
|
||||
if d.dryRun {
|
||||
// If we're dry-running; we should create a faked client that answers some GETs in order to be able to do the full init flow and just logs the rest of requests
|
||||
dryRunGetter := apiclient.NewInitDryRunGetter(d.cfg.NodeRegistration.Name, d.cfg.Networking.ServiceSubnet)
|
||||
d.client = apiclient.NewDryRunClient(dryRunGetter, os.Stdout)
|
||||
} else {
|
||||
// If we're acting for real, we should create a connection to the API server and wait for it to come up
|
||||
var err error
|
||||
d.client, err = kubeconfigutil.ClientSetFromFile(kubeadmconstants.GetAdminKubeConfigPath())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
return d.client, nil
|
||||
}
|
||||
|
||||
// Tokens returns an array of token strings.
|
||||
func (d initData) Tokens() []string {
|
||||
tokens := []string{}
|
||||
for _, bt := range d.cfg.BootstrapTokens {
|
||||
tokens = append(tokens, bt.Token.String())
|
||||
}
|
||||
return tokens
|
||||
}
|
||||
|
||||
// runInit executes master node provisioning
|
||||
func runInit(i *initData, out io.Writer) error {
|
||||
fmt.Println("[preflight] running pre-flight checks")
|
||||
if err := preflight.RunInitMasterChecks(utilsexec.New(), i.cfg, i.ignorePreflightErrors); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !i.dryRun {
|
||||
fmt.Println("[preflight/images] Pulling images required for setting up a Kubernetes cluster")
|
||||
fmt.Println("[preflight/images] This might take a minute or two, depending on the speed of your internet connection")
|
||||
fmt.Println("[preflight/images] You can also perform this action in beforehand using 'kubeadm config images pull'")
|
||||
if err := preflight.RunPullImagesCheck(utilsexec.New(), i.cfg, i.ignorePreflightErrors); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
fmt.Println("[preflight/images] Would pull the required images (like 'kubeadm config images pull')")
|
||||
}
|
||||
|
||||
// Get directories to write files to; can be faked if we're dry-running
|
||||
glog.V(1).Infof("[init] Getting certificates directory from configuration")
|
||||
|
@ -21,11 +21,13 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
kubeadmscheme "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme"
|
||||
kubeadmapiv1beta1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta1"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation"
|
||||
"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/preflight"
|
||||
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
||||
@ -35,13 +37,9 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
masterPreflightLongDesc = normalizer.LongDesc(`
|
||||
Run master pre-flight checks, functionally equivalent to what implemented by kubeadm init.
|
||||
` + cmdutil.AlphaDisclaimer)
|
||||
|
||||
masterPreflightExample = normalizer.Examples(`
|
||||
# Run master pre-flight checks.
|
||||
kubeadm alpha phase preflight master
|
||||
# Run master pre-flight checks using a config file.
|
||||
kubeadm init phase preflight --config kubeadm-config.yml
|
||||
`)
|
||||
|
||||
nodePreflightLongDesc = normalizer.LongDesc(`
|
||||
@ -56,6 +54,52 @@ var (
|
||||
errorMissingConfigFlag = errors.New("the --config flag is mandatory")
|
||||
)
|
||||
|
||||
// preflightMasterData defines the behavior that a runtime data struct passed to the PreflightMaster master phase
|
||||
// should have. Please note that we are using an interface in order to make this phase reusable in different workflows
|
||||
// (and thus with different runtime data struct, all of them requested to be compliant to this interface)
|
||||
type preflightMasterData interface {
|
||||
Cfg() *kubeadmapi.InitConfiguration
|
||||
DryRun() bool
|
||||
IgnorePreflightErrors() sets.String
|
||||
}
|
||||
|
||||
// NewPreflightMasterPhase creates a kubeadm workflow phase that implements preflight checks for a new master node.
|
||||
func NewPreflightMasterPhase() workflow.Phase {
|
||||
return workflow.Phase{
|
||||
Name: "preflight",
|
||||
Short: "Run master pre-flight checks",
|
||||
Long: "Run master pre-flight checks, functionally equivalent to what implemented by kubeadm init.",
|
||||
Example: masterPreflightExample,
|
||||
Run: runPreflightMaster,
|
||||
}
|
||||
}
|
||||
|
||||
// runPreflightMaster executes preflight checks logic.
|
||||
func runPreflightMaster(c workflow.RunData) error {
|
||||
data, ok := c.(preflightMasterData)
|
||||
if !ok {
|
||||
return fmt.Errorf("preflight phase invoked with an invalid data struct")
|
||||
}
|
||||
|
||||
fmt.Println("[preflight] running pre-flight checks")
|
||||
if err := preflight.RunInitMasterChecks(utilsexec.New(), data.Cfg(), data.IgnorePreflightErrors()); err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
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')")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewCmdPreFlight calls cobra.Command for preflight checks
|
||||
func NewCmdPreFlight() *cobra.Command {
|
||||
var cfgPath string
|
||||
@ -70,47 +114,11 @@ func NewCmdPreFlight() *cobra.Command {
|
||||
options.AddConfigFlag(cmd.PersistentFlags(), &cfgPath)
|
||||
options.AddIgnorePreflightErrorsFlag(cmd.PersistentFlags(), &ignorePreflightErrors)
|
||||
|
||||
cmd.AddCommand(NewCmdPreFlightMaster(&cfgPath, &ignorePreflightErrors))
|
||||
cmd.AddCommand(NewCmdPreFlightNode(&cfgPath, &ignorePreflightErrors))
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
// NewCmdPreFlightMaster calls cobra.Command for master preflight checks
|
||||
func NewCmdPreFlightMaster(cfgPath *string, ignorePreflightErrors *[]string) *cobra.Command {
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "master",
|
||||
Short: "Run master pre-flight checks",
|
||||
Long: masterPreflightLongDesc,
|
||||
Example: masterPreflightExample,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
if len(*cfgPath) == 0 {
|
||||
kubeadmutil.CheckErr(errorMissingConfigFlag)
|
||||
}
|
||||
ignorePreflightErrorsSet, err := validation.ValidateIgnorePreflightErrors(*ignorePreflightErrors)
|
||||
kubeadmutil.CheckErr(err)
|
||||
|
||||
cfg := &kubeadmapiv1beta1.InitConfiguration{}
|
||||
kubeadmscheme.Scheme.Default(cfg)
|
||||
|
||||
internalcfg, err := configutil.ConfigFileAndDefaultsToInternalConfig(*cfgPath, cfg)
|
||||
kubeadmutil.CheckErr(err)
|
||||
err = configutil.VerifyAPIServerBindAddress(internalcfg.APIEndpoint.AdvertiseAddress)
|
||||
kubeadmutil.CheckErr(err)
|
||||
|
||||
fmt.Println("[preflight] running pre-flight checks")
|
||||
|
||||
err = preflight.RunInitMasterChecks(utilsexec.New(), internalcfg, ignorePreflightErrorsSet)
|
||||
kubeadmutil.CheckErr(err)
|
||||
|
||||
fmt.Println("[preflight] pre-flight checks passed")
|
||||
},
|
||||
}
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
// NewCmdPreFlightNode calls cobra.Command for node preflight checks
|
||||
func NewCmdPreFlightNode(cfgPath *string, ignorePreflightErrors *[]string) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
|
Loading…
Reference in New Issue
Block a user