WAL-GでmongoDBをいい感じにバックアップする

# はじめに
Misskey v10, めいすきー鯖缶のみなさん  
データベースのバックアップは取られていますか？  
この度、[私がPostgreSQLで物理バックアップ](https://qiita.com/atsu1125/items/676d24c0473ad94b3f2b)に愛用している[WAL-G](https://github.com/wal-g/wal-g)さんがmongoDBにもベータ版ながら対応してきたというところで試用してみました。  
mongoDBって今までmongodumpでローカルにダンプを作ってそれを圧縮してストレージに保存するしかなかったんですが、これはオブジェクトストレージにバックアップを圧縮してアップロードできるのでとてもいいです。  
ベータ版ではありますが、OplogというWALみたいなものを書き出せるので、ポイントインリカバリに役立つ可能性があります。  
OplogはWALと比較して扱いが難しかったんですが、WAL-Gさんはどうにか扱えるように工夫してくれてます。  

:::note warn
機能としては十分に感じてますが、まだベータ版なのでポリシーによっては本番環境への導入はまだできないかもしれません。  
:::

さらに可用性を高めるならレプリケーションと併用するとよいでしょう。  
https://qiita.com/atsu1125/items/df0ca4d47b835f22dbd3  
こちらにまとめておきました。  

# 作業環境

OS: Debian Bullseye  
Software version: mongoDB Community Edition 5.0.10  
WAL-G: v2.0.1  
mongoDBを使用しているアプリケーションはめいすきーです。  
https://github.com/atsu1125/misskey  
個人的にとても優れたオープンソースのSNSソフトウェアなのでおすすめです。  
が基本的にはmongoDBの利用するソフトウェア全て向けに書いています。

# WAL-Gのインストール

これは普通にビルド済みの実行ファイルを入れます。 
 
```
wget https://github.com/wal-g/wal-g/releases/download/v2.0.1/wal-g-mongo-ubuntu-20.04-amd64
chmod +x wal-g-mongo-ubuntu-20.04-amd64
mv wal-g-mongo-ubuntu-20.04-amd64 /usr/local/bin/wal-g-mongo
```

# 環境変数定義

次に`/usr/local/bin/wal-g-mongo.sh`を作成します。  
ラッパーってやつです。このスクリプトで環境変数を操作します。  
設定値は各自で読み替えてもらってください。  
S3互換のストレージ使ってますが、GSでもいけます。  
https://qiita.com/atsu1125/items/676d24c0473ad94b3f2b#%E7%92%B0%E5%A2%83%E5%A4%89%E6%95%B0%E5%AE%9A%E7%BE%A9  
を参考に。  

```bash:/usr/local/bin/wal-g-mongo.sh
#!/bin/bash
export AWS_ACCESS_KEY_ID="アクセスキー"
export AWS_SECRET_ACCESS_KEY="シークレット"
export AWS_ENDPOINT="https://エンドポイント"
export WALG_S3_PREFIX="s3://バケット名/"
export MONGODB_URI="mongodb://ユーザー名:パスワード@localhost:27017/?authSource=認証データベース名&socketTimeoutMS=60000&connectTimeoutMS=10000"
export WALG_STREAM_CREATE_COMMAND='mongodump --archive --oplog -h localhost:27017 -u ユーザー名 -p パスワード --authenticationDatabase 認証データベース名'
export WALG_STREAM_RESTORE_COMMAND='mongorestore --archive --oplogReplay -h localhost:27017 -u ユーザー名 -p パスワード --authenticationDatabase 認証データベース名'
export OPLOG_ARCHIVE_TIMEOUT_INTERVAL="30s"
export OPLOG_ARCHIVE_AFTER_SIZE="20971520"
export OPLOG_PITR_DISCOVERY_INTERVAL="168h"
export OPLOG_PUSH_WAIT_FOR_BECOME_PRIMARY="true"
export WALG_COMPRESSION_METHOD="brotli"

exec /usr/local/bin/wal-g-mongo "$@"
```

# フルバックアップの設定
フルバックアップはサービス化したいんで
```bash
systemctl edit --full --force wal-g-mongo-dump.service
```
で

```systemd:wal-g-mongo-dump.service
[Unit]
Description = Push mongodump

[Service]
Type = oneshot
User = root
WorkingDirectory = /usr/local/bin
ExecStart = /usr/bin/bash -c '/usr/local/bin/wal-g-mongo.sh backup-push'
ExecStartPost = /usr/bin/bash -c '/usr/local/bin/wal-g-mongo.sh delete --retain-count 7 --confirm'
ExecStartPost = /usr/bin/bash -c '/usr/local/bin/wal-g-mongo.sh oplog-purge --confirm'
```

を入力します。  
手動でこのサービスを実行することでもデータベースのバックアップをオブジェクトストレージに転送できます。  
retain 7で直近７個分のバックアップ保存してます。  
これを定期実行させたいので  

```bash
systemctl edit --full --force wal-g-mongo-dump.timer
```

で

```systemd:wal-g-mongo-dump.timer
[Unit]
Description=Push mongodump Timer

[Timer]
OnCalendar=daily
Persistent=false
RandomizedDelaySec=3600

[Install]
WantedBy=timers.target
```
を入力します。  
毎日だいたい０時に3600秒以内の遅延で実行されます。  

```bash
systemctl enable --now wal-g-mongo-dump.timer
```
でこのタイマーを開始できます。  

実行ログなどに関しては
```bash
systemctl status wal-g-mongo-dump
journalctl -xeu wal-g-mongo-dump
systemctl list-timers
```
であたりで確認します。  

# oplogのアーカイブの設定

oplogをアーカイブしてポイントインリカバリに使えるようにしたいわけです。  
mongoDBにおける`oplog push`はサービスとして実行するのがよさそうです。  

```bash
systemctl edit --full --force wal-g-mongo-oplog.service
```
で

```systemd:wal-g-mongo-oplog.service
[Unit]
Description = Push mongo oplog
Requires = mongod.service

[Service]
Type = simple
User = root
WorkingDirectory = /usr/local/bin
ExecStart = /usr/bin/bash -c '/usr/local/bin/wal-g-mongo.sh oplog-push'
Restart = always

[Install]
WantedBy = multi-user.target
```
を入力してください。  

これはmongoDBが起動した後にサービスとして起動するので、

```bash
systemctl enable --now wal-g-mongo-oplog.service
```
でサービスを自動起動・開始してください。  

```bash
systemctl status wal-g-mongo-oplog.service
journalctl -xeu wal-g-mongo-oplog.service
```
で正常に動いてるか見てみましょう。