From 55df307d9892df491d67b60f0b25d43fa6d16c2f Mon Sep 17 00:00:00 2001 From: louisehong Date: Fri, 21 Aug 2020 17:23:22 +0800 Subject: [PATCH] restore only one node to local --- Dockerfile | 20 +++++++++++++++ cmd/etcd.go | 21 +++++++++++----- install/constants.go | 1 + install/etcd_restore.go | 56 +++++++++++++++++++++++++++++++++++++++++ install/etcd_save.go | 13 ++++++++-- 5 files changed, 103 insertions(+), 8 deletions(-) create mode 100644 Dockerfile diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 000000000..50a7e1720 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,20 @@ +FROM golang:1.14.3 AS builder + +ENV GO111MODULE=on +ENV GOPROXY=https://goproxy.io + +WORKDIR /root + +COPY . . + +RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o /sealos -mod vendor -ldflags "-X github.com/fanux/sealos/version.Version=latest -X github.com/fanux/sealos/version.Build= -X 'github.com/fanux/sealos/version.BuildTime='" main.go + +FROM alpine:3.7 +ENV TZ=Asia/Shangha +RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories && \ + apk add tzdata ca-certificates && \ + cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \ + echo "Asia/Shanghai" > /etc/timezone && apk add --update bash && \ + rm -rf /var/cache/apk/* +COPY --from=builder /sealos /bin/sealos +ENTRYPOINT ["/bin/sealos"] \ No newline at end of file diff --git a/cmd/etcd.go b/cmd/etcd.go index a316a729e..542669bc6 100644 --- a/cmd/etcd.go +++ b/cmd/etcd.go @@ -22,12 +22,14 @@ import ( ) var exampleCmd = ` - - # snapshot save the etcd - sealos etcd --snap-save --name snapshot --path /opt/sealos/ectd-backup + # snapshot save the etcd, the backupPath is on etcd nodes. not on the sealos init machine. + sealos etcd --snap-save --name snapshot --backupPath /opt/sealos/ectd-backup # snapshot restore the etcd - sealos etcd --restore --name snapshot --path /opt/sealos/ectd-backup + sealos etcd --snap-restore --name snapshot --backupPath /opt/sealos/ectd-backup + + # etcd health check + sealos etcd --health ` // etcdCmd represents the etcd command @@ -47,6 +49,12 @@ var etcdCmd = &cobra.Command{ e := install.GetEtcdBackFlags() e.HealthCheck() } + if install.EtcdRestore { + e := install.GetRestoreFlags() + e.Restore() + logger.Info("check your Restore dir: %s", e.RestoreDir) + logger.Info("restore kubernetes yourself glad~") + } }, } @@ -55,10 +63,11 @@ func init() { rootCmd.AddCommand(etcdCmd) etcdCmd.Flags().BoolVar(&install.EtcdSnapshotSave, "snap-save", false, "snapshot your kubernets etcd ") - etcdCmd.Flags().BoolVar(&install.EtcdRestore, "restore", false, "restore your kubernets etcd") + etcdCmd.Flags().BoolVar(&install.EtcdRestore, "snap-restore", false, "restore your kubernets etcd") etcdCmd.Flags().BoolVar(&install.EtcdHealthCheck, "health", false, "check your kubernets etcd") etcdCmd.Flags().StringVar(&install.SnapshotName,"name",install.ETCDSNAPSHOTDEFAULTNAME,"Specify snapshot name") - etcdCmd.Flags().StringVar(&install.EtcdBackDir,"path",install.ETCDDEFAULTBACKUPDIR,"Specify snapshot backup dir") + etcdCmd.Flags().StringVar(&install.EtcdBackDir,"backupPath",install.ETCDDEFAULTBACKUPDIR,"Specify snapshot backup dir") + etcdCmd.Flags().StringVar(&install.RestorePath,"restorePath",install.ETCDDEFAULTRESTOREDIR,"Specify snapshot restore dir") // Here you will define your flags and configuration settings. diff --git a/install/constants.go b/install/constants.go index 3c9ad13c3..16df62728 100644 --- a/install/constants.go +++ b/install/constants.go @@ -16,6 +16,7 @@ const ( // etcd backup ETCDSNAPSHOTDEFAULTNAME = "snapshot" ETCDDEFAULTBACKUPDIR = "/opt/sealos/ectd-backup" + ETCDDEFAULTRESTOREDIR = "/opt/sealos/ectd-restore" EtcdCacart = "/root/.sealos/pki/etcd/ca.crt" EtcdCert = "/root/.sealos/pki/etcd/healthcheck-client.crt" EtcdKey = "/root/.sealos/pki/etcd/healthcheck-client.key" diff --git a/install/etcd_restore.go b/install/etcd_restore.go index 301754495..bdc974801 100644 --- a/install/etcd_restore.go +++ b/install/etcd_restore.go @@ -3,7 +3,10 @@ package install import ( "fmt" "github.com/wonderivan/logger" + "go.etcd.io/etcd/clientv3/snapshot" + "go.uber.org/zap" "os" + "path/filepath" ) func GetRestoreFlags() *EtcdFlags { @@ -27,6 +30,7 @@ func GetRestoreFlags() *EtcdFlags { return e } +// we don't restore kubernetes but restore etcd func (e *EtcdFlags) Prepare() error { // stop kube-apiserver kube-controller-manager kube-scheduler etcd // on every etcd nodes , and back all data to /var/lib/etcd.bak @@ -48,6 +52,58 @@ func (e *EtcdFlags) Prepare() error { return nil } +func (e *EtcdFlags) Restore() { + restorePeerURLs := GetEtcdPeerURLs(e.EtcdHosts) + restoreClusterToken := "etcd-cluster" + restoreCluster:= GetEtcdInitialCluster(e.EtcdHosts) + walDir := filepath.Join(e.RestoreDir, "member", "wal") + + lg, err := zap.NewProduction() + if err != nil { + logger.Error("get lg error: ", err) + os.Exit(-1) + } + sp := snapshot.NewV3(lg) + // get master name. + host := SSHConfig.CmdToString(e.EtcdHosts[0], "hostname", "") + if err := sp.Restore(snapshot.RestoreConfig{ + SnapshotPath: e.LongName, + Name: "etcd-"+host, + OutputDataDir: e.RestoreDir, + OutputWALDir: walDir, + PeerURLs: restorePeerURLs, + InitialCluster: restoreCluster, + InitialClusterToken: restoreClusterToken, + SkipHashCheck: true, + }); err != nil { + logger.Error("restore etcd error: ", err) + os.Exit(-1) + } +} + +func GetEtcdInitialCluster(hosts []string) string { + initialCluster := "" + for i, host := range hosts { + hostname := SSHConfig.CmdToString(host, "hostname", "") + ip := reFormatHostToIp(host) + initialCluster += fmt.Sprintf("etcd-%s=https://%s:2380", hostname, ip) + if i < (len(hosts) - 1) { + initialCluster += "," + } + } + return initialCluster +} + +func GetEtcdPeerURLs(hosts []string) []string { + var peerUrls []string + for _, host := range hosts { + ip := reFormatHostToIp(host) + url := fmt.Sprintf("https://%s:2380", ip) + peerUrls = append(peerUrls, url) + } + return peerUrls +} + func CmdWork(node, cmd, workdir string) error { command := fmt.Sprintf("cd %s && %s", workdir, cmd) // not safe when use etcdctl to backup diff --git a/install/etcd_save.go b/install/etcd_save.go index a880b6704..e280524f0 100644 --- a/install/etcd_save.go +++ b/install/etcd_save.go @@ -53,6 +53,14 @@ func GetEtcdBackFlags() *EtcdFlags { } func Save(e *EtcdFlags) { + if !FileExist(e.BackDir) { + err := os.MkdirAll(e.BackDir, os.ModePerm) + if err != nil { + logger.Error("mkdir BackDir err: ",err) + os.Exit(1) + } + } + cfg, err := GetCfg(e.Endpoints) if err != nil { logger.Error("get etcd cfg error: ", err) @@ -69,6 +77,7 @@ func Save(e *EtcdFlags) { if err := sp.Save(ctx, *cfg, e.LongName); err != nil { logger.Error("snapshot save err: ", err) + os.Exit(-1) } fmt.Printf("Snapshot saved at %s\n", e.LongName) } @@ -130,7 +139,7 @@ type epHealth struct { Error string `json:"error"` } -func (e *EtcdFlags)HealthCheck() { +func (e *EtcdFlags) HealthCheck() { cfgs := []*clientv3.Config{} for _, ep := range e.Endpoints { cfg, err := GetCfg([]string{ep}) @@ -183,4 +192,4 @@ func (e *EtcdFlags)HealthCheck() { if errs { logger.Error("unhealthy cluster") } -} \ No newline at end of file +}