Skip to content

Commit

Permalink
feat: support recover master0
Browse files Browse the repository at this point in the history
  • Loading branch information
kakzhou719 committed Dec 2, 2022
1 parent 48baeed commit 08cd5ca
Show file tree
Hide file tree
Showing 31 changed files with 546 additions and 361 deletions.
1 change: 1 addition & 0 deletions cmd/sealer/cmd/alpha/alpha.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,5 +36,6 @@ func NewCmdAlpha() *cobra.Command {
cmd.AddCommand(NewUpgradeCmd())
cmd.AddCommand(NewGenCmd())
cmd.AddCommand(NewCheckCmd())
cmd.AddCommand(NewRecoverCmd())
return cmd
}
145 changes: 145 additions & 0 deletions cmd/sealer/cmd/alpha/recover.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
// Copyright © 2022 Alibaba Group Holding Ltd.
//
// 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 alpha

import (
"fmt"
"net"
"path/filepath"
"strconv"

"github.com/sealerio/sealer/cmd/sealer/cmd/utils"
"github.com/sealerio/sealer/pkg/clusterfile"
"github.com/sealerio/sealer/pkg/infradriver"
netutils "github.com/sealerio/sealer/utils/net"
"github.com/sealerio/sealer/utils/shellcommand"
"github.com/spf13/cobra"
)

type RecoverFlags struct {
Host net.IP
}

var recoverFlag *RecoverFlags

var longRecoverCmdDescription = ` `

var exampleForRecoverCmd = `The following command will recover master0 node through specified host ip:
sealer alpha recover master0 --host 192.168.1.203
`

// NewRecoverCmd recover master0
func NewRecoverCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "recover",
Short: "sealer experimental sub-commands for recover cluster",
Long: longAlphaCmdDescription,
}
cmd.AddCommand(NewRecoverMaster0Cmd())
return cmd
}

// NewRecoverMaster0Cmd recover master0
func NewRecoverMaster0Cmd() *cobra.Command {
recoverCmd := &cobra.Command{
Use: "master0",
Short: "recover master0 to specified host by sealer",
Long: longRecoverCmdDescription,
Example: exampleForRecoverCmd,
RunE: func(cmd *cobra.Command, args []string) error {
recoverHost := recoverFlag.Host
if recoverHost == nil {
return fmt.Errorf("recover host cannot be empty")
}

cf, err := clusterfile.NewClusterFile(nil)
if err != nil {
return err
}

cluster := cf.GetCluster()
infraDriver, err := infradriver.NewInfraDriver(&cluster)
if err != nil {
return err
}

regConfig := infraDriver.GetClusterRegistryConfig()
if !netutils.IsInIPList(recoverHost, regConfig.LocalRegistry.DeployHosts) {
return fmt.Errorf("recover host(%s) must in local registry deploy host (%s)",
recoverHost, regConfig.LocalRegistry.DeployHosts)
}

rootfs := infraDriver.GetClusterRootfsPath()
dataDir := filepath.Join(rootfs, "registry")
//todo use registry driver to launch registry
initRegistry := fmt.Sprintf("cd %s/scripts && bash init-registry.sh %s %s %s", infraDriver.GetClusterRootfsPath(),
strconv.Itoa(regConfig.LocalRegistry.Port), dataDir, regConfig.LocalRegistry.Domain)
if err := infraDriver.CmdAsync(recoverHost, initRegistry); err != nil {
return err
}

client := utils.GetClusterClient()
if client == nil {
return fmt.Errorf("failed to init cluster client")
}

currentCluster, err := utils.GetCurrentCluster(client)
if err != nil {
return fmt.Errorf("failed to get current cluster: %v", err)
}
// get current host ip list
var hosts []net.IP
for _, host := range currentCluster.Spec.Hosts {
hosts = append(hosts, host.IPS...)
}

// remove old registry hosts alias
uninstallCmd := shellcommand.CommandUnSetHostAlias(shellcommand.DefaultSealerHostAliasForRegistry)
removeFunc := func(host net.IP) error {
err := infraDriver.CmdAsync(host, uninstallCmd)
if err != nil {
return fmt.Errorf("failed to delete registry configuration: %v", err)
}
return nil
}

err = infraDriver.Execute(hosts, removeFunc)
if err != nil {
return err
}

// add new registry hosts alias
addFunc := func(host net.IP) error {
err := infraDriver.CmdAsync(host, shellcommand.CommandSetHostAlias(regConfig.LocalRegistry.Domain,
recoverHost.String(), shellcommand.DefaultSealerHostAliasForRegistry))
if err != nil {
return fmt.Errorf("failed to config cluster hosts file cmd: %v", err)
}
return nil
}

err = infraDriver.Execute(hosts, addFunc)
if err != nil {
return err
}

return nil
},
}

recoverFlag = &RecoverFlags{}
recoverCmd.Flags().IPVar(&recoverFlag.Host, "host", nil, "ip address that the new master0 will be recovered on")
return recoverCmd
}
82 changes: 19 additions & 63 deletions cmd/sealer/cmd/cluster/apply.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,30 +16,26 @@ package cluster

import (
"fmt"
"net"
"os"
"path/filepath"

"github.com/sealerio/sealer/cmd/sealer/cmd/utils"

"github.com/sealerio/sealer/cmd/sealer/cmd/types"

"github.com/pkg/errors"
"github.com/sealerio/sealer/common"
"github.com/sealerio/sealer/pkg/client/k8s"
"github.com/sealerio/sealer/pkg/clusterfile"
v12 "github.com/sealerio/sealer/pkg/define/image/v1"
"github.com/sealerio/sealer/pkg/define/options"
"github.com/sealerio/sealer/pkg/imageengine"
"github.com/sealerio/sealer/pkg/infradriver"
v2 "github.com/sealerio/sealer/types/api/v2"
"github.com/sealerio/sealer/utils/strings"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
corev1 "k8s.io/api/core/v1"
)

var applyClusterFile string

var applyMode string

const MasterRoleLabel = "node-role.kubernetes.io/master"
var applyFlags *types.ApplyFlags

var longApplyCmdDescription = `apply command is used to apply a Kubernetes cluster via specified Clusterfile.
If the Clusterfile is applied first time, Kubernetes cluster will be created. Otherwise, sealer
Expand All @@ -58,9 +54,11 @@ func NewApplyCmd() *cobra.Command {
Args: cobra.NoArgs,
RunE: func(cmd *cobra.Command, args []string) error {
var (
cf clusterfile.Interface
clusterFileData []byte
err error
cf clusterfile.Interface
clusterFileData []byte
err error
applyClusterFile = applyFlags.ClusterFile
applyMode = applyFlags.ApplyMode
)
logrus.Warn("sealer apply command will be deprecated in the future, please use sealer run instead.")

Expand Down Expand Up @@ -99,17 +97,17 @@ func NewApplyCmd() *cobra.Command {

if extension.Type == v12.AppInstaller {
logrus.Infof("start to install application: %s", imageName)
return installApplication(imageName, []string{}, extension, infraDriver, imageEngine)
return installApplication(imageName, []string{}, extension, infraDriver, imageEngine, applyMode)
}

client := getClusterClient()
client := utils.GetClusterClient()
if client == nil {
// no k8s client means to init a new cluster.
logrus.Infof("start to create new cluster with image: %s", imageName)
return createNewCluster(imageName, infraDriver, imageEngine, cf)
return createNewCluster(imageName, infraDriver, imageEngine, cf, applyMode)
}

currentCluster, err := GetCurrentCluster(client)
currentCluster, err := utils.GetCurrentCluster(client)
if err != nil {
return errors.Wrap(err, "failed to get current cluster")
}
Expand All @@ -127,52 +125,10 @@ func NewApplyCmd() *cobra.Command {
return scaleUpCluster(imageName, mj, nj, infraDriver, imageEngine, cf)
},
}
applyCmd.Flags().BoolVar(&ForceDelete, "force", false, "force to delete the specified cluster if set true")
applyCmd.Flags().StringVarP(&applyClusterFile, "Clusterfile", "f", "", "Clusterfile path to apply a Kubernetes cluster")
applyCmd.Flags().StringVarP(&applyMode, "applyMode", "m", common.ApplyModeApply, "load images to the specified registry in advance")
return applyCmd
}

func GetCurrentCluster(client *k8s.Client) (*v2.Cluster, error) {
nodes, err := client.ListNodes()
if err != nil {
return nil, err
}

cluster := &v2.Cluster{}
var masterIPList []net.IP
var nodeIPList []net.IP

for _, node := range nodes.Items {
addr := getNodeAddress(node)
if addr == nil {
continue
}
if _, ok := node.Labels[MasterRoleLabel]; ok {
masterIPList = append(masterIPList, addr)
continue
}
nodeIPList = append(nodeIPList, addr)
}
cluster.Spec.Hosts = []v2.Host{{IPS: masterIPList, Roles: []string{common.MASTER}}, {IPS: nodeIPList, Roles: []string{common.NODE}}}

return cluster, nil
}

func getNodeAddress(node corev1.Node) net.IP {
if len(node.Status.Addresses) < 1 {
return nil
}
return net.ParseIP(node.Status.Addresses[0].Address)
}

func getClusterClient() *k8s.Client {
client, err := k8s.NewK8sClient()
if client != nil {
return client
}
if err != nil {
logrus.Warnf("try to new k8s client via default kubeconfig, maybe this is a new cluster that needs to be created: %v", err)
}
return nil
applyFlags = &types.ApplyFlags{}
applyCmd.Flags().BoolVar(&applyFlags.ForceDelete, "force", false, "force to delete the specified cluster if set true")
applyCmd.Flags().StringVarP(&applyFlags.ClusterFile, "Clusterfile", "f", "", "Clusterfile path to apply a Kubernetes cluster")
applyCmd.Flags().StringVarP(&applyFlags.ApplyMode, "applyMode", "m", common.ApplyModeApply, "load images to the specified registry in advance")
return applyCmd
}
42 changes: 15 additions & 27 deletions cmd/sealer/cmd/cluster/run-app.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ package cluster

import (
"fmt"
"path/filepath"

"github.com/sealerio/sealer/cmd/sealer/cmd/types"
"github.com/sealerio/sealer/common"
Expand All @@ -27,7 +26,6 @@ import (
"github.com/sealerio/sealer/pkg/imagedistributor"
"github.com/sealerio/sealer/pkg/imageengine"
"github.com/sealerio/sealer/pkg/infradriver"
"github.com/sealerio/sealer/pkg/registry"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)
Expand All @@ -37,16 +35,17 @@ var longNewRunAPPCmdDescription = `sealer run-app localhost/nginx:v1`
var exampleForRunAppCmd = ``

func NewRunAPPCmd() *cobra.Command {
runCmd := &cobra.Command{
runAppCmd := &cobra.Command{
Use: "run-app",
Short: "start to run an application cluster image",
Long: longNewRunAPPCmdDescription,
Example: exampleForRunAppCmd,
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
var (
cf clusterfile.Interface
err error
cf clusterfile.Interface
err error
applyMode = appFlags.ApplyMode
)

cf, err = clusterfile.NewClusterFile(nil)
Expand Down Expand Up @@ -74,18 +73,20 @@ func NewRunAPPCmd() *cobra.Command {
return fmt.Errorf("exit install process, wrong cluster image type: %s", extension.Type)
}

return installApplication(args[0], appFlags.LaunchCmds, extension, infraDriver, imageEngine)
return installApplication(args[0], appFlags.LaunchCmds, extension, infraDriver, imageEngine, applyMode)
},
}

appFlags = &types.APPFlags{}
runCmd.Flags().StringSliceVar(&appFlags.LaunchCmds, "cmds", []string{}, "override default LaunchCmds of clusterimage")
runAppCmd.Flags().StringSliceVar(&appFlags.LaunchCmds, "cmds", []string{}, "override default LaunchCmds of clusterimage")
//runCmd.Flags().StringSliceVar(&appFlags.LaunchArgs, "args", []string{}, "override default LaunchArgs of clusterimage")
return runCmd
runAppCmd.Flags().StringVarP(&appFlags.ApplyMode, "applyMode", "m", common.ApplyModeApply, "load images to the specified registry in advance")

return runAppCmd
}

func installApplication(appImageName string, launchCmds []string, extension v12.ImageExtension,
infraDriver infradriver.InfraDriver, imageEngine imageengine.Interface) error {
infraDriver infradriver.InfraDriver, imageEngine imageengine.Interface, createMode string) error {
clusterHosts := infraDriver.GetHostIPList()

clusterHostsPlatform, err := infraDriver.GetHostsPlatform(clusterHosts)
Expand Down Expand Up @@ -115,30 +116,17 @@ func installApplication(appImageName string, launchCmds []string, extension v12.
return err
}

if applyMode == common.ApplyModeLoadImage {
logrus.Infof("start to apply with mode(%s)", applyMode)

if err = distributor.DistributeRegistry(infraDriver.GetHostIPList()[0], infraDriver.GetClusterRootfsPath()); err != nil {
if createMode == common.ApplyModeLoadImage {
logrus.Infof("start to apply with mode(%s)", createMode)
reg := infraDriver.GetClusterRegistryConfig()
if err = distributor.DistributeRegistry(reg.LocalRegistry.DeployHosts, infraDriver.GetClusterRootfsPath()); err != nil {
return err
}
logrus.Infof("load image success")
return nil
}

//todo grab this config from cluster file, that's because it belongs to cluster level information
var registryConfig registry.RegConfig
var config = registry.Registry{
Domain: registry.DefaultDomain,
Port: registry.DefaultPort,
}

registryConfig.LocalRegistry = &registry.LocalRegistry{
DataDir: filepath.Join(infraDriver.GetClusterRootfsPath(), "registry"),
DeployHost: infraDriver.GetHostIPListByRole(common.MASTER)[0],
Registry: config,
}

installer := clusterruntime.NewAppInstaller(infraDriver, distributor, extension, registryConfig)
installer := clusterruntime.NewAppInstaller(infraDriver, distributor, extension)
err = installer.Install(infraDriver.GetHostIPListByRole(common.MASTER)[0], launchCmds)
if err != nil {
return err
Expand Down
Loading

0 comments on commit 08cd5ca

Please sign in to comment.