EC2でEBS上のMySQLのデータをバックアップ
こんにちは。フレクトの大橋です。
ベターホームレシピ(http://bhmb.jp)では、MySQLを会員やレシピデータ用の
インスタンスと、Cicindela用のインスタンスを同一のサーバにそれぞれ
データをEBSに置いて運用しています。
レプリケーションなど信頼性向上のための施策をしているのですが、
運用上大事なのはバックアップです。
そこで、今日はEBS上のMySQLのデータのスナップショットを
整合性を失わずにバックアップする方法についてベターホームレシピでの
実運用の事例をもとに紹介します。
■ 本題の前に・・・、Amazon RDSについて
そもそも直接MySQLをEC2上にインストールしなくても、日々機能が強化されている
Amazon RDSを使えばよいのではないか、という考えもあります。はい、その通りです。
特に最近はMulti-AZ機能なども提供され、安心感があります。
ただ、ベターホームレシピを検討していたときには、RDSは冗長化機能が弱い、
バックアップでIOフリーズがあったりする、など現在より課題も多かったので
EC2上で自前運用としました。
また、運用にかけられる予算が少なかったので、EC2とは別に複数のインスタンスでの
RDSの費用が発生するのが嫌だったというのもあります。
RDSを選ぶかは、みなさまの環境によると思います。
■ EBS上にMySQLデータを置いて動かす
では、EC2上で自前でMySQLを運用する場合について進めます。
普通にインストールすると、EC2のローカルストレージにデータを置くことになりますが、
EC2のインスタンスが落ちた場合、データ消えてしまうので怖いです。
したがって、MySQLのプログラム自体はEC2のローカルストレージでも
いいのですが、データディレクトリはEBS上に置くことにします。
肝心の方法ですが、以下に書いてある通りですんなりできます。
http://d.hatena.ne.jp/shibataism/20080822/1219422913
http://developer.amazonwebservices.com/connect/entry.jspa?externalID=1663&categoryID=100
■ ファイルシステムは xfs
ポイントはファイルシステムをxfsで作ることできます。
xfsはファイルシステムのフリーズフリーズ解除(freeze/thaw)機能があり、
EBSスナップショット取得中に書き込みをロックすることができ、
一貫性を持ったファイルシステムのスナップショット取得ができます。
freezeのコマンドはシェルからできるので、運用上、自動化することもでき、
今回の用途にはよいです。なので、以下に続く例もxfsにします。
■ 手動でフリーズ、スナップショット取得を実行してみる
前提としてmysqlのデータファイルは
/vol/****/mysql/data
にあるものとします。(****は当社の場合はプロジェクト名です)
手順は以下の順番です。
(1) MySQLのデータをFLUSHし、READロックをかけます。つまり、書き込みできないようにします。これでDBへの書き込みはできなくなります。
(2) xfs_freezeコマンドでファイルシステムを凍結。ファイルシステムに書き込みをできなくすると同時に、ファイルシステム上のキャッシュやメタデータなどをディスクに書き込んでしまいます。
(3) EBSのスナップショットを取得する。
(4) xfsの凍結を解除します。ec2-create-snapshotでできます。
(5) MySQLのロックを解除します。
DBやファイルシステムの状態が不整合を起こさないようにする工夫は(1)、(2)です。
(1)でMySQLのキャッシュのデータをFLUSHし、全部ディスクに退避させ、その上でREADロックです。
これでMySQLに追加書き込みはできません。その上で(2)を実施して、ファイルシステムに書き込みできなくします。
ディスクに追加書き込みできなくしてからEBSのスナップショット取得、そしてロックを順次解除していきます。具体的には以下のようにmysqlのコンソールに入ってコマンドを実行していくとできます。
----------------------------
# mysql -u root --password=xxxx --port=xxxx --host=xxx.xxx.xxx.xxx # mysqlのコンソールへ。
mysql >FLUSH TABLES WITH READ LOCK; # (1)MySQLをロック
mysql >SYSTEM xfs_freeze -f /vol # (2)ファイルシステムをロック
mysql >SYSTEM ec2-create-snapshot -d xxxxx vol-xxxxxx # (3)EBSのスナップショット
mysql >SYSTEM xfs_freeze -u /vol # (4)ファイルシステムのロック解除
mysql >UNLOCK TABLES; # (5)MySQLのアンロック
----------------------------
■ バックアップのプロセスを自動化する
上記のプロセスをスクリプトで自動化しておくと、定期的なスナップショット
取得ができて便利です。以下に簡単なPerlでのスクリプト例も書いておきます。
なお、xfsを使わない場合も想定して、xfs_freezeの前にsyncを入れていますが、
それ以外は上記のプロセスの自動化となっています。
#!/usr/bin/env perl use strict; use warnings; use DBI; my $use_xfs = 1; my $xfs_mount_point = '/vol'; my $use_mysql = 1; my $mysql_username = 'xxxx'; my $mysql_password = 'xxxx'; my $mysql_host = 'xxx.xxx.xxx.xxx'; my $mysql_port = 3306; my $mysql_dsn = [ "DBI:mysql:;host=$mysql_host;$mysql_port", $mysql_username, $mysql_password ]; my $dbh = undef; # connect and lock mysql if ($use_mysql) { $dbh = connect_db($mysql_dsn); flush_tables_with_read_lock($dbh); } # commit buffer to disk run_command( ['sync'] ); # freeze file system if ($use_xfs) { run_command( [ 'xfs_freeze', '-f', $xfs_mount_point ] ); } # snapshot ebs run_command( [ 'ec2-create-snapshot', '-d', 'xxxxxx', 'vol-xxxxx' ] ); # thaw file system if ($use_xfs) { run_command( [ 'xfs_freeze', '-u', $xfs_mount_point ] ); } # unlock and disconnect if ($use_mysql) { unlock_tables($dbh); disconnect_db($dbh); } exit 0; sub run_command { my ($command) = @_; eval { system(@$command) and die "failed($?)\n"; }; warn "ERROR: @$command: $@" if $@; } sub connect_db { my $dsn = shift; my $dbh = DBI->connect(@$dsn) or die "cannot connect database " . $!; return $dbh; } sub disconnect_db { my $dbh = shift; $dbh->disconnect(); } sub flush_tables_with_read_lock { my $dbh = shift; $dbh->do('FLUSH TABLES WITH READ LOCK;') or die $dbh->errstr; } sub unlock_tables { my $dbh = shift; $dbh->do('UNLOCK TABLES; ') or die $dbh->errstr; }
■ 注意点、制限事項など
ベターホームレシピで運用しているときはだいたい1回5秒くらいかかります。
特にEBSスナップショットに時間がかかります。その間、書き込みがブロックされるので
注意が必要です。書き込みに待ちが発生してもよい環境(スレーブ環境)などで取得するか、
マスタ環境で取得する場合は、書き込みブロックが許容できる環境で実施するのが
よいと思います。
なお、EBSスナップショットの取得はec2-create-snapshotコマンドではなく、APIを直接
たたけばもう少し高速になるはずです。それはまた今度実施してみます。
あと今回はxfsにしましたが、ext3,ext4など他のファイルシステムでもxfs_freeze的なことが
できるのかは、ちょっと調べましたが、見当たりませんでした。できるのかもしれませんが、
他のファイルシステムでもこういったバックアップ運用ができるのか、今後調べてみたいです。
■ 参考資料
今回の記事は以下の記事をもとに作りました。
・EBSでMySQLのスナップショットを取るための手順等の資料等
http://developer.amazonwebservices.com/connect/entry.jspa?externalID=1663&categoryID=100
http://alestic.com/2009/09/ec2-consistent-snapshot
■ まとめ
このような手順を踏めば、定期的に整合性の取れた状態でスナップショットを
作っておけて便利です。今度はリストアの方法なども記載したいです。
フレクトではEC2を使ったインフラ運用に興味のあるエンジニアを
募集しています。興味のある方は以下からご連絡ください。
http://www.flect.co.jp/recruit/index.html
ありがたくスクリプトを参考にさせていただきます。
> ext3,ext4など他のファイルシステムでもxfs_freeze的なこと
は、xfsutil-linux-ng2.18 からの fsfreeze で対応できませんでしょうか。
いま手元の環境は、2.17.2 なので、確認できないのですが。
投稿: ひさやん | 2011年2月18日 (金) 14:06
初めまして、結構前の記事への指摘で申し訳ありません。
mysql >SYSTEM UNLOCK TABLES; # (5)MySQLのアンロック
ですが
mysql >UNLOCK TABLES;
の打ち間違いかと思います。
投稿: くにきや | 2012年3月28日 (水) 07:12
>くにきやさん
初めまして。
コメントありがとうございます。
たしかにそうですね。以下に修正しました。
mysql >UNLOCK TABLES;
ありがとうございます。
投稿: 大橋 正興 | 2012年3月28日 (水) 09:28