diff --git a/Documentation/v2/admin_guide.md b/Documentation/v2/admin_guide.md index 97877c497..58b83dc9f 100644 --- a/Documentation/v2/admin_guide.md +++ b/Documentation/v2/admin_guide.md @@ -217,12 +217,14 @@ To recover from such scenarios, etcd provides functionality to backup and restor **NB:** Windows users must stop etcd before running the backup command. -The first step of the recovery is to backup the data directory on a functioning etcd node. To do this, use the `etcdctl backup` command, passing in the original data directory used by etcd. For example: +The first step of the recovery is to backup the data directory and wal directory, if stored separately, on a functioning etcd node. To do this, use the `etcdctl backup` command, passing in the original data (and wal) directory used by etcd. For example: ```sh etcdctl backup \ --data-dir %data_dir% \ + [--wal-dir %wal_dir%] \ --backup-dir %backup_data_dir% + [--backup-wal-dir %backup_wal_dir%] ``` This command will rewrite some of the metadata contained in the backup (specifically, the node ID and cluster ID), which means that the node will lose its former identity. In order to recreate a cluster from the backup, you will need to start a new, single-node cluster. The metadata is rewritten to prevent the new node from inadvertently being joined onto an existing cluster. @@ -234,20 +236,24 @@ To restore a backup using the procedure created above, start etcd with the `-for ```sh etcd \ -data-dir=%backup_data_dir% \ + [-wal-dir=%backup_wal_dir%] \ -force-new-cluster \ ... ``` Now etcd should be available on this node and serving the original datastore. -Once you have verified that etcd has started successfully, shut it down and move the data back to the previous location (you may wish to make another copy as well to be safe): +Once you have verified that etcd has started successfully, shut it down and move the data and wal, if stored separately, back to the previous location (you may wish to make another copy as well to be safe): ```sh pkill etcd rm -fr %data_dir% + rm -fr %wal_dir% mv %backup_data_dir% %data_dir% + mv %backup_wal_dir% %wal_dir% etcd \ -data-dir=%data_dir% \ + [-wal-dir=%wal_dir%] \ ... ``` diff --git a/etcdctl/ctlv2/command/backup_command.go b/etcdctl/ctlv2/command/backup_command.go index c4ee61d39..9b49d9e6c 100644 --- a/etcdctl/ctlv2/command/backup_command.go +++ b/etcdctl/ctlv2/command/backup_command.go @@ -37,7 +37,9 @@ func NewBackupCommand() cli.Command { ArgsUsage: " ", Flags: []cli.Flag{ cli.StringFlag{Name: "data-dir", Value: "", Usage: "Path to the etcd data dir"}, + cli.StringFlag{Name: "wal-dir", Value: "", Usage: "Path to the etcd wal dir"}, cli.StringFlag{Name: "backup-dir", Value: "", Usage: "Path to the backup dir"}, + cli.StringFlag{Name: "backup-wal-dir", Value: "", Usage: "Path to the backup wal dir"}, }, Action: handleBackup, } @@ -45,10 +47,23 @@ func NewBackupCommand() cli.Command { // handleBackup handles a request that intends to do a backup. func handleBackup(c *cli.Context) { + var srcWAL string + var destWAL string + srcSnap := path.Join(c.String("data-dir"), "member", "snap") destSnap := path.Join(c.String("backup-dir"), "member", "snap") - srcWAL := path.Join(c.String("data-dir"), "member", "wal") - destWAL := path.Join(c.String("backup-dir"), "member", "wal") + + if c.String("wal-dir") != "" { + srcWAL = c.String("wal-dir") + } else { + srcWAL = path.Join(c.String("data-dir"), "member", "wal") + } + + if c.String("backup-wal-dir") != "" { + destWAL = c.String("backup-wal-dir") + } else { + destWAL = path.Join(c.String("backup-dir"), "member", "wal") + } if err := os.MkdirAll(destSnap, 0700); err != nil { log.Fatalf("failed creating backup snapshot dir %v: %v", destSnap, err)