Implement kubeadm reset

pull/6/head
Lucas Käldström 2016-10-15 11:58:06 +03:00
parent e0fc43b42d
commit ecdaa7195a
4 changed files with 141 additions and 20 deletions

View File

@ -80,6 +80,7 @@ func NewKubeadmCommand(f cmdutil.Factory, in io.Reader, out, err io.Writer) *cob
cmds.AddCommand(NewCmdInit(out)) cmds.AddCommand(NewCmdInit(out))
cmds.AddCommand(NewCmdJoin(out)) cmds.AddCommand(NewCmdJoin(out))
cmds.AddCommand(NewCmdReset(out))
cmds.AddCommand(NewCmdVersion(out)) cmds.AddCommand(NewCmdVersion(out))
return cmds return cmds

View File

@ -0,0 +1,96 @@
/*
Copyright 2014 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 cmd
import (
"fmt"
"io"
"os"
"os/exec"
"github.com/spf13/cobra"
"k8s.io/kubernetes/cmd/kubeadm/app/preflight"
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
"k8s.io/kubernetes/pkg/util/initsystem"
)
func NewCmdReset(out io.Writer) *cobra.Command {
var skipPreFlight bool
cmd := &cobra.Command{
Use: "reset",
Short: "Revert the actions kubeadm init or join made to the machine",
Run: func(cmd *cobra.Command, args []string) {
err := RunReset(out, cmd, skipPreFlight)
cmdutil.CheckErr(err)
},
}
cmd.PersistentFlags().BoolVar(
&skipPreFlight, "skip-preflight-checks", false,
"skip preflight checks normally run before modifying the system",
)
return cmd
}
func RunReset(out io.Writer, cmd *cobra.Command, skipPreFlight bool) error {
if !skipPreFlight {
fmt.Println("Running pre-flight checks")
err := preflight.RunResetCheck()
if err != nil {
return &preflight.PreFlightError{Msg: err.Error()}
}
} else {
fmt.Println("Skipping pre-flight checks")
}
serviceToStop := "kubelet"
initSystem, err := initsystem.GetInitSystem()
if err != nil {
fmt.Printf("%v", err)
} else {
fmt.Printf("Stopping the %s service...\n", serviceToStop)
initSystem.ServiceStop(serviceToStop)
}
fmt.Printf("Unmounting directories in /var/lib/kubelet...\n")
// Don't check for errors here, since umount will return a non-zero exit code if there is no directories to umount
exec.Command("sh", "-c", "cat /proc/mounts | awk '{print $2}' | grep '/var/lib/kubelet' | xargs umount").Run()
dirsToRemove := []string{"/var/lib/kubelet", "/var/lib/etcd", "/etc/kubernetes"}
fmt.Printf("Deleting the stateful directories: %v\n", dirsToRemove)
for _, dir := range dirsToRemove {
err := os.RemoveAll(dir)
if err != nil {
fmt.Printf("failed to remove directory: [%v]\n", err)
}
}
dockerCheck := preflight.ServiceCheck{Service: "docker"}
if warnings, errors := dockerCheck.Check(); len(warnings) == 0 && len(errors) == 0 {
fmt.Println("Stopping all running docker containers...")
if err := exec.Command("sh", "-c", "docker ps | grep 'k8s_' | awk '{print $1}' | xargs docker rm --force --volumes").Run(); err != nil {
fmt.Println("failed to stop the running containers")
}
} else {
fmt.Println("docker doesn't seem to be running, skipping the removal of kubernetes containers")
}
return nil
}

View File

@ -45,32 +45,32 @@ type PreFlightCheck interface {
// detect a supported init system however, all checks are skipped and a warning is // detect a supported init system however, all checks are skipped and a warning is
// returned. // returned.
type ServiceCheck struct { type ServiceCheck struct {
service string Service string
} }
func (sc ServiceCheck) Check() (warnings, errors []error) { func (sc ServiceCheck) Check() (warnings, errors []error) {
initSystem := initsystem.GetInitSystem() initSystem, err := initsystem.GetInitSystem()
if initSystem == nil { if err != nil {
return []error{fmt.Errorf("no supported init system detected, skipping service checks for %s", sc.service)}, nil return []error{err}, nil
} }
warnings = []error{} warnings = []error{}
if !initSystem.ServiceExists(sc.service) { if !initSystem.ServiceExists(sc.Service) {
warnings = append(warnings, fmt.Errorf("%s service does not exist", sc.service)) warnings = append(warnings, fmt.Errorf("%s service does not exist", sc.Service))
return warnings, nil return warnings, nil
} }
if !initSystem.ServiceIsEnabled(sc.service) { if !initSystem.ServiceIsEnabled(sc.Service) {
warnings = append(warnings, warnings = append(warnings,
fmt.Errorf("%s service is not enabled, please run 'systemctl enable %s.service'", fmt.Errorf("%s service is not enabled, please run 'systemctl enable %s.service'",
sc.service, sc.service)) sc.Service, sc.Service))
} }
if !initSystem.ServiceIsActive(sc.service) { if !initSystem.ServiceIsActive(sc.Service) {
errors = append(errors, errors = append(errors,
fmt.Errorf("%s service is not active, please run 'systemctl start %s.service'", fmt.Errorf("%s service is not active, please run 'systemctl start %s.service'",
sc.service, sc.service)) sc.Service, sc.Service))
} }
return warnings, errors return warnings, errors
@ -160,8 +160,8 @@ func RunInitMasterChecks() error {
// TODO: Some of these ports should come from kubeadm config eventually: // TODO: Some of these ports should come from kubeadm config eventually:
checks := []PreFlightCheck{ checks := []PreFlightCheck{
IsRootCheck{root: true}, IsRootCheck{root: true},
ServiceCheck{service: "kubelet"}, ServiceCheck{Service: "kubelet"},
ServiceCheck{service: "docker"}, ServiceCheck{Service: "docker"},
PortOpenCheck{port: 443}, PortOpenCheck{port: 443},
PortOpenCheck{port: 2379}, PortOpenCheck{port: 2379},
PortOpenCheck{port: 8080}, PortOpenCheck{port: 8080},
@ -189,12 +189,9 @@ func RunJoinNodeChecks() error {
// TODO: Some of these ports should come from kubeadm config eventually: // TODO: Some of these ports should come from kubeadm config eventually:
checks := []PreFlightCheck{ checks := []PreFlightCheck{
IsRootCheck{root: true}, IsRootCheck{root: true},
ServiceCheck{service: "docker"}, ServiceCheck{Service: "docker"},
ServiceCheck{service: "kubelet"}, ServiceCheck{Service: "kubelet"},
PortOpenCheck{port: 8080},
PortOpenCheck{port: 10250}, PortOpenCheck{port: 10250},
PortOpenCheck{port: 10251},
PortOpenCheck{port: 10252},
DirAvailableCheck{path: "/etc/kubernetes"}, DirAvailableCheck{path: "/etc/kubernetes"},
DirAvailableCheck{path: "/var/lib/kubelet"}, DirAvailableCheck{path: "/var/lib/kubelet"},
InPathCheck{executable: "ebtables", mandatory: true}, InPathCheck{executable: "ebtables", mandatory: true},
@ -211,6 +208,14 @@ func RunJoinNodeChecks() error {
return runChecks(checks) return runChecks(checks)
} }
func RunResetCheck() error {
checks := []PreFlightCheck{
IsRootCheck{root: true},
}
return runChecks(checks)
}
// runChecks runs each check, displays it's warnings/errors, and once all // runChecks runs each check, displays it's warnings/errors, and once all
// are processed will exit if any errors occurred. // are processed will exit if any errors occurred.
func runChecks(checks []PreFlightCheck) error { func runChecks(checks []PreFlightCheck) error {

View File

@ -17,11 +17,18 @@ limitations under the License.
package initsystem package initsystem
import ( import (
"fmt"
"os/exec" "os/exec"
"strings" "strings"
) )
type InitSystem interface { type InitSystem interface {
// ServiceStart tries to start a specific service
ServiceStart(service string) error
// ServiceStop tries to stop a specific service
ServiceStop(service string) error
// ServiceExists ensures the service is defined for this init system. // ServiceExists ensures the service is defined for this init system.
ServiceExists(service string) bool ServiceExists(service string) bool
@ -34,6 +41,18 @@ type InitSystem interface {
type SystemdInitSystem struct{} type SystemdInitSystem struct{}
func (sysd SystemdInitSystem) ServiceStart(service string) error {
args := []string{"start", service}
_, err := exec.Command("systemctl", args...).Output()
return err
}
func (sysd SystemdInitSystem) ServiceStop(service string) error {
args := []string{"stop", service}
_, err := exec.Command("systemctl", args...).Output()
return err
}
func (sysd SystemdInitSystem) ServiceExists(service string) bool { func (sysd SystemdInitSystem) ServiceExists(service string) bool {
args := []string{"status", service} args := []string{"status", service}
outBytes, _ := exec.Command("systemctl", args...).Output() outBytes, _ := exec.Command("systemctl", args...).Output()
@ -70,11 +89,11 @@ func (sysd SystemdInitSystem) ServiceIsActive(service string) bool {
// getInitSystem returns an InitSystem for the current system, or nil // getInitSystem returns an InitSystem for the current system, or nil
// if we cannot detect a supported init system for pre-flight checks. // if we cannot detect a supported init system for pre-flight checks.
// This indicates we will skip init system checks, not an error. // This indicates we will skip init system checks, not an error.
func GetInitSystem() InitSystem { func GetInitSystem() (InitSystem, error) {
// Assume existence of systemctl in path implies this is a systemd system: // Assume existence of systemctl in path implies this is a systemd system:
_, err := exec.LookPath("systemctl") _, err := exec.LookPath("systemctl")
if err == nil { if err == nil {
return &SystemdInitSystem{} return &SystemdInitSystem{}, nil
} }
return nil return nil, fmt.Errorf("no supported init system detected, skipping checking for services")
} }