mirror of https://github.com/k3s-io/k3s
Merge pull request #73163 from MalloZup/phases-preflight
expose preflight join as phasespull/564/head
commit
f2ade8e993
|
@ -17,7 +17,6 @@ limitations under the License.
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
|
@ -38,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"
|
||||
|
@ -68,17 +68,6 @@ var (
|
|||
|
||||
`)
|
||||
|
||||
notReadyToJoinControPlaneTemp = template.Must(template.New("join").Parse(dedent.Dedent(`
|
||||
One or more conditions for hosting a new control plane instance is not satisfied.
|
||||
|
||||
{{.Error}}
|
||||
|
||||
Please ensure that:
|
||||
* The cluster has a stable controlPlaneEndpoint address.
|
||||
* The certificates that must be shared among control plane instances are provided.
|
||||
|
||||
`)))
|
||||
|
||||
joinControPlaneDoneTemp = template.Must(template.New("join").Parse(dedent.Dedent(`
|
||||
This node has joined the cluster and a new control plane instance was created:
|
||||
|
||||
|
@ -210,9 +199,7 @@ func NewCmdJoin(out io.Writer, joinOptions *joinOptions) *cobra.Command {
|
|||
AddJoinConfigFlags(cmd.Flags(), joinOptions.externalcfg)
|
||||
AddJoinOtherFlags(cmd.Flags(), &joinOptions.cfgPath, &joinOptions.ignorePreflightErrors, &joinOptions.controlPlane, &joinOptions.token)
|
||||
|
||||
// initialize the workflow runner with the list of phases
|
||||
// TODO: append phases here like so:
|
||||
// joinRunner.AppendPhase(phases.NewPreflightMasterPhase())
|
||||
joinRunner.AppendPhase(phases.NewPreflightJoinPhase())
|
||||
|
||||
// sets the data builder function, that will be used by the runner
|
||||
// both when running the entire workflow or single phases
|
||||
|
@ -445,14 +432,6 @@ func (j *joinData) OutputWriter() io.Writer {
|
|||
|
||||
// Run executes worker node provisioning and tries to join an existing cluster.
|
||||
func (j *joinData) Run() error {
|
||||
fmt.Println("[preflight] Running pre-flight checks")
|
||||
|
||||
// Start with general checks
|
||||
klog.V(1).Infoln("[preflight] Running general checks")
|
||||
if err := preflight.RunJoinNodeChecks(utilsexec.New(), j.cfg, j.ignorePreflightErrors); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Fetch the init configuration based on the join configuration.
|
||||
// TODO: individual phases should call these:
|
||||
// - phases that need initCfg should call joinData.InitCfg().
|
||||
|
@ -465,35 +444,7 @@ func (j *joinData) Run() error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Continue with more specific checks based on the init configuration
|
||||
klog.V(1).Infoln("[preflight] Running configuration dependant checks")
|
||||
if err := preflight.RunOptionalJoinNodeChecks(utilsexec.New(), &initCfg.ClusterConfiguration, j.ignorePreflightErrors); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if j.cfg.ControlPlane != nil {
|
||||
// Checks if the cluster configuration supports
|
||||
// joining a new control plane instance and if all the necessary certificates are provided
|
||||
if err := j.CheckIfReadyForAdditionalControlPlane(&initCfg.ClusterConfiguration); err != nil {
|
||||
// outputs the not ready for hosting a new control plane instance message
|
||||
ctx := map[string]string{
|
||||
"Error": err.Error(),
|
||||
}
|
||||
|
||||
var msg bytes.Buffer
|
||||
notReadyToJoinControPlaneTemp.Execute(&msg, ctx)
|
||||
return errors.New(msg.String())
|
||||
}
|
||||
|
||||
// run kubeadm init preflight checks for checking all the prequisites
|
||||
fmt.Println("[join] Running pre-flight checks before initializing the new control plane instance")
|
||||
preflight.RunInitMasterChecks(utilsexec.New(), initCfg, j.ignorePreflightErrors)
|
||||
|
||||
fmt.Println("[join] Pulling control-plane images")
|
||||
if err := preflight.RunPullImagesCheck(utilsexec.New(), initCfg, j.ignorePreflightErrors); err != nil {
|
||||
return err
|
||||
}
|
||||
// Prepares the node for hosting a new control plane instance by writing necessary
|
||||
// kubeconfig files, and static pod manifests
|
||||
if err := j.PrepareForHostingControlPlane(initCfg); err != nil {
|
||||
|
@ -539,22 +490,6 @@ func (j *joinData) Run() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// CheckIfReadyForAdditionalControlPlane ensures that the cluster is in a state that supports
|
||||
// joining an additional control plane instance and if the node is ready to join
|
||||
func (j *joinData) CheckIfReadyForAdditionalControlPlane(cfg *kubeadmapi.ClusterConfiguration) error {
|
||||
// blocks if the cluster was created without a stable control plane endpoint
|
||||
if cfg.ControlPlaneEndpoint == "" {
|
||||
return errors.New("unable to add a new control plane instance a cluster that doesn't have a stable controlPlaneEndpoint address")
|
||||
}
|
||||
|
||||
// checks if the certificates that must be equal across contolplane instances are provided
|
||||
if ret, err := certsphase.SharedCertificateExists(cfg); !ret {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// PrepareForHostingControlPlane makes all preparation activities require for a node hosting a new control plane instance
|
||||
func (j *joinData) PrepareForHostingControlPlane(initConfiguration *kubeadmapi.InitConfiguration) error {
|
||||
|
||||
|
|
|
@ -17,23 +17,43 @@ limitations under the License.
|
|||
package phases
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"text/template"
|
||||
|
||||
"github.com/lithammer/dedent"
|
||||
"github.com/pkg/errors"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/klog"
|
||||
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"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/phases/certs"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/preflight"
|
||||
"k8s.io/kubernetes/pkg/util/normalizer"
|
||||
utilsexec "k8s.io/utils/exec"
|
||||
)
|
||||
|
||||
var (
|
||||
masterPreflightExample = normalizer.Examples(`
|
||||
initPreflightExample = normalizer.Examples(`
|
||||
# Run master pre-flight checks using a config file.
|
||||
kubeadm init phase preflight --config kubeadm-config.yml
|
||||
`)
|
||||
joinPreflightExample = normalizer.Examples(`
|
||||
# Run join pre-flight checks using a config file.
|
||||
kubeadm join phase preflight --config kubeadm-config.yml
|
||||
`)
|
||||
|
||||
notReadyToJoinControPlaneTemp = template.Must(template.New("join").Parse(dedent.Dedent(`
|
||||
One or more conditions for hosting a new control plane instance is not satisfied.
|
||||
|
||||
{{.Error}}
|
||||
|
||||
Please ensure that:
|
||||
* The cluster has a stable controlPlaneEndpoint address.
|
||||
* The certificates that must be shared among control plane instances are provided.
|
||||
|
||||
`)))
|
||||
)
|
||||
|
||||
// preflightMasterData defines the behavior that a runtime data struct passed to the PreflightMaster master phase
|
||||
|
@ -45,13 +65,19 @@ type preflightMasterData interface {
|
|||
IgnorePreflightErrors() sets.String
|
||||
}
|
||||
|
||||
type preflightJoinData interface {
|
||||
Cfg() *kubeadmapi.JoinConfiguration
|
||||
InitCfg() (*kubeadmapi.InitConfiguration, error)
|
||||
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,
|
||||
Example: initPreflightExample,
|
||||
Run: runPreflightMaster,
|
||||
InheritFlags: []string{
|
||||
options.CfgPath,
|
||||
|
@ -60,6 +86,7 @@ func NewPreflightMasterPhase() workflow.Phase {
|
|||
}
|
||||
}
|
||||
|
||||
// TODO(dmaiocchi): rename all instances of master to controlPlane in this file.
|
||||
// runPreflightMaster executes preflight checks logic.
|
||||
func runPreflightMaster(c workflow.RunData) error {
|
||||
data, ok := c.(preflightMasterData)
|
||||
|
@ -85,3 +112,96 @@ func runPreflightMaster(c workflow.RunData) error {
|
|||
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewPreflightJoinPhase creates a kubeadm workflow phase that implements preflight checks for a new node join
|
||||
func NewPreflightJoinPhase() workflow.Phase {
|
||||
return workflow.Phase{
|
||||
Name: "preflight",
|
||||
Short: "Run join pre-flight checks",
|
||||
Long: "Run join pre-flight checks, functionally equivalent to what is implemented by kubeadm join.",
|
||||
Example: joinPreflightExample,
|
||||
Run: runPreflightJoin,
|
||||
InheritFlags: []string{
|
||||
options.CfgPath,
|
||||
options.IgnorePreflightErrors,
|
||||
options.TLSBootstrapToken,
|
||||
options.TokenStr,
|
||||
options.ControlPlane,
|
||||
options.APIServerAdvertiseAddress,
|
||||
options.APIServerBindPort,
|
||||
options.NodeCRISocket,
|
||||
options.NodeName,
|
||||
options.FileDiscovery,
|
||||
options.TokenDiscovery,
|
||||
options.TokenDiscoveryCAHash,
|
||||
options.TokenDiscoverySkipCAHash,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// runPreflightJoin executes preflight checks logic.
|
||||
func runPreflightJoin(c workflow.RunData) error {
|
||||
j, ok := c.(preflightJoinData)
|
||||
if !ok {
|
||||
return errors.New("preflight phase invoked with an invalid data struct")
|
||||
}
|
||||
// Start with general checks
|
||||
klog.V(1).Infoln("[preflight] Running general checks")
|
||||
if err := preflight.RunJoinNodeChecks(utilsexec.New(), j.Cfg(), j.IgnorePreflightErrors()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
initCfg, err := j.InitCfg()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Continue with more specific checks based on the init configuration
|
||||
klog.V(1).Infoln("[preflight] Running configuration dependant checks")
|
||||
if err := preflight.RunOptionalJoinNodeChecks(utilsexec.New(), &initCfg.ClusterConfiguration, j.IgnorePreflightErrors()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if j.Cfg().ControlPlane != nil {
|
||||
// Checks if the cluster configuration supports
|
||||
// joining a new control plane instance and if all the necessary certificates are provided
|
||||
if err := checkIfReadyForAdditionalControlPlane(&initCfg.ClusterConfiguration); err != nil {
|
||||
// outputs the not ready for hosting a new control plane instance message
|
||||
ctx := map[string]string{
|
||||
"Error": err.Error(),
|
||||
}
|
||||
|
||||
var msg bytes.Buffer
|
||||
notReadyToJoinControPlaneTemp.Execute(&msg, ctx)
|
||||
return errors.New(msg.String())
|
||||
}
|
||||
|
||||
// run kubeadm init preflight checks for checking all the prequisites
|
||||
fmt.Println("[preflight] Running pre-flight checks before initializing the new control plane instance")
|
||||
if err := preflight.RunInitMasterChecks(utilsexec.New(), initCfg, j.IgnorePreflightErrors()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Println("[preflight] Pulling control-plane images")
|
||||
if err := preflight.RunPullImagesCheck(utilsexec.New(), initCfg, j.IgnorePreflightErrors()); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// checkIfReadyForAdditionalControlPlane ensures that the cluster is in a state that supports
|
||||
// joining an additional control plane instance and if the node is ready to preflight
|
||||
func checkIfReadyForAdditionalControlPlane(initConfiguration *kubeadmapi.ClusterConfiguration) error {
|
||||
// blocks if the cluster was created without a stable control plane endpoint
|
||||
if initConfiguration.ControlPlaneEndpoint == "" {
|
||||
return errors.New("unable to add a new control plane instance a cluster that doesn't have a stable controlPlaneEndpoint address")
|
||||
}
|
||||
|
||||
// checks if the certificates that must be equal across contolplane instances are provided
|
||||
if ret, err := certs.SharedCertificateExists(initConfiguration); !ret {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue