序章

定期的なデータベースのバックアップは、意図しないデータ損失イベントを防ぐための重要なステップです。 一般に、バックアップには、ファイルシステムレベル(「物理」)バックアップと論理バックアップの2つの大きなカテゴリがあります。

ファイルシステムレベルのバックアップには、ある時点で基になるデータファイルのスナップショットを作成し、スナップショットされたファイルにキャプチャされた状態を使用してデータベースをクリーンに回復できるようにすることが含まれます。 これらは、特に LVMスナップショットなどのファイルシステムスナップショット、または DigitalOceanブロックストレージスナップショットなどのブロックストレージボリュームスナップショットと組み合わせて使用する場合に、大規模なデータベースを迅速にバックアップするのに役立ちます。

論理バックアップには、ツールの使用が含まれます(例: mongodumpまたはpg_dump)を使用して、データベースからバックアップファイルにデータをエクスポートします。バックアップファイルは、対応する復元ツール(例: mongorestoreまたはpg_restore)。 これらは、バックアップおよび復元するデータをきめ細かく制御し、バックアップは多くの場合、データベースのバージョンやインストール間で移植可能です。 論理バックアップツールは、メモリを介してバックアップされているすべてのデータを読み取るため、速度が遅くなり、特に大規模なデータベースでは重要な追加の負荷が発生する可能性があります。

効果的なバックアップおよびリカバリ戦略の設計には、多くの場合、パフォーマンスへの影響、実装コスト、およびデータストレージコストと、リカバリ速度、データ整合性、およびバックアップカバレッジとのトレードオフが含まれます。 最適なソリューションは、リカバリポイントと時間目的およびデータベースの規模とアーキテクチャによって異なります。

このガイドでは、組み込みの論理バックアップツールであるmongodumpを使用してMongoDBデータベースをバックアップする方法を示します。 次に、結果のシリアル化されたデータバックアップファイルを圧縮して、冗長性の高いオブジェクトストアである DigitalOceanSpacesにアップロードする方法を示します。 また、Bashとcronを使用してバックアップとアップロードの操作を定期的にスケジュールする方法を示し、最後にサンプルのデータ回復シナリオで締めくくります。

このチュートリアルの終わりまでに、アプリケーションがデータ損失に見舞われた場合に迅速に回復できるようにする、拡張可能な自動バックアップ戦略のフレームワークを実装しました。 小規模から中規模のデータベースの場合、mongodumpを使用した論理バックアップにより、バックアップおよびリカバリするデータをきめ細かく制御できます。 これらの圧縮されたバックアップアーカイブをDigitalOceanSpacesに保存すると、耐久性のあるオブジェクトストアですぐに利用できるようになり、データ損失イベントが発生した場合にアプリケーションデータが保護されて迅速に回復できるようになります。

注: mongodumpツールを使用すると、特に負荷の高いデータベースでパフォーマンスに影響が出る可能性があります。 最初に、シミュレートされた負荷のある非本番データベースを使用してこの手順をテストし、この方法が本番デプロイメントで機能することを確認する必要があります。

前提条件

このガイドを開始する前に、次の前提条件が利用可能であることを確認してください。

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データベースに存在するコレクションをリストしてみましょう。

  1. show collections

データベースにはまだ何も挿入していないため、コレクションはなく、出力なしでプロンプトに戻ります。

ダミーのrestaurantsコレクションにドキュメントを挿入してみましょう。このコレクションは自動的に作成されます(まだ存在していないため)。

  1. db.restaurants.insert({'name': 'Pizzeria Sammy'})

次の出力が表示されます。

Output
WriteResult({ "nInserted" : 1 })

これは、挿入操作が成功したことを示しています。

コレクションをもう一度リストしましょう:

show collections

新しく作成されたrestaurantsコレクションが表示されます。

Output
restaurants

MongoDBシェルを終了するには、CTRL +Dを押します。

データベースにサンプルデータを保存したので、バックアップする準備が整いました。

ステップ2—mongodumpを使用してMongoDBデータをバックアップする

次に、組み込みのmongodumpユーティリティを使用して、MongoDBデータベース全体を圧縮アーカイブファイルにバックアップ(または「ダンプ」)します。

まず、backupという一時ディレクトリを作成して、mongodumpによって作成されたアーカイブを保存しましょう。

  1. mkdir backup

それでは、このMongoDBインスタンスのtestデータベースをtest_dump.gzという圧縮アーカイブファイルにバックアップしましょう。 インスタンスに他のデータベースが含まれている場合は、--dbフラグの後にtestを別のデータベース名に置き換えることができます。 --dbフラグを省略して、MongoDBインスタンスのすべてのデータベースをバックアップすることもできます。

注:次のコマンドは、Mongoシェルではなくターミナルから実行する必要があります。

  1. mongodump --db test --archive=./backup/test_dump.gz --gzip

ここでは、--archiveフラグを使用して、すべてのデータを単一のアーカイブファイル(場所はarchiveパラメーターで指定)に保存することを指定し、--gzipフラグは、このファイルを圧縮することを指定します。 さらに、オプションで--collectionまたは--queryフラグを使用して、アーカイブする特定のコレクションまたはクエリを選択できます。 これらのフラグの詳細については、mongodumpドキュメントを参照してください。

dumpコマンドを実行すると、次の出力が表示されます。

Output
2018-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を使用しますが、スペースの実際の名前を入力する必要があります。

  1. s3cmd info s3://mongo-backup-demo/

次の出力が表示されます。

Output
s3://mongo-backup-demo/ (bucket): Location: nyc3 Payer: BucketOwner Expiration Rule: none Policy: none CORS: none ACL: 3587522: FULL_CONTROL

これは、接続が成功し、s3cmdがオブジェクトをスペースに転送できることを示しています。

putコマンドを使用して、手順2で作成したアーカイブをSpaceに転送しましょう。

  1. s3cmd put ./backup/test_dump.gz s3://mongo-backup-demo/

ファイル転送の出力が表示されます。

Output
upload: './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

転送が完了したら、スペースの内容を一覧表示して、ファイルがスペースに正常に転送されたことを確認します。

  1. s3cmd ls s3://mongo-backup-demo/

バックアップアーカイブファイルが表示されます。

Output
2018-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を使用します)。

  1. nano backup_mongo.sh

次のコードスニペットを貼り付けます。必ず、関連する値を更新して、独自のスペース、データベース、およびファイル名を参照してください。 このファイルをbackup_mongo.shと呼びますが、このファイルには任意の名前を付けることができます。 このセクションの最後に完全なスクリプトを見つけることもできます。

このスクリプトを少しずつ見ていきましょう。

backup_mongo.sh
#!/bin/bash

set -e
...

ここで、#!/bin/bashは、スクリプトをBashコードとして解釈するようにシェルに指示します。 set -eは、スクリプトコマンドのいずれかが失敗した場合、インタプリタにすぐに終了するように指示します。

backup_mongo.sh
...

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インスタンス全体(すべてのデータベース)をバックアップする場合、この変数は使用されません。
backup_mongo.sh
...

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スペース。

backup_mongo.sh
...

echo "Cleaning up compressed archive"
rm $HOME/backup/tmp_dump.gz

echo 'Backup complete!'

ここでは、バックアップアーカイブをSpaceに正常にコピーしたので、~/backupディレクトリから削除します。最終出力は、バックアップが完了したことを示します。

これらすべてのコードスニペットを組み合わせると、完全なスクリプトは次のようになります。

backup_mongo.sh
#!/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スクリプトをすばやく実行してみましょう。

まず、スクリプトを実行可能にします。

  1. chmod +x backup_mongo.sh

次に、スクリプトを実行します。

  1. ./backup_mongo.sh

次の出力が表示されます。

Output
Mon 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/logmongo_backupサブディレクトリを作成します(通常、ロギングに使用されます)。

  1. sudo mkdir /var/log/mongo_backup

次に、そのディレクトリをUnixユーザーに書き込み可能にします。 この場合、ユーザー名は sammy ですが、サーバーのsudo権限を持つ関連する非rootユーザー名を使用する必要があります。

  1. 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を開きます。

  1. crontab -e

次のメニューが表示され、好みのテキストエディタを選択できます。

Output
no 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と入力します。 次に、コメントアウトされたセクションに続いて、ファイルに次の行を追加します。

crontab -e
# 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の最後に必ず末尾の改行を含めてください。 ファイルを保存して閉じます。

次の出力が表示されます。

Output
no crontab for sammy - using an empty one crontab: installing new crontab

バックアップスクリプトは、毎朝午前2時に実行されます。 stdoutstderr(出力ストリームとエラーストリーム)の両方がパイプ処理され、前に作成したログディレクトリのmongo_backup.logというログファイルに追加されます。

0 2 * * * (cron構文では毎晩午前2:00に実行)を希望のバックアップ頻度と時間に変更できます。 cronとその構文の詳細については、Cronを使用してVPSでタスクを自動化する方法のチュートリアルを参照してください。

このチュートリアルは、バックアップが機能していることを確認するための簡単な回復演習で締めくくります。

ステップ6—テストリカバリを実行する

バックアップ戦略には、定期的にテストされるリカバリ手順が含まれている必要があります。 ここでは、DigitalOceanスペースにアップロードした圧縮バックアップファイルからの復元を簡単にテストします。

まず、SpaceからMongoDBドロップレットのホームディレクトリにtest_dump.gzをダウンロードします。

  1. s3cmd get s3://mongo-backup-demo/test_dump.gz

次の出力が表示されます。

Output
download: '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インスタンスに接続します。

  1. mongo

ここで、use testデータベースを作成し、MongoDBインスタンスから削除します。

  1. use test
  2. db.dropDatabase()

testドロップを確認する次の出力が表示されます。

Output
{ "dropped" : "test", "ok" : 1 }

ここで、mongoシェルを終了し、mongorestoreコマンドを実行します。

  1. mongorestore --gzip --archive=test_dump.gz --db test

ここでは、ソースバックアップファイルが圧縮され、「アーカイブファイル」形式であることを指定します(mongodumpを呼び出すときに--archiveおよび--gzipフラグを使用したことを思い出してください)。 testデータベースに復元したいと思います。

次の出力が表示されます。

Output
2018-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コレクションにクエリを実行します。

  1. 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の概要を参照してください。