Go 製のバックアップツール「restic」でバックアップを管理する

# 概要
Go 製のバックアップツール [restic](https://github.com/restic/restic) を試してみたのでメモ。

バックアップをレポジトリ単位で一元的に管理できる。主な機能としては

 - バックエンドに複数サービス対応
 - スナップショット作成
 - インクリメンタルバックアップ
 - バックアップ対象の暗号化


サポートされるバックエンド（プロトコル）

- Local
- SFTP
- REST Server
- Amazon S3
- Minio Server
- OpenStack Swift
- Backblaze B2


今回は S3 バックエンドを設定する。

#環境

 - CentOS Linux release 7.2.1511 (Core)
 - restic 0.6.1 (v0.6.1-18-ga9a2798)

#restic インストール

```bash
$ git clone https://github.com/restic/restic
$ cd restic
$ go run build.go
```

作成されたバイナリを適当なパスに展開


#バックエンドに Amazon S3 を使う 

credential を環境変数に設定

```bash
$ export AWS_ACCESS_KEY_ID=AK***************
$ export AWS_SECRET_ACCESS_KEY=**************************************
```

レポジトリを初期化
※指定した名前で S3 にもバケットが自動で作成される

```bash
$ restic -r s3:s3.amazonaws.com/quickguard-restic-test init
enter password for new backend:
enter password again:
created restic backend 61b47afaeb at s3:s3.amazonaws.com/quickguard-restic-test

Please note that knowledge of your password is required to access
the repository. Losing your password means that your data is
irrecoverably lost.
```

環境変数 RESTIC_REPOSITORY と RESTIC_PASSWORD にレポジトリとパスワードを設定しておくと、以後の入力を省略可能となる

```bash
$ export RESTIC_REPOSITORY=s3:s3.amazonaws.com/quickguard-restic-test
$ export RESTIC_PASSWORD=*************
```

#スナップショット作成

```bash
$ restic backup /data/html
scan [/data/html]
scanned 280 directories, 3012 files in 0:00
[0:13] 100.00%  7.834 MiB/s  101.848 MiB / 101.848 MiB  3292 / 3292 items  0 errors  ETA 0:00
duration: 0:13, 7.73MiB/s
snapshot 8ef85219 saved
```


特定ファイル除外

```
$ restic backup /data/html --exclude=*.log --exclude-file=exclude
```

#標準入力からのスナップショット作成

mysqldump のスナップショット作成

```bash
$ mysqldump -u root -x --all-databases | restic backup --stdin --stdin-filename mysqldump-all.sql
[0:04] 10.210 MiB  2.553 MiB/s
duration: 0:04, 2.18MiB/s
archived as dbadd447
```

確認

```
$ restic snapshots --host DB001
ID        Date                 Host        Tags        Directory
----------------------------------------------------------------------
dbadd447  2017-06-06 15:15:39  DB001                   mysqldump-all.sql
```


#スナップショット一覧取得

全スナップショット取得
※Date は backup を実行したマシンの localtime が表示される

```bash
$ restic snapshots
ID        Date                 Host        Tags        Directory
----------------------------------------------------------------------
8ef85219  2017-06-06 11:53:29  WEB001                  /data/html
23dfb53f  2017-06-06 11:59:41  WEB001                  /data/html
dbadd447  2017-06-06 15:15:39  DB001                   mysqldump-all.sql
11df38e8  2017-06-06 04:01:42  WEB002                  /data/html
```

Host, Directory で filter も可能

```bash
$ restic snapshots --host WEB002
ID        Date                 Host        Tags        Directory
----------------------------------------------------------------------
11df38e8  2017-06-06 04:01:42  WEB002                  /data/html

$ restic snapshots --path /data/html
ID        Date                 Host        Tags        Directory
----------------------------------------------------------------------
8ef85219  2017-06-06 11:53:29  WEB001                  /data/html
23dfb53f  2017-06-06 11:59:41  WEB001                  /data/html
11df38e8  2017-06-06 04:01:42  WEB002                  /data/html
```


**json output**

```bash
$ restic snapshots --json | jq .
```

```json
[
  {
    "time": "2017-06-06T11:53:29.754786574+09:00",
    "tree": "4cdbdd0ca17c112a54bbb3b318a52580c3036d22035e8b06e2092b16e99c72c3",
    "paths": [
      "/data/html"
    ],
    "hostname": "WEB001",
    "username": "root",
    "id": "8ef85219b0aabed43b95f8b863712df85be108f44ff560968d402cc243586729"
  },
  {
    "time": "2017-06-06T11:59:41.863158034+09:00",
    "parent": "8ef85219b0aabed43b95f8b863712df85be108f44ff560968d402cc243586729",
    "tree": "3362dd121c4b748032d62b71508458c7953dee353a187497271089c3c4db59fc",
    "paths": [
      "/data/html"
    ],
    "hostname": "WEB001",
    "username": "root",
    "id": "23dfb53faa3b6f0b20512f0b884e0185605877503fbbdbb033c7769ac1c35a83"
  },
  {
    "time": "2017-06-06T04:01:42.168333564Z",
    "tree": "5cf40d8d3955c940d28ecfaa38e8d509f042c7bc5696247b86e9a9c4ca925536",
    "paths": [
      "/data/html"
    ],
    "hostname": "WEB002",
    "username": "user",
    "uid": 501,
    "gid": 496,
    "id": "11df38e8822022df07bfd182ffc8bc3b17f81ba49f5029563f41096c632afe50"
  }
]
```


#レポジトリをマウント

```bash
$ mkdir -p ~/mnt/restic
$ restic mount ~/mnt/restic
```

エラー発生

```
fusermount: exec: "fusermount": executable file not found in $PATH
unable to umount (maybe already umounted?): exec: "fusermount": executable file not found in $PATH
```

fusermount が必要らしいので以下インストール

```
$ sudo yum install -y fuse
```

再度マウント

```
$ restic mount ~/mnt/restic
Now serving the repository at ~/mnt/restic
Don't forget to umount after quitting!
```

スナップショット取得のタイミングのディレクトリが確認できる(ReadOnly)

```
$ ls ~/mnt/restic/
snapshots

$ ls ~/mnt/restic/snapshots/
2017-06-06T11:53:29+09:00  2017-06-06T11:59:41+09:00
```

アンマウント

```bash
$ fusermount -u ~/mnt/restic
```

#スナップショットをリストア

**全ファイルをリストア**

```bash
$ restic restore 23dfb53f --target /tmp/restore
restoring <Snapshot 23dfb53f of [/data/html] at 2017-06-06 11:59:41.863158034 +0900 JST by user@WEB001> to /tmp/restore
```

遅すぎる。 111MB 程度のリストアに 15分 かかる。

```
real    15m44.892s
user    0m4.896s
sys     0m1.375s
```

特定ファイル（パス）のみリストアも出来ないっぽい。


#スナップショット削除

```bash
$ restic forget 8ef85219
```

ロックされてるっぽい

```
repository is already locked by PID 10523 on WEB001 by root (UID 0, GID 0)
lock was created at 2017-06-06 13:11:49 (13m22.283550245s ago)
storage ID 6adf6afd
the `unlock` command can be used to remove stale locks
```

ロック解除

```bash
$ restic unlock 8ef85219
successfully removed locks
```

再度実行

```bash
$ restic forget 8ef85219
removed snapshot 8ef85219
```

データも削除する場合は `prune` を実行

```bash
$ restic prune
counting files in repo
building new index for repo
[0:10] 100.00%  129 / 129 packs
repository contains 129 packs (41196 blobs) with 587.506 MiB bytes
processed 41196 blobs: 0 duplicate blobs, 0B duplicate
load all snapshots
find data that is still in use for 2 snapshots
[35:47] 100.00%  2 / 2 snapshots
found 40946 of 41196 data blobs still in use, removing 250 blobs
will delete 0 packs and rewrite 19 packs, this frees 1.073 MiB
[2:29] 100.00%  19 / 19 packs rewritten
counting files in repo
[0:10] 100.00%  128 / 128 packs
finding old index files
saved new index as fd6b9098
remove 3 old index files
done
```

これも 40分 程度かかる。


#ポリシーベースのスナップショットローテーション

`forget` に対して以下のポリシーが設定できる

 - `--keep-last` n never delete the n last (most recent) snapshots
 - `--keep-hourly` n for the last n hours in which a snapshot was made, keep only the last snapshot for each hour.
 - `--keep-daily` n for the last n days which have one or more snapshots, only keep the last one for that day.
 - `--keep-weekly` n for the last n weeks which have one or more snapshots, only keep the last one for that week.
 - `--keep-monthly` n for the last n months which have one or more snapshots, only keep the last one for that month.
 - `--keep-yearly` n for the last n years which have one or more snapshots, only keep the last one for that year.


最新のスナップショットを1個残して不要データ削除

```
$ restic forget --keep-last 1 --prune
```

結果

```
snapshots for host WEB002, paths: [/data/www]:

keep 1 snapshots:
ID        Date                 Host        Tags        Directory
----------------------------------------------------------------------
11df38e8  2017-06-06 04:01:42  WEB002                    /data/html

snapshots for host WEB001, paths: [/data/html]:

keep 1 snapshots:
ID        Date                 Host        Tags        Directory
----------------------------------------------------------------------
23dfb53f  2017-06-06 11:59:41  WEB001                  /data/html
```

#レポジトリ内のファイル検索

レポジトリ内の index.php を検索

```bash
$ restic find index.php
```

結果

```
$ restic find index.php
enter password for repository:
Found matching entries in snapshot 23dfb53faa3b6f0b20512f0b884e0185605877503fbbdbb033c7769ac1c35a83
/html/index.php
...
```

実行時間

```
real    32m25.850s
user    0m7.464s
sys     0m0.540s
```

　
ローカルバックエンドで実行した場合は、S3 バックエンドでは 数十分かかっていた restore, find が3秒程度で結果が返ってきたため、S3 バックエンドのせいで諸々の動作がクソ重いと思われる。