mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-24 20:24:09 +00:00
Merge pull request #59115 from alexbrand/kubeadm-confirm-reset-2
Automatic merge from submit-queue (batch tested with PRs 59965, 59115, 63076, 63059). If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>. kubeadm: prompt for confirmation when resetting a master Signed-off-by: Alexander Brand <alexbrand09@gmail.com> **What this PR does / why we need it**: This PR implements a confirmation prompt when running `kubeadm reset` on a master node. This is to prevent users from mistakenly resetting a master node. **Which issue(s) this PR fixes**: Fixes https://github.com/kubernetes/kubeadm/issues/673 **Special notes for your reviewer**: I am somewhat torn on the approach on how to detect that kubeadm is running on a master node. I went with checking for the apiserver manfiest file on the local filesystem, as it seems like a simpler approach when compared to getting a k8s client, getting a list of nodes, finding the current node, and checking if it has the master taint. I am happy to rework if the latter is more desirable. Sample runs: ``` # ./kubeadm reset [Warning] Are you sure you want to reset this master node? Type the word "confirm" to continue: no Aborted reset operation on master node # ./kubeadm reset [Warning] Are you sure you want to reset this master node? Type the word "confirm" to continue: confirm [preflight] Running pre-flight checks. [reset] Stopping the kubelet service. [reset] WARNING: The kubelet service could not be stopped by kubeadm: [exit status 1] [reset] WARNING: Please ensure kubelet is stopped manually. [reset] Unmounting mounted directories in "/var/lib/kubelet" ........ # ./kubeadm reset [Warning] Are you sure you want to reset this master node? Type the word "confirm" to continue: Aborted reset operation on master node # ./kubeadm reset --confirm [preflight] Running pre-flight checks. [reset] Stopping the kubelet service. [reset] WARNING: The kubelet service could not be stopped by kubeadm: [exit status 1] [reset] WARNING: Please ensure kubelet is stopped manually. [reset] Unmounting mounted directories in "/var/lib/kubelet" ........ ``` **Release note**: ```release-note kubeadm: prompt the user for confirmation when resetting a master node ```
This commit is contained in:
commit
163b848abe
@ -32,7 +32,7 @@ import (
|
||||
)
|
||||
|
||||
// NewKubeadmCommand return cobra.Command to run kubeadm command
|
||||
func NewKubeadmCommand(_ io.Reader, out, err io.Writer) *cobra.Command {
|
||||
func NewKubeadmCommand(in io.Reader, out, err io.Writer) *cobra.Command {
|
||||
cmds := &cobra.Command{
|
||||
Use: "kubeadm",
|
||||
Short: "kubeadm: easily bootstrap a secure Kubernetes cluster",
|
||||
@ -77,7 +77,7 @@ func NewKubeadmCommand(_ io.Reader, out, err io.Writer) *cobra.Command {
|
||||
cmds.AddCommand(NewCmdConfig(out))
|
||||
cmds.AddCommand(NewCmdInit(out))
|
||||
cmds.AddCommand(NewCmdJoin(out))
|
||||
cmds.AddCommand(NewCmdReset(out))
|
||||
cmds.AddCommand(NewCmdReset(in, out))
|
||||
cmds.AddCommand(NewCmdVersion(out))
|
||||
cmds.AddCommand(NewCmdToken(out, err))
|
||||
cmds.AddCommand(upgrade.NewCmdUpgrade(out))
|
||||
|
@ -17,6 +17,8 @@ limitations under the License.
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
@ -44,11 +46,12 @@ var (
|
||||
)
|
||||
|
||||
// NewCmdReset returns the "kubeadm reset" command
|
||||
func NewCmdReset(out io.Writer) *cobra.Command {
|
||||
func NewCmdReset(in io.Reader, out io.Writer) *cobra.Command {
|
||||
var skipPreFlight bool
|
||||
var certsDir string
|
||||
var criSocketPath string
|
||||
var ignorePreflightErrors []string
|
||||
var forceReset bool
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "reset",
|
||||
@ -57,7 +60,7 @@ func NewCmdReset(out io.Writer) *cobra.Command {
|
||||
ignorePreflightErrorsSet, err := validation.ValidateIgnorePreflightErrors(ignorePreflightErrors, skipPreFlight)
|
||||
kubeadmutil.CheckErr(err)
|
||||
|
||||
r, err := NewReset(ignorePreflightErrorsSet, certsDir, criSocketPath)
|
||||
r, err := NewReset(in, ignorePreflightErrorsSet, forceReset, certsDir, criSocketPath)
|
||||
kubeadmutil.CheckErr(err)
|
||||
kubeadmutil.CheckErr(r.Run(out))
|
||||
},
|
||||
@ -83,6 +86,11 @@ func NewCmdReset(out io.Writer) *cobra.Command {
|
||||
"The path to the CRI socket to use with crictl when cleaning up containers.",
|
||||
)
|
||||
|
||||
cmd.PersistentFlags().BoolVar(
|
||||
&forceReset, "force", false,
|
||||
"Reset the node without prompting for confirmation.",
|
||||
)
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
@ -93,9 +101,21 @@ type Reset struct {
|
||||
}
|
||||
|
||||
// NewReset instantiate Reset struct
|
||||
func NewReset(ignorePreflightErrors sets.String, certsDir, criSocketPath string) (*Reset, error) {
|
||||
glog.Infoln("[preflight] running pre-flight checks")
|
||||
func NewReset(in io.Reader, ignorePreflightErrors sets.String, forceReset bool, certsDir, criSocketPath string) (*Reset, error) {
|
||||
if !forceReset {
|
||||
fmt.Println("[reset] WARNING: changes made to this host by 'kubeadm init' or 'kubeadm join' will be reverted.")
|
||||
fmt.Print("[reset] are you sure you want to proceed? [y/N]: ")
|
||||
s := bufio.NewScanner(in)
|
||||
s.Scan()
|
||||
if err := s.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if strings.ToLower(s.Text()) != "y" {
|
||||
return nil, errors.New("Aborted reset operation")
|
||||
}
|
||||
}
|
||||
|
||||
glog.Infoln("[preflight] running pre-flight checks")
|
||||
if err := preflight.RunRootCheckOnly(ignorePreflightErrors); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -56,28 +56,31 @@ func assertDirEmpty(t *testing.T, path string) {
|
||||
}
|
||||
|
||||
func TestNewReset(t *testing.T) {
|
||||
var in io.Reader
|
||||
certsDir := kubeadmapiext.DefaultCertificatesDir
|
||||
criSocketPath := "/var/run/dockershim.sock"
|
||||
skipPreFlight := false
|
||||
forceReset := true
|
||||
|
||||
ignorePreflightErrors := []string{"all"}
|
||||
ignorePreflightErrorsSet, _ := validation.ValidateIgnorePreflightErrors(ignorePreflightErrors, skipPreFlight)
|
||||
NewReset(ignorePreflightErrorsSet, certsDir, criSocketPath)
|
||||
NewReset(in, ignorePreflightErrorsSet, forceReset, certsDir, criSocketPath)
|
||||
|
||||
ignorePreflightErrors = []string{}
|
||||
ignorePreflightErrorsSet, _ = validation.ValidateIgnorePreflightErrors(ignorePreflightErrors, skipPreFlight)
|
||||
NewReset(ignorePreflightErrorsSet, certsDir, criSocketPath)
|
||||
NewReset(in, ignorePreflightErrorsSet, forceReset, certsDir, criSocketPath)
|
||||
}
|
||||
|
||||
func TestNewCmdReset(t *testing.T) {
|
||||
var out io.Writer
|
||||
cmd := NewCmdReset(out)
|
||||
var in io.Reader
|
||||
cmd := NewCmdReset(in, out)
|
||||
|
||||
tmpDir, err := ioutil.TempDir("", "kubeadm-reset-test")
|
||||
if err != nil {
|
||||
t.Errorf("Unable to create temporary directory: %v", err)
|
||||
}
|
||||
args := []string{"--ignore-preflight-errors=all", "--cert-dir=" + tmpDir}
|
||||
args := []string{"--ignore-preflight-errors=all", "--cert-dir=" + tmpDir, "--force"}
|
||||
cmd.SetArgs(args)
|
||||
if err := cmd.Execute(); err != nil {
|
||||
t.Errorf("Cannot execute reset command: %v", err)
|
||||
|
Loading…
Reference in New Issue
Block a user