mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-21 10:51:29 +00:00
kubeadm: move show-join-command as a separate phase
This commit is contained in:
parent
6dd8b86124
commit
8e4cf3b8d2
@ -21,9 +21,7 @@ import (
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"text/template"
|
||||
|
||||
"github.com/lithammer/dedent"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
flag "github.com/spf13/pflag"
|
||||
@ -48,46 +46,6 @@ import (
|
||||
kubeconfigutil "k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig"
|
||||
)
|
||||
|
||||
var (
|
||||
initDoneTempl = template.Must(template.New("init").Parse(dedent.Dedent(`
|
||||
Your Kubernetes control-plane has initialized successfully!
|
||||
|
||||
To start using your cluster, you need to run the following as a regular user:
|
||||
|
||||
mkdir -p $HOME/.kube
|
||||
sudo cp -i {{.KubeConfigPath}} $HOME/.kube/config
|
||||
sudo chown $(id -u):$(id -g) $HOME/.kube/config
|
||||
|
||||
Alternatively, if you are the root user, you can run:
|
||||
|
||||
export KUBECONFIG=/etc/kubernetes/admin.conf
|
||||
|
||||
You should now deploy a pod network to the cluster.
|
||||
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
|
||||
https://kubernetes.io/docs/concepts/cluster-administration/addons/
|
||||
|
||||
{{if .ControlPlaneEndpoint -}}
|
||||
{{if .UploadCerts -}}
|
||||
You can now join any number of the control-plane node running the following command on each as root:
|
||||
|
||||
{{.joinControlPlaneCommand}}
|
||||
|
||||
Please note that the certificate-key gives access to cluster sensitive data, keep it secret!
|
||||
As a safeguard, uploaded-certs will be deleted in two hours; If necessary, you can use
|
||||
"kubeadm init phase upload-certs --upload-certs" to reload certs afterward.
|
||||
|
||||
{{else -}}
|
||||
You can now join any number of control-plane nodes by copying certificate authorities
|
||||
and service account keys on each node and then running the following as root:
|
||||
|
||||
{{.joinControlPlaneCommand}}
|
||||
|
||||
{{end}}{{end}}Then you can join any number of worker nodes by running the following on each as root:
|
||||
|
||||
{{.joinWorkerCommand}}
|
||||
`)))
|
||||
)
|
||||
|
||||
// initOptions defines all the init options exposed via flags by kubeadm init.
|
||||
// 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.
|
||||
@ -151,11 +109,7 @@ func newCmdInit(out io.Writer, initOptions *initOptions) *cobra.Command {
|
||||
data := c.(*initData)
|
||||
fmt.Printf("[init] Using Kubernetes version: %s\n", data.cfg.KubernetesVersion)
|
||||
|
||||
if err := initRunner.Run(args); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return showJoinCommand(data, out)
|
||||
return initRunner.Run(args)
|
||||
},
|
||||
Args: cobra.NoArgs,
|
||||
}
|
||||
@ -191,6 +145,7 @@ func newCmdInit(out io.Writer, initOptions *initOptions) *cobra.Command {
|
||||
initRunner.AppendPhase(phases.NewBootstrapTokenPhase())
|
||||
initRunner.AppendPhase(phases.NewKubeletFinalizePhase())
|
||||
initRunner.AppendPhase(phases.NewAddonPhase())
|
||||
initRunner.AppendPhase(phases.NewShowJoinCommandPhase())
|
||||
|
||||
// sets the data builder function, that will be used by the runner
|
||||
// both when running the entire workflow or single phases
|
||||
@ -565,39 +520,3 @@ func (d *initData) PatchesDir() string {
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func printJoinCommand(out io.Writer, adminKubeConfigPath, token string, i *initData) error {
|
||||
joinControlPlaneCommand, err := cmdutil.GetJoinControlPlaneCommand(adminKubeConfigPath, token, i.CertificateKey(), i.skipTokenPrint, i.skipCertificateKeyPrint)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
joinWorkerCommand, err := cmdutil.GetJoinWorkerCommand(adminKubeConfigPath, token, i.skipTokenPrint)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ctx := map[string]interface{}{
|
||||
"KubeConfigPath": adminKubeConfigPath,
|
||||
"ControlPlaneEndpoint": i.Cfg().ControlPlaneEndpoint,
|
||||
"UploadCerts": i.uploadCerts,
|
||||
"joinControlPlaneCommand": joinControlPlaneCommand,
|
||||
"joinWorkerCommand": joinWorkerCommand,
|
||||
}
|
||||
|
||||
return initDoneTempl.Execute(out, ctx)
|
||||
}
|
||||
|
||||
// showJoinCommand prints the join command after all the phases in init have finished
|
||||
func showJoinCommand(i *initData, out io.Writer) error {
|
||||
adminKubeConfigPath := i.KubeConfigPath()
|
||||
|
||||
// Prints the join command, multiple times in case the user has multiple tokens
|
||||
for _, token := range i.Tokens() {
|
||||
if err := printJoinCommand(out, adminKubeConfigPath, token, i); err != nil {
|
||||
return errors.Wrap(err, "failed to print join command")
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
119
cmd/kubeadm/app/cmd/phases/init/showjoincommand.go
Normal file
119
cmd/kubeadm/app/cmd/phases/init/showjoincommand.go
Normal file
@ -0,0 +1,119 @@
|
||||
/*
|
||||
Copyright 2022 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 phases
|
||||
|
||||
import (
|
||||
"io"
|
||||
"text/template"
|
||||
|
||||
"github.com/lithammer/dedent"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow"
|
||||
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
|
||||
)
|
||||
|
||||
var (
|
||||
initDoneTempl = template.Must(template.New("init").Parse(dedent.Dedent(`
|
||||
Your Kubernetes control-plane has initialized successfully!
|
||||
|
||||
To start using your cluster, you need to run the following as a regular user:
|
||||
|
||||
mkdir -p $HOME/.kube
|
||||
sudo cp -i {{.KubeConfigPath}} $HOME/.kube/config
|
||||
sudo chown $(id -u):$(id -g) $HOME/.kube/config
|
||||
|
||||
Alternatively, if you are the root user, you can run:
|
||||
|
||||
export KUBECONFIG=/etc/kubernetes/admin.conf
|
||||
|
||||
You should now deploy a pod network to the cluster.
|
||||
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
|
||||
https://kubernetes.io/docs/concepts/cluster-administration/addons/
|
||||
|
||||
{{if .ControlPlaneEndpoint -}}
|
||||
{{if .UploadCerts -}}
|
||||
You can now join any number of the control-plane node running the following command on each as root:
|
||||
|
||||
{{.joinControlPlaneCommand}}
|
||||
|
||||
Please note that the certificate-key gives access to cluster sensitive data, keep it secret!
|
||||
As a safeguard, uploaded-certs will be deleted in two hours; If necessary, you can use
|
||||
"kubeadm init phase upload-certs --upload-certs" to reload certs afterward.
|
||||
|
||||
{{else -}}
|
||||
You can now join any number of control-plane nodes by copying certificate authorities
|
||||
and service account keys on each node and then running the following as root:
|
||||
|
||||
{{.joinControlPlaneCommand}}
|
||||
|
||||
{{end}}{{end}}Then you can join any number of worker nodes by running the following on each as root:
|
||||
|
||||
{{.joinWorkerCommand}}
|
||||
`)))
|
||||
)
|
||||
|
||||
// NewShowJoinCommandPhase creates a kubeadm workflow phase that implements showing the join command.
|
||||
func NewShowJoinCommandPhase() workflow.Phase {
|
||||
return workflow.Phase{
|
||||
Name: "show-join-command",
|
||||
Short: "Show the join command for control-plane and worker node",
|
||||
Run: showJoinCommand,
|
||||
Dependencies: []string{"bootstrap-token", "upload-certs"},
|
||||
}
|
||||
}
|
||||
|
||||
// showJoinCommand prints the join command after all the phases in init have finished
|
||||
func showJoinCommand(c workflow.RunData) error {
|
||||
data, ok := c.(InitData)
|
||||
if !ok {
|
||||
return errors.New("show-join-command phase invoked with an invalid data struct")
|
||||
}
|
||||
|
||||
adminKubeConfigPath := data.KubeConfigPath()
|
||||
|
||||
// Prints the join command, multiple times in case the user has multiple tokens
|
||||
for _, token := range data.Tokens() {
|
||||
if err := printJoinCommand(data.OutputWriter(), adminKubeConfigPath, token, data); err != nil {
|
||||
return errors.Wrap(err, "failed to print join command")
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func printJoinCommand(out io.Writer, adminKubeConfigPath, token string, i InitData) error {
|
||||
joinControlPlaneCommand, err := cmdutil.GetJoinControlPlaneCommand(adminKubeConfigPath, token, i.CertificateKey(), i.SkipTokenPrint(), i.SkipCertificateKeyPrint())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
joinWorkerCommand, err := cmdutil.GetJoinWorkerCommand(adminKubeConfigPath, token, i.SkipTokenPrint())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ctx := map[string]interface{}{
|
||||
"KubeConfigPath": adminKubeConfigPath,
|
||||
"ControlPlaneEndpoint": i.Cfg().ControlPlaneEndpoint,
|
||||
"UploadCerts": i.UploadCerts(),
|
||||
"joinControlPlaneCommand": joinControlPlaneCommand,
|
||||
"joinWorkerCommand": joinWorkerCommand,
|
||||
}
|
||||
|
||||
return initDoneTempl.Execute(out, ctx)
|
||||
}
|
@ -78,6 +78,9 @@ type Phase struct {
|
||||
// ArgsValidator defines the positional arg function to be used for validating args for this phase
|
||||
// If not set a phase will adopt the args of the top level command.
|
||||
ArgsValidator cobra.PositionalArgs
|
||||
|
||||
// Dependencies is a list of phases that the specific phase depends on.
|
||||
Dependencies []string
|
||||
}
|
||||
|
||||
// AppendPhase adds the given phase to the nested, ordered sequence of phases.
|
||||
|
@ -198,6 +198,29 @@ func (e *Runner) Run(args []string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// precheck phase dependencies before actual execution
|
||||
missedDeps := make(map[string][]string)
|
||||
visited := make(map[string]struct{})
|
||||
for _, p := range e.phaseRunners {
|
||||
if run, ok := phaseRunFlags[p.generatedName]; !run || !ok {
|
||||
continue
|
||||
}
|
||||
for _, dep := range p.Phase.Dependencies {
|
||||
if _, ok := visited[dep]; !ok {
|
||||
missedDeps[p.Phase.Name] = append(missedDeps[p.Phase.Name], dep)
|
||||
}
|
||||
}
|
||||
visited[p.Phase.Name] = struct{}{}
|
||||
}
|
||||
if len(missedDeps) > 0 {
|
||||
var msg strings.Builder
|
||||
msg.WriteString("unresolved dependencies:")
|
||||
for phase, missedPhases := range missedDeps {
|
||||
msg.WriteString(fmt.Sprintf("\n\tmissing %v phase(s) needed by %q phase", missedPhases, phase))
|
||||
}
|
||||
return errors.New(msg.String())
|
||||
}
|
||||
|
||||
// builds the runner data
|
||||
var data RunData
|
||||
if data, err = e.InitData(args); err != nil {
|
||||
|
Loading…
Reference in New Issue
Block a user