サーバのバックアップ

先日自宅サーバの障害復旧で面倒な目に遭ってしまったので、色々と見直し。。。


まずサーバのバックアップ

反省。定期的に取りましょう(^^; 少なくともバージョンアップ前には・・・

  • ディザスタリカバリ:無し→Acronisでイメージバックアップ(外付けHDDにバックアップ)
LVMだったのでスナップショットに頼り切っていて、バックアップを怠っていたので
  • ファイルシステム:LVM→Ext3
Acronisでイメージバックアップが取れるようにExt3を使用することに
  • スナップショット:LVMスナップショット→cronとdumpとtarで地味にバックアップ
ということで、スナップショットは便利だけど捨てて、地味に昔ながらのファイルバックアップを行う事に。

Acronis True Image Home (面倒臭くて2009しかインストールしてなかったのだけど、Home2010のライセンスは買ってあったので)なんて久しぶりに使ったのだけど、簡単にUSBブート出来るようになってたりしていて、地味に便利になっている。

あと、スナップショットは便利だけど、スクリプト組んでファイルバックアップを行う方法は昔ながらのノウハウで色々出来て楽っちゃ楽。

バックアップだけをみると、MacOSXのTime MachineはGUIで簡単にスナップショットから好きなファイルだけ抜いてこれる上、ディザスタリカバリにも対応できる点が良いかな。Windows7の標準バックアップも賢いようだけどまだ使ってみてない。地味にWindows2008のServer BackupはディザスタリカバリにDVDからの復旧が使えるようになってたり良くなってる。何にせよ問題になるのがデータベースのバックアップ。スナップショットだろうとファイルでバックアップを行う方法だろうと、データベースの不整合から逃れる術は無くて、結局データベースの停止を行ってダンプしてファイルにバックアップするか、オープン中のファイルをバックアップできるソリューションを使う必要が有るのだけど。


データベース(MySQL)のバックアップ

結局完全なバックアップは難しいのでファイルへのダンプと、データベースのクラスタを併用することに。
  • ファイルへのダンプ
mysqldumpでフルダンプ。テキストファイルに吐き出しておく。

/usr/bin/mysqldump -x -A -u データベースのユーザ --password='パスワード' --opt > /var/db-backup/DB-dump.`/bin/date +'%Y%M%d%k%M'`
gzip /var/db-backup/DB-dump.`/bin/date +'%Y%M%d%k%M'`

とか、そんな感じのシェルスクリプトを作ってcronで定時実行する。

  • MySQLのレプリケート
まずマスターサーバ側でネットワークソケットを空けたり、bin-log取ったりと、クラスタ化の準備。

/etc/mysql/my.cnfに
[server]
server-id        = 1
log-bin
を追記。

データベースに設定を反映させるために再起動する
(Slave)# sudo service mysql restart

レプリケート用にREPLICATION SLAVE権限を与えたユーザを作っておく。
mysql(Master)> GRANT REPLICATION SLAVE ON *.* TO repl@10.0.0.2 IDENTIFIED BY 'password';
データベースの更新をストップして
mysql(Master)> FLUSH TABLES WITH READ LOCK;
バイナリログを確認(スレーブで同期させるときに必要な情報)
mysql(Master)> SHOW MASTER STATUS;
+-----------------+----------+--------------+------------------+
| File            | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+-----------------+----------+--------------+------------------+
| dbsv-bin.000001 |       79 |              |                  |
+-----------------+----------+--------------+------------------+
1 row in set (0.00 sec)

スレーブ側にコピーする為にデータベースのダンプを取る
(Master)# tar zcf backupfile.tar.gz /var/lib/mysql/
(取ったファイルはスレーブ機にコピーする)
ファイルが取れたのでデータベースの更新を許可
mysql(Master)> UNLOCK TABLES;

別のホストでスレーブサーバを立てて、レプリケートを行う。

データベースを停止して
(Slave)# sudo service mysql stop

スレーブの設定を記述する
/etc/mysql/my.cnfに
[server]
server-id        = 2
を追記。

データベースに設定を反映させるために再起動する
(Slave)# sudo service mysql restart

マスターで採取したファイルを解凍&展開
(Slave)# cd /
(Slave)# tar zxf backupfile.tar.gz

データベースを動作させて
(Slave)# sudo service mysql start

マスターとの同期情報を設定して
mysql(Slave)> CHANGE MASTER TO
MASTER_HOST='10.0.0.1',  ← マスターのホスト名/IPアドレス
MASTER_USER='repl', ← マスター接続に使用するユーザー名 MASTER_PASSWORD='password', ← パスワード MASTER_LOG_FILE='dbsv-bin.000001', ← さっきマスターで確認したファイル MASTER_LOG_POS=79; ← さっきマスターで確認した位置

同期を開始させる
mysql(Slave)> START SLAVE;

こんな感じでMySQLのファイルダンプと、MySQLのレプリケーションを設定した。
レプリケーションは冗長目的なので、あくまで受け身の同期でしかない。selectとかの検索系のクエリは使えるけど、insertとかupdateとかの更新系のクエリは使えない(というかマスターに反映しない)。けど、必要が有ればスレーブ側のデータベースを停止させればデータベースのフルバックアップが取れるし、スレーブ側のデータベースを再開させれば、またマスターとの同期が行われる。
検索系のクエリを分散させれば、一応データベースの負荷分散にもなるのだけど、そもそも負荷の問題は無いし、目的が違うので気にしない。
MySQLのレプリケーションについては公式サイトにある情報(http://dev.mysql.com/doc/refman/5.1/ja/replication.html)で必要な情報は揃えられる。SQL ServerであればMSDN(http://msdn.microsoft.com/ja-jp/library/ms187048.aspx)か?

という事で、やっとデータのバックアップとかするようになりました。