DigitalOceanSpacesへのスケジュールされたMongoDBバックアップを設定する方法
序章
定期的なデータベースのバックアップは、意図しないデータ損失イベントを防ぐための重要なステップです。 一般に、バックアップには、ファイルシステムレベル(「物理」)バックアップと論理バックアップの2つの大きなカテゴリがあります。
ファイルシステムレベルのバックアップには、ある時点で基になるデータファイルのスナップショットを作成し、スナップショットされたファイルにキャプチャされた状態を使用してデータベースをクリーンに回復できるようにすることが含まれます。 これらは、特に LVMスナップショットなどのファイルシステムスナップショット、または DigitalOceanブロックストレージスナップショットなどのブロックストレージボリュームスナップショットと組み合わせて使用する場合に、大規模なデータベースを迅速にバックアップするのに役立ちます。
論理バックアップには、ツールの使用が含まれます(例: mongodump
またはpg_dump
)を使用して、データベースからバックアップファイルにデータをエクスポートします。バックアップファイルは、対応する復元ツール(例: mongorestore
またはpg_restore
)。 これらは、バックアップおよび復元するデータをきめ細かく制御し、バックアップは多くの場合、データベースのバージョンやインストール間で移植可能です。 論理バックアップツールは、メモリを介してバックアップされているすべてのデータを読み取るため、速度が遅くなり、特に大規模なデータベースでは重要な追加の負荷が発生する可能性があります。
効果的なバックアップおよびリカバリ戦略の設計には、多くの場合、パフォーマンスへの影響、実装コスト、およびデータストレージコストと、リカバリ速度、データ整合性、およびバックアップカバレッジとのトレードオフが含まれます。 最適なソリューションは、リカバリポイントと時間目的およびデータベースの規模とアーキテクチャによって異なります。
このガイドでは、組み込みの論理バックアップツールであるmongodump
を使用してMongoDBデータベースをバックアップする方法を示します。 次に、結果のシリアル化されたデータバックアップファイルを圧縮して、冗長性の高いオブジェクトストアである DigitalOceanSpacesにアップロードする方法を示します。 また、Bashとcron
を使用してバックアップとアップロードの操作を定期的にスケジュールする方法を示し、最後にサンプルのデータ回復シナリオで締めくくります。
このチュートリアルの終わりまでに、アプリケーションがデータ損失に見舞われた場合に迅速に回復できるようにする、拡張可能な自動バックアップ戦略のフレームワークを実装しました。 小規模から中規模のデータベースの場合、mongodump
を使用した論理バックアップにより、バックアップおよびリカバリするデータをきめ細かく制御できます。 これらの圧縮されたバックアップアーカイブをDigitalOceanSpacesに保存すると、耐久性のあるオブジェクトストアですぐに利用できるようになり、データ損失イベントが発生した場合にアプリケーションデータが保護されて迅速に回復できるようになります。
注: mongodump
ツールを使用すると、特に負荷の高いデータベースでパフォーマンスに影響が出る可能性があります。 最初に、シミュレートされた負荷のある非本番データベースを使用してこの手順をテストし、この方法が本番デプロイメントで機能することを確認する必要があります。
前提条件
このガイドを開始する前に、次の前提条件が利用可能であることを確認してください。
- Ubuntu 16.04を使用したサーバーの初期設定で詳しく説明されている、sudo権限を持つ非rootユーザーのUbuntu16.04ドロップレット
- Ubuntu 16.04にMongoDBをインストールする方法で詳しく説明されている、実行中のMongoDB3.2以降のインストール
- DigitalOceanスペースとAPIキーの作成方法で詳しく説明されているDigitalOceanスペースとAPIクレデンシャルのセット。
s3cmd
コマンドラインファイル転送クライアント(2.X)は、LogrotateおよびS3cmdを使用してログをUbuntu16.04のオブジェクトストレージにアーカイブする方法のステップ1で詳しく説明されています。- DigitalOceanスペースを管理するためのs3cmd2.xの構成方法で詳しく説明されているように、スペースにアクセスするように構成された
s3cmd
Dropletにログインし、MongoDBを起動して実行し、Spaceを作成したら、開始する準備が整います。
ステップ1—テストデータを挿入する
クリーンなMongoDBインストールから開始し、まだデータを保存していない場合は、テスト目的で、最初にいくつかのサンプルデータをダミーのrestaurants
コレクションに挿入する必要があります。 データベースにすでにいくつかのコレクションとドキュメントが保存されている場合は、この手順をスキップして、手順2に進んでください。
まず、MongoDBシェルを使用して実行中のデータベースに接続します。
mongo
次のMongoシェルプロンプトが表示されます。
MongoDB shell version: 3.2.19
connecting to: test
Welcome to the MongoDB shell.
For interactive help, type "help".
For more comprehensive documentation, see
http://docs.mongodb.org/
Questions? Try the support group
http://groups.google.com/group/mongodb-user
Server has startup warnings:
2018-04-11T20:30:57.320+0000 I CONTROL [initandlisten]
2018-04-11T20:30:57.320+0000 I CONTROL [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/defrag is 'always'.
2018-04-11T20:30:57.320+0000 I CONTROL [initandlisten] ** We suggest setting it to 'never'
2018-04-11T20:30:57.320+0000 I CONTROL [initandlisten]
>
デフォルトでは、シェルはtest
データベースに接続します。
test
データベースに存在するコレクションをリストしてみましょう。
- show collections
データベースにはまだ何も挿入していないため、コレクションはなく、出力なしでプロンプトに戻ります。
ダミーのrestaurants
コレクションにドキュメントを挿入してみましょう。このコレクションは自動的に作成されます(まだ存在していないため)。
- db.restaurants.insert({'name': 'Pizzeria Sammy'})
次の出力が表示されます。
OutputWriteResult({ "nInserted" : 1 })
これは、挿入操作が成功したことを示しています。
コレクションをもう一度リストしましょう:
show collections
新しく作成されたrestaurants
コレクションが表示されます。
Outputrestaurants
MongoDBシェルを終了するには、CTRL
+D
を押します。
データベースにサンプルデータを保存したので、バックアップする準備が整いました。
ステップ2—mongodump
を使用してMongoDBデータをバックアップする
次に、組み込みのmongodump
ユーティリティを使用して、MongoDBデータベース全体を圧縮アーカイブファイルにバックアップ(または「ダンプ」)します。
まず、backup
という一時ディレクトリを作成して、mongodump
によって作成されたアーカイブを保存しましょう。
- mkdir backup
それでは、このMongoDBインスタンスのtest
データベースをtest_dump.gz
という圧縮アーカイブファイルにバックアップしましょう。 インスタンスに他のデータベースが含まれている場合は、--db
フラグの後にtest
を別のデータベース名に置き換えることができます。 --db
フラグを省略して、MongoDBインスタンスのすべてのデータベースをバックアップすることもできます。
注:次のコマンドは、Mongoシェルではなく
- mongodump --db test --archive=./backup/test_dump.gz --gzip
ここでは、--archive
フラグを使用して、すべてのデータを単一のアーカイブファイル(場所はarchive
パラメーターで指定)に保存することを指定し、--gzip
フラグは、このファイルを圧縮することを指定します。 さらに、オプションで--collection
または--query
フラグを使用して、アーカイブする特定のコレクションまたはクエリを選択できます。 これらのフラグの詳細については、mongodump
ドキュメントを参照してください。
dumpコマンドを実行すると、次の出力が表示されます。
Output2018-04-13T16:29:32.191+0000 writing test.restaurants to archive './backup/test_dump.gz'
2018-04-13T16:29:32.192+0000 done dumping test.restaurants (1 document)
これは、テストデータが正常にダンプされたことを示しています。
次のステップでは、このバックアップアーカイブをオブジェクトストレージにアップロードします。
ステップ3—バックアップアーカイブをDigitalOceanSpacesにアップロードする
このアーカイブをDigitalOceanSpaceにアップロードするには、前提条件でインストールおよび構成したs3cmd
ツールを使用する必要があります。
最初にs3cmd
構成をテストし、バックアップスペースへのアクセスを試みます。 このチュートリアルでは、スペース名としてmongo-backup-demo
を使用しますが、スペースの実際の名前を入力する必要があります。
- s3cmd info s3://mongo-backup-demo/
次の出力が表示されます。
Outputs3://mongo-backup-demo/ (bucket):
Location: nyc3
Payer: BucketOwner
Expiration Rule: none
Policy: none
CORS: none
ACL: 3587522: FULL_CONTROL
これは、接続が成功し、s3cmd
がオブジェクトをスペースに転送できることを示しています。
put
コマンドを使用して、手順2で作成したアーカイブをSpaceに転送しましょう。
- s3cmd put ./backup/test_dump.gz s3://mongo-backup-demo/
ファイル転送の出力が表示されます。
Outputupload: './backup/test_dump.gz' -> 's3://mongo-backup-demo/test_dump.gz' [1 of 1]
297 of 297 100% in 0s 25.28 kB/s done
転送が完了したら、スペースの内容を一覧表示して、ファイルがスペースに正常に転送されたことを確認します。
- s3cmd ls s3://mongo-backup-demo/
バックアップアーカイブファイルが表示されます。
Output2018-04-13 20:39 297 s3://mongo-backup-demo/test_dump.gz
この時点で、test
MongoDBデータベースが正常にバックアップされ、バックアップアーカイブがDigitalOceanSpaceに転送されました。
次のセクションでは、cron
を使用してスケジュールできるように、Bashを使用して上記の手順をスクリプト化する方法について説明します。
ステップ4—バックアップスクリプトを作成してテストする
MongoDBデータベースを圧縮アーカイブファイルにバックアップし、このファイルをSpaceに転送したので、これらの手動手順を1つのBashスクリプトに組み合わせることができます。
バックアップスクリプトを作成する
まず、mongodump
コマンドとs3cmd put
コマンドを組み合わせたスクリプトを作成し、いくつかのログ記録のように、いくつかの追加のベルとホイッスルを追加します(echo
を使用)。
お好みのテキストエディタで空のファイルを開きます(ここではnano
を使用します)。
- nano backup_mongo.sh
次のコードスニペットを貼り付けます。必ず、関連する値を更新して、独自のスペース、データベース、およびファイル名を参照してください。 このファイルをbackup_mongo.sh
と呼びますが、このファイルには任意の名前を付けることができます。 このセクションの最後に完全なスクリプトを見つけることもできます。
このスクリプトを少しずつ見ていきましょう。
#!/bin/bash
set -e
...
ここで、#!/bin/bash
は、スクリプトをBashコードとして解釈するようにシェルに指示します。 set -e
は、スクリプトコマンドのいずれかが失敗した場合、インタプリタにすぐに終了するように指示します。
...
SPACE_NAME=mongo-backup-demo
BACKUP_NAME=$(date +%y%m%d_%H%M%S).gz
DB=test
...
このセクションでは、後で使用する3つの変数を設定します。
SPACE_NAME
:バックアップファイルをアップロードするDigitalOceanスペースの名前BACKUP_NAME
:バックアップアーカイブの名前。 ここでは、基本的な日時文字列に設定します。DB
:スクリプトがバックアップするMongoDBデータベースを指定します。 MongoDBインスタンス全体(すべてのデータベース)をバックアップする場合、この変数は使用されません。
...
date
echo "Backing up MongoDB database to DigitalOcean Space: $SPACE_NAME"
echo "Dumping MongoDB $DB database to compressed archive"
mongodump --db $DB --archive=$HOME/backup/tmp_dump.gz --gzip
echo "Copying compressed archive to DigitalOcean Space: $SPACE_NAME"
s3cmd put $HOME/backup/tmp_dump.gz s3://$SPACE_NAME/$BACKUP_NAME
...
次に、日付と時刻を(ログ記録の目的で)印刷し、上記でテストしたmongodump
コマンドを実行してバックアップを開始します。 バックアップアーカイブをもう一度~/backup/
に保存します。
次に、s3cmd
を使用して、このアーカイブをこれら2つのSPACE_NAME
変数とBACKUP_NAME
変数で指定された場所にコピーします。 たとえば、スペース名がmongo-backup-demo
で、現在の日時が2018/04/12 12:42:21
の場合、バックアップには180412_124221.gz
という名前が付けられ、mongo-backup-demo
スペース。
...
echo "Cleaning up compressed archive"
rm $HOME/backup/tmp_dump.gz
echo 'Backup complete!'
ここでは、バックアップアーカイブをSpaceに正常にコピーしたので、~/backup
ディレクトリから削除します。最終出力は、バックアップが完了したことを示します。
これらすべてのコードスニペットを組み合わせると、完全なスクリプトは次のようになります。
#!/bin/bash
set -e
SPACE_NAME=mongo-backup-demo
BACKUP_NAME=$(date +%y%m%d_%H%M%S).gz
DB=test
date
echo "Backing up MongoDB database to DigitalOcean Space: $SPACE_NAME"
echo "Dumping MongoDB $DB database to compressed archive"
mongodump --db $DB --archive=$HOME/backup/tmp_dump.gz --gzip
echo "Copying compressed archive to DigitalOcean Space: $SPACE_NAME"
s3cmd put $HOME/backup/tmp_dump.gz s3://$SPACE_NAME/$BACKUP_NAME
echo "Cleaning up compressed archive"
rm $HOME/backup/tmp_dump.gz
echo 'Backup complete!'
完了したら、必ずこのファイルを保存してください。
次に、このスクリプトをテストして、すべてのサブコマンドが機能することを検証します。
バックアップスクリプトのテスト
backup_mongo.sh
スクリプトをすばやく実行してみましょう。
まず、スクリプトを実行可能にします。
- chmod +x backup_mongo.sh
次に、スクリプトを実行します。
- ./backup_mongo.sh
次の出力が表示されます。
OutputMon Apr 16 22:20:26 UTC 2018
Backing up MongoDB database to DigitalOcean Space: mongo-backup-demo
Dumping MongoDB test database to compressed archive
2018-04-16T22:20:26.664+0000 writing test.restaurants to archive '/home/sammy/backup/tmp_dump.gz'
2018-04-16T22:20:26.671+0000 done dumping test.restaurants (1 document)
Copying compressed archive to DigitalOcean Space: mongo-backup-demo
upload: '/home/sammy/backup/tmp_dump.gz' -> 's3://mongo-backup-demo/180416_222026.gz' [1 of 1]
297 of 297 100% in 0s 3.47 kB/s done
Cleaning up compressed archive
Backup complete!
バックアップシェルスクリプトが正常に作成され、cron
を使用してスケジュールを設定できるようになりました。
ステップ5—cronを使用して毎日のバックアップをスケジュールする
バックアップスクリプトの夜間実行をスケジュールするには、Unixライクなオペレーティングシステムに組み込まれているジョブスケジューリングユーティリティであるcron
を使用します。
まず、バックアップスクリプトのログを保存するディレクトリを作成します。 次に、バックアップスクリプトをcrontab(cron
の構成ファイル)に追加して、cron
が毎晩実行するようにスケジュールします。 cron
は任意の定期的な頻度をサポートしているため、オプションで毎週または毎月のバックアップをスケジュールできます。
ロギングディレクトリの作成
バックアップスクリプトのログファイルを保存するディレクトリを作成しましょう。 これらのログにより、バックアップスクリプトを定期的にチェックして、すべてが正常であることを確認し、一部のコマンドが失敗した場合にデバッグすることができます。
/var/log
にmongo_backup
サブディレクトリを作成します(通常、ロギングに使用されます)。
- sudo mkdir /var/log/mongo_backup
次に、そのディレクトリをUnixユーザーに書き込み可能にします。 この場合、ユーザー名は sammy ですが、サーバーのsudo権限を持つ関連する非rootユーザー名を使用する必要があります。
- sudo chown sammy:sammy /var/log/mongo_backup
Unixユーザーsammyが/var/log/mongo_backup
に書き込むことができるようになりました。 cronジョブはsammyとして実行されるため、ログファイルをこのディレクトリに書き込むことができます。
スケジュールされたcronジョブを作成しましょう。
cronジョブを作成する
cronジョブを作成するには、「crontab」と呼ばれる、スケジュールされたジョブのリストを含むファイルを編集します。 /etc/crontab
には、ユーザーごとに1つずつ、複数のcrontabがあり、システム全体のcrontabがあることに注意してください。 このチュートリアルでは、ユーザーsammyとしてバックアップスクリプトを実行します。 ユースケースによっては、システム全体のcrontabから実行することを選択できます。
編集のためにcrontabを開きます。
- crontab -e
次のメニューが表示され、好みのテキストエディタを選択できます。
Outputno crontab for sammy - using an empty one
Select an editor. To change later, run 'select-editor'.
1. /bin/ed
2. /bin/nano <---- easiest
3. /usr/bin/vim.basic
4. /usr/bin/vim.tiny
Choose 1-4 [2]: no crontab for sammy - using an empty one
好みのエディターを選択してください。 nano
を選択するには、2
と入力します。 次に、コメントアウトされたセクションに続いて、ファイルに次の行を追加します。
# For more information see the manual pages of crontab(5) and cron(8)
#
# m h dom mon dow command
0 2 * * * /home/sammy/backup_mongo.sh >>/var/log/mongo_backup/mongo_backup.log 2>&1
crontabの最後に必ず末尾の改行を含めてください。 ファイルを保存して閉じます。
次の出力が表示されます。
Outputno crontab for sammy - using an empty one
crontab: installing new crontab
バックアップスクリプトは、毎朝午前2時に実行されます。 stdout
とstderr
(出力ストリームとエラーストリーム)の両方がパイプ処理され、前に作成したログディレクトリのmongo_backup.log
というログファイルに追加されます。
0 2 * * *
(cron構文では毎晩午前2:00に実行)を希望のバックアップ頻度と時間に変更できます。 cronとその構文の詳細については、Cronを使用してVPSでタスクを自動化する方法のチュートリアルを参照してください。
このチュートリアルは、バックアップが機能していることを確認するための簡単な回復演習で締めくくります。
ステップ6—テストリカバリを実行する
バックアップ戦略には、定期的にテストされるリカバリ手順が含まれている必要があります。 ここでは、DigitalOceanスペースにアップロードした圧縮バックアップファイルからの復元を簡単にテストします。
まず、SpaceからMongoDBドロップレットのホームディレクトリにtest_dump.gz
をダウンロードします。
- s3cmd get s3://mongo-backup-demo/test_dump.gz
次の出力が表示されます。
Outputdownload: 's3://mongo-backup-demo/test_dump.gz' -> './test_dump.gz' [1 of 1]
297 of 297 100% in 0s 1305.79 B/s done
このチュートリアルを新しいMongoDBインスタンスで開始した場合、バックアップしたデータベースはtest
データベースのみであったことを思い出してください。
デモンストレーションの目的で、このテストデータベースを削除して、クリーンな復元を実行できるようにします。 この最初の手順を実行しないと、復元手順で元のドキュメントが検出され、スキップされます。 特定のユースケースでは、新しいドキュメントのみを復元することもできますが、このチュートリアルでは、空のデータベースへの完全な復元を明示的にテストしたいと思います。
mongo
シェルを使用してMongoDBインスタンスに接続します。
- mongo
ここで、use
test
データベースを作成し、MongoDBインスタンスから削除します。
- use test
- db.dropDatabase()
test
ドロップを確認する次の出力が表示されます。
Output{ "dropped" : "test", "ok" : 1 }
ここで、mongo
シェルを終了し、mongorestore
コマンドを実行します。
- mongorestore --gzip --archive=test_dump.gz --db test
ここでは、ソースバックアップファイルが圧縮され、「アーカイブファイル」形式であることを指定します(mongodump
を呼び出すときに--archive
および--gzip
フラグを使用したことを思い出してください)。 test
データベースに復元したいと思います。
次の出力が表示されます。
Output2018-04-16T23:10:07.317+0000 creating intents for archive
2018-04-16T23:10:07.453+0000 reading metadata for test.restaurants from archive 'test_dump.gz'
2018-04-16T23:10:07.497+0000 restoring test.restaurants from archive 'test_dump.gz'
2018-04-16T23:10:07.541+0000 restoring indexes for collection test.restaurants from metadata
2018-04-16T23:10:07.541+0000 finished restoring test.restaurants (1 document)
2018-04-16T23:10:07.541+0000 done
これは、test
の復元が成功したことを示しています。
結論として、最初のrestaurants
データが正常に復元されたことを確認しましょう。
MongoDBシェルを開き、restaurants
コレクションにクエリを実行します。
- db.restaurants.find()
このチュートリアルの最初のステップで保存したオブジェクトが表示されます。
Output{ "_id" : ObjectId("5ace7614dbdf8137afe60025"), "name" : "Pizzeria Sammy" }
これで、このMongoDBバックアップ戦略の実装とテストに成功しました。
結論
このチュートリアルでは、夜間の論理MongoDBバックアップの戦略を実装およびテストする方法を学習しました。
このガイドは、さまざまな方法で拡張または変更できます。 ここにいくつかの簡単な提案があります:
- 目標復旧時点(RPO)に応じて、データ復旧ウィンドウに一致するように、推奨されるバックアップ頻度を増減することができます。
- もう1つの便利な追加機能は、バックアップスクリプトサブコマンドが失敗した場合にトリガーされるアラート機能です(例: この機能は、定期的に監視されているアラート受信ボックスに電子メールを送信する可能性があります)。
- このスクリプトは、Spacesオブジェクトの削除を処理しません。 たとえば、6か月ほど前のバックアップをクリーンアップすることをお勧めします。
- 本番ユースケースによっては、より複雑なバックアップローテーションスキームを実装することをお勧めします。
mongodump
の手順では、ダンプされたすべてのデータをすばやく読み取る必要があるため、このバックアップ方法は、中小規模のデータベース、特に特定のコレクションや結果セットなどの部分的なバックアップに最適です。 大規模な展開には、ファイルシステムレベルのバックアップをお勧めします。 ファイルシステムレベルのMongoDBバックアップの詳細については、ドロップレットスナップショットを使用してMongoDBをバックアップする方法に関するこのチュートリアルを参照してください。 MongoDBデータベースをバックアップするさまざまな方法の詳細については、MongoDBマニュアルを参照してください。
このチュートリアルで紹介するソリューションは、mongodump
を活用してバックアップデータのカバレッジをきめ細かく制御し、DigitalOceanSpacesを活用して費用効果が高く耐久性のある長期データストレージを実現します。 mongodump
バックアップユーティリティの詳細については、MongoDBマニュアルのリファレンスページを参照してください。 DigitalOcean Spacesの詳細については、DigitalOceanSpacesの概要を参照してください。