fix: delete node nil pointer panic

Signed-off-by: 24sama <jacksama@foxmail.com>
This commit is contained in:
24sama 2022-06-07 11:28:28 +08:00
parent f7036b0b7a
commit d25eab880c
10 changed files with 90 additions and 195 deletions

View File

@ -1,41 +0,0 @@
/*
Copyright 2021 The KubeSphere 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 config
import (
"github.com/kubesphere/kubekey/pkg/common"
"github.com/kubesphere/kubekey/pkg/core/task"
)
type ModifyConfigModule struct {
common.KubeModule
}
func (m *ModifyConfigModule) Init() {
m.Name = "ModifyConfigModule"
m.Desc = "Modify the KubeKey config file"
modify := &task.LocalTask{
Name: "ModifyConfig",
Desc: "Modify the KubeKey config file",
Action: new(ModifyConfig),
}
m.Tasks = []task.Interface{
modify,
}
}

View File

@ -1,116 +0,0 @@
/*
Copyright 2021 The KubeSphere 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 config
import (
"fmt"
"github.com/kubesphere/kubekey/pkg/common"
"github.com/kubesphere/kubekey/pkg/core/connector"
"github.com/pkg/errors"
"os/exec"
"path/filepath"
"strconv"
"unicode"
)
type ModifyConfig struct {
common.KubeAction
}
func (m *ModifyConfig) Execute(runtime connector.Runtime) error {
fp, _ := filepath.Abs(m.KubeConf.Arg.FilePath)
cmd0 := fmt.Sprintf("cat %s | grep %s | wc -l", fp, m.KubeConf.Arg.NodeName)
nodeNameNum, err0 := exec.Command("/bin/sh", "-c", cmd0).CombinedOutput()
if err0 != nil {
return errors.Wrap(err0, "Failed to get node num")
}
host := &connector.BaseHost{Name: m.KubeConf.Arg.NodeName}
if string(nodeNameNum) == "2\n" {
cmd := fmt.Sprintf("sed -i /%s/d %s", m.KubeConf.Arg.NodeName, fp)
_ = exec.Command("/bin/sh", "-c", cmd).Run()
runtime.DeleteHost(host)
} else if string(nodeNameNum) == "1\n" {
cmd := fmt.Sprintf("sed -i /%s/d %s", m.KubeConf.Arg.NodeName, fp)
_ = exec.Command("/bin/sh", "-c", cmd).Run()
runtime.DeleteHost(host)
var newNodeName []string
for i := 0; i < len(runtime.GetHostsByRole(common.Worker)); i++ {
name := runtime.GetHostsByRole(common.Worker)[i].GetName()
if m.KubeConf.Arg.NodeName == name {
continue
} else {
newNodeName = append(newNodeName, name)
}
}
var connNodeName []string
for j := 0; j < len(newNodeName); j++ {
t := j
nodename1 := newNodeName[t]
for t+1 < len(newNodeName) && IsAdjoin(newNodeName[t], newNodeName[t+1]) {
t++
}
if t == j {
connNodeName = append(connNodeName, nodename1)
} else {
connNodeName = append(connNodeName, Merge(nodename1, newNodeName[t]))
j = t
}
}
cmd1 := fmt.Sprintf("sed -i -n '1,/worker/p;/controlPlaneEndpoint/,$p' %s", fp)
_ = exec.Command("/bin/sh", "-c", cmd1).Run()
for k := 0; k < len(connNodeName); k++ {
workPar := connNodeName[k]
workPar1 := fmt.Sprintf("%s", workPar)
cmd2 := fmt.Sprintf("sed -i '/worker/a\\ \\ \\ \\ \\- %s' %s", workPar1, fp)
_ = exec.Command("/bin/sh", "-c", cmd2).Run()
}
} else {
return errors.New("Please check the node name in the config-sample.yaml or only support to delete worker")
}
return nil
}
func Merge(name1, name2 string) (endName string) {
par1, par2 := SplitNum(name1)
_, par4 := SplitNum(name2)
endName = fmt.Sprintf("%s[%s:%s]", par1, strconv.Itoa(par2), strconv.Itoa(par4))
return endName
}
func IsAdjoin(name1, name2 string) bool {
IsAd := false
par1, par2 := SplitNum(name1)
par3, par4 := SplitNum(name2)
if par1 == par3 && par4 == par2+1 {
IsAd = true
}
return IsAd
}
func SplitNum(nodeName string) (name string, num int) {
nodeLen := len(nodeName)
i := nodeLen - 1
for ; nodeLen > 0; i-- {
if !unicode.IsDigit(rune(nodeName[i])) {
num, _ := strconv.Atoi(nodeName[i+1:])
name := nodeName[:i+1]
return name, num
}
}
return "", 0
}

View File

@ -17,12 +17,14 @@
package os
import (
"path/filepath"
"github.com/kubesphere/kubekey/pkg/bootstrap/os/templates"
"github.com/kubesphere/kubekey/pkg/common"
"github.com/kubesphere/kubekey/pkg/core/action"
"github.com/kubesphere/kubekey/pkg/core/prepare"
"github.com/kubesphere/kubekey/pkg/core/task"
"github.com/kubesphere/kubekey/pkg/core/util"
"path/filepath"
)
type ConfigureOSModule struct {
@ -91,15 +93,19 @@ func (c *ClearOSEnvironmentModule) Init() {
Name: "ResetNetworkConfig",
Desc: "Reset os network config",
Hosts: c.Runtime.GetHostsByRole(common.K8s),
Prepare: new(DeleteNode),
Action: new(ResetNetworkConfig),
Parallel: true,
}
uninstallETCD := &task.RemoteTask{
Name: "UninstallETCD",
Desc: "Uninstall etcd",
Hosts: c.Runtime.GetHostsByRole(common.ETCD),
Prepare: new(EtcdTypeIsKubeKey),
Name: "UninstallETCD",
Desc: "Uninstall etcd",
Hosts: c.Runtime.GetHostsByRole(common.ETCD),
Prepare: &prepare.PrepareCollection{
new(EtcdTypeIsKubeKey),
new(DeleteNode),
},
Action: new(UninstallETCD),
Parallel: true,
}
@ -108,6 +114,7 @@ func (c *ClearOSEnvironmentModule) Init() {
Name: "RemoveFiles",
Desc: "Remove cluster files",
Hosts: c.Runtime.GetHostsByRole(common.K8s),
Prepare: new(DeleteNode),
Action: new(RemoveFiles),
Parallel: true,
}
@ -116,6 +123,7 @@ func (c *ClearOSEnvironmentModule) Init() {
Name: "DaemonReload",
Desc: "Systemd daemon reload",
Hosts: c.Runtime.GetHostsByRole(common.K8s),
Prepare: new(DeleteNode),
Action: new(DaemonReload),
Parallel: true,
}

View File

@ -46,3 +46,21 @@ func (e *EtcdTypeIsKubeKey) PreCheck(_ connector.Runtime) (bool, error) {
return false, nil
}
type DeleteNode struct {
common.KubePrepare
}
func (d *DeleteNode) PreCheck(runtime connector.Runtime) (bool, error) {
nodeName, ok := d.PipelineCache.Get("dstNode")
if !ok {
return true, nil
}
host := runtime.RemoteHost()
if host.GetName() == nodeName {
return true, nil
}
return false, nil
}

View File

@ -22,11 +22,12 @@ import (
"strings"
osrelease "github.com/dominodatalab/os-release"
"github.com/pkg/errors"
"github.com/kubesphere/kubekey/pkg/bootstrap/os/repository"
"github.com/kubesphere/kubekey/pkg/common"
"github.com/kubesphere/kubekey/pkg/core/connector"
"github.com/kubesphere/kubekey/pkg/utils"
"github.com/pkg/errors"
)
type NodeConfigureOS struct {
@ -214,6 +215,9 @@ func (d *DaemonReload) Execute(runtime connector.Runtime) error {
if _, err := runtime.GetRunner().SudoCmd("systemctl daemon-reload && exit 0", false); err != nil {
return errors.Wrap(errors.WithStack(err), "systemctl daemon-reload failed")
}
// try to restart the cotainerd after /etc/cni has been removed
_, _ = runtime.GetRunner().SudoCmd("systemctl restart containerd", false)
return nil
}

View File

@ -21,6 +21,7 @@ import (
versionutil "k8s.io/apimachinery/pkg/util/version"
"github.com/kubesphere/kubekey/pkg/bootstrap/os"
"github.com/kubesphere/kubekey/pkg/certs/templates"
"github.com/kubesphere/kubekey/pkg/common"
"github.com/kubesphere/kubekey/pkg/core/action"
@ -200,10 +201,13 @@ func (u *UninstallAutoRenewCertsModule) Init() {
u.Desc = "UnInstall auto renew control-plane certs"
uninstall := &task.RemoteTask{
Name: "UnInstallAutoRenewCerts",
Desc: "UnInstall auto renew control-plane certs",
Hosts: u.Runtime.GetHostsByRole(common.Master),
Prepare: new(AutoRenewCertsEnabled),
Name: "UnInstallAutoRenewCerts",
Desc: "UnInstall auto renew control-plane certs",
Hosts: u.Runtime.GetHostsByRole(common.Master),
Prepare: &prepare.PrepareCollection{
new(AutoRenewCertsEnabled),
new(os.DeleteNode),
},
Action: new(UninstallAutoRenewCerts),
Parallel: true,
}

View File

@ -18,12 +18,14 @@ package connector
import (
"fmt"
"os"
"path/filepath"
"github.com/pkg/errors"
"github.com/kubesphere/kubekey/pkg/core/common"
"github.com/kubesphere/kubekey/pkg/core/logger"
"github.com/kubesphere/kubekey/pkg/core/util"
"github.com/pkg/errors"
"os"
"path/filepath"
)
type BaseRuntime struct {
@ -122,7 +124,14 @@ func (b *BaseRuntime) GetIgnoreErr() bool {
}
func (b *BaseRuntime) GetAllHosts() []Host {
return b.allHosts
hosts := make([]Host, 0, 0)
for i := range b.allHosts {
if b.allHosts[i] == nil || b.HostIsDeprecated(b.allHosts[i]) {
continue
}
hosts = append(hosts, b.allHosts[i])
}
return hosts
}
func (b *BaseRuntime) SetAllHosts(hosts []Host) {

View File

@ -18,6 +18,10 @@ package kubernetes
import (
"fmt"
"path/filepath"
"github.com/pkg/errors"
"github.com/kubesphere/kubekey/pkg/binaries"
"github.com/kubesphere/kubekey/pkg/common"
"github.com/kubesphere/kubekey/pkg/core/action"
@ -25,8 +29,6 @@ import (
"github.com/kubesphere/kubekey/pkg/core/task"
"github.com/kubesphere/kubekey/pkg/images"
"github.com/kubesphere/kubekey/pkg/kubernetes/templates"
"github.com/pkg/errors"
"path/filepath"
)
type StatusModule struct {
@ -358,11 +360,11 @@ func (c *CompareConfigAndClusterInfoModule) Init() {
c.Desc = "Compare config and cluster nodes info"
check := &task.RemoteTask{
Name: "FindDifferences",
Desc: "Find the differences between config and cluster node info",
Name: "FindNode",
Desc: "Find information about nodes that are expected to be deleted",
Hosts: c.Runtime.GetHostsByRole(common.Master),
Prepare: new(common.OnlyFirstMaster),
Action: new(FindDifferences),
Action: new(FindNode),
}
c.Tasks = []task.Interface{

View File

@ -20,13 +20,22 @@ import (
"context"
"encoding/base64"
"fmt"
"github.com/kubesphere/kubekey/pkg/etcd"
"os"
"path/filepath"
"sort"
"strings"
"time"
"github.com/kubesphere/kubekey/pkg/etcd"
"github.com/pkg/errors"
corev1 "k8s.io/api/core/v1"
kubeerrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
versionutil "k8s.io/apimachinery/pkg/util/version"
kube "k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/clientcmd"
kubekeyv1alpha2 "github.com/kubesphere/kubekey/apis/kubekey/v1alpha2"
"github.com/kubesphere/kubekey/pkg/common"
"github.com/kubesphere/kubekey/pkg/core/action"
@ -42,13 +51,6 @@ import (
"github.com/kubesphere/kubekey/pkg/plugins/dns"
dnsTemplates "github.com/kubesphere/kubekey/pkg/plugins/dns/templates"
"github.com/kubesphere/kubekey/pkg/utils"
"github.com/pkg/errors"
corev1 "k8s.io/api/core/v1"
kubeerrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
versionutil "k8s.io/apimachinery/pkg/util/version"
kube "k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/clientcmd"
)
type GetClusterStatus struct {
@ -478,15 +480,14 @@ func (k *KubeadmReset) Execute(runtime connector.Runtime) error {
return nil
}
type FindDifferences struct {
type FindNode struct {
common.KubeAction
}
func (f *FindDifferences) Execute(runtime connector.Runtime) error {
var node string
func (f *FindNode) Execute(runtime connector.Runtime) error {
var resArr []string
res, err := runtime.GetRunner().Cmd(
"sudo -E /usr/local/bin/kubectl get nodes | grep -v NAME | grep -v 'master' | awk '{print $1}'",
"sudo -E /usr/local/bin/kubectl get nodes | grep -v NAME | grep -v 'master\\|control-plane' | awk '{print $1}'",
true)
if err != nil {
return errors.Wrap(errors.WithStack(err), "kubectl get nodes failed")
@ -498,19 +499,23 @@ func (f *FindDifferences) Execute(runtime connector.Runtime) error {
resArr = strings.Split(res, "\r\n")
}
var workerNameStr string
workerName := make(map[string]struct{})
for j := 0; j < len(runtime.GetHostsByRole(common.Worker)); j++ {
workerNameStr += runtime.GetHostsByRole(common.Worker)[j].GetName()
workerName[runtime.GetHostsByRole(common.Worker)[j].GetName()] = struct{}{}
}
var node string
for i := 0; i < len(resArr); i++ {
if strings.Contains(workerNameStr, resArr[i]) {
continue
} else {
if _, ok := workerName[resArr[i]]; ok && resArr[i] == f.KubeConf.Arg.NodeName {
node = resArr[i]
break
}
}
if node == "" {
return errors.New("Please check the node name in the config-sample.yaml or only support to delete a worker")
}
f.PipelineCache.Set("dstNode", node)
return nil
}

View File

@ -17,9 +17,10 @@
package pipelines
import (
"github.com/kubesphere/kubekey/pkg/bootstrap/config"
"github.com/kubesphere/kubekey/pkg/bootstrap/confirm"
"github.com/kubesphere/kubekey/pkg/bootstrap/os"
"github.com/kubesphere/kubekey/pkg/bootstrap/precheck"
"github.com/kubesphere/kubekey/pkg/certs"
"github.com/kubesphere/kubekey/pkg/common"
"github.com/kubesphere/kubekey/pkg/core/module"
"github.com/kubesphere/kubekey/pkg/core/pipeline"
@ -30,9 +31,10 @@ func DeleteNodePipeline(runtime *common.KubeRuntime) error {
m := []module.Module{
&precheck.GreetingsModule{},
&confirm.DeleteNodeConfirmModule{},
&config.ModifyConfigModule{},
&kubernetes.CompareConfigAndClusterInfoModule{},
&kubernetes.DeleteKubeNodeModule{},
&os.ClearOSEnvironmentModule{},
&certs.UninstallAutoRenewCertsModule{},
}
p := pipeline.Pipeline{