2008-07-22

MogileFS のために MySQL の NDB Cluster を動かす

はてなブックマーク   livedoor clip

お久しぶりです、日野原です。引き続き MogileFS の話題です。

と言っても前回の続きで開発環境上での話ではなく、サーバに MogileFS を入れていこうと言う話になります。

そこで MogileFS についてちゃんと調べ始めると、「Learning MogileFS」という資料の「mysql database cluster」のところになんと「その名の通りNDB Cluster推奨」と書いてあるではありませんか。

というわけで今回は MySQL の NDB Cluster を 3 台の CentOS 5.2 のマシンにセットアップします。NDB Cluster 自体の説明はThink ITの記事などいろいろとあるので、参考にしてください。
インストールにはrpm 形式で配布されているバイナリを使います。(CentOS 5.2 なので Red Hat Enterprise Linux 5 用の RPM をダウンロードします。記事中ではダウンロードの部分は省略します。)

配布されているページに行くとバージョン番号が MySQL Cluster 6.2.15 となっていて面食らいますが、管理ツールの出力によると MySQL 自体は 5.1.23 で、その上に ndb の 6.2.15 が載っているようです。

今回の構成では、クラスタの 3 種類のノードは以下のように構成します。

3台のマシンのホスト名は srv[1-3] 、IPは 192.168.10.[1-3] とします。そして srv1 上で管理ノード(ndb_mgmd)、srv2 と srv3 上で SQLノード(mysqld)とデータノード(ndbd)を動かします。

この構成だと管理ノードが単一故障点になってしまっていますが、ここを複数構成にするための説明はまだ見つかっていないので今後の課題とさせてください。

それでは実際にインストール作業を始めていきます。
ちなみに、今回のサーバはちゃんと識者に CPAN が使えるようにしてもらってあるので、perl のモジュールのインストールは yum ではなく CPAN から行います。

まずは管理ノードです。
管理ノードに必要なのは以下の3つです。

  • perl の Class::MethodMaker モジュール
  • MySQL-Cluster-gpl-management-6.2.15-0.rhel5.i386.rpm
  • MySQL-Cluster-gpl-tools-6.2.15-0.rhel5.i386.rpm

これらを srv1 にインストールします。

% sudo cpan -i Class::MethodMaker
% sudo rpm -ivh MySQL-Cluster-gpl-management-6.2.15-0.rhel5.i386.rpm
% sudo rpm -ivh MySQL-Cluster-gpl-tools-6.2.15-0.rhel5.i386.rpm

次に設定ファイルを作成します。今回は設定ファイルは /var/lib/mysql-cluster/config.ini という名前で配置します。また、管理ノードは mysql というユーザで起動しますので、ユーザを作成しておいてください。

% sudo /usr/sbin/useradd mysql -d /var/lib/mysql-cluster
% cd /var/lib
% sudo mkdir mysql-cluster
% sudo chown mysql:mysql mysql-cluster
% cd mysql-cluster
% sudo vim config.ini
% cat config.ini
[NDBD DEFAULT]
NoOfReplicas = 2
DataDir = /var/lib/mysql-cluster
ServerPort = 63132[MGM]
Id = 1
HostName = 192.168.10.1
DataDir = /var/lib/mysql-cluster

[NDBD]
Id = 11
HostName = 192.168.10.2

[NDBD]
Id = 12
HostName = 192.168.10.3

[MYSQLD]
Id = 21
HostName = 192.168.10.2

[MYSQLD]
Id = 22
HostName = 192.168.10.3

ここで、NDBD DEFAULT セクションの最後の ServerPort がはまりどころです。
オフィシャルのドキュメントを見ると「旧式」となっており、「デフォルトのポートは同じコンピュータ上の 2 つのノードが同じポート番号を受信しないようにダイナミックに割り当てられているため、通常このパラメータの値を指定する必要はありません。」とあるのですが、これを指定しておかないとファイアーウォールに阻まれて通信がうまくいきません。ひょっとしたら将来のバージョンでは不要になるかもしれませんが、今回インストールしたバージョンでは必要です。
具体的には、データノードから管理ノードに一見ちゃんと接続されているように見えているのに接続されておらず、SQLノードが管理ノードに接続できないという現象が起こります。
私はこれで2日つぶしました。

そのほかのオプションについてはオフィシャルのドキュメントを見てください。基本的な設定例等を見ればわかると思います。

設定ファイルができたら管理ノードにアクセスするためのポートを開けます。

% sudo /usr/sbin/lokkit

デフォルトのポートの 1186 は CentOS 5.2 では /etc/services に書いてあるので、カスタマイズのボタンから「その他のポート」に「mysql-cluster:tcp」を追加します。

そして、管理ノードを起動します。

% sudo -u mysql /usr/sbin/ndb_mgmd -f /var/lib/mysql-cluster/config.ini

起動したら、管理クライアントを起動して show コマンドで状況を確認してみましょう。

% ndb_mgm
-- NDB Cluster -- Management Client --
ndb_mgm> show
Connected to Management Server at: localhost:1186
Cluster Configuration
---------------------
[ndbd(NDB)]     2 node(s)
id=11 (not connected, accepting connect from 192.168.10.2)
id=12 (not connected, accepting connect from 192.168.10.3)

[ndb_mgmd(MGM)] 1 node(s)
id=1    @192.168.10.1  (mysql-5.1.23 ndb-6.2.15)

[mysqld(API)]   2 node(s)
id=21 (not connected, accepting connect from 192.168.10.2)
id=22 (not connected, accepting connect from 192.168.10.3)

これで管理ノードの準備はOKです。

次にデータノードとSQLノードの設定をしますが、これは srv2 と srv3 の両方に対して実行します。以下では srv2 に対して実行しているものとして解説しますが、srv3 に対しても実行してください。

まず、最低限必要なのは以下の4つです。

  • perl の DBI モジュール
  • MySQL-Cluster-gpl-client-6.2.15-0.rhel5.i386.rpm
  • MySQL-Cluster-gpl-storage-6.2.15-0.rhel5.i386.rpm
  • MySQL-Cluster-gpl-server-6.2.15-0.rhel5.i386.rpm

これらを順にインストールします。

% sudo cpan -i DBI
% sudo rpm -ivh MySQL-Cluster-gpl-client-6.2.15-0.rhel5.i386.rpm
% sudo rpm -ivh MySQL-Cluster-gpl-storage-6.2.15-0.rhel5.i386.rpm
% sudo rpm -ivh MySQL-Cluster-gpl-server-6.2.15-0.rhel5.i386.rpm
% mysqladmin -u root password rootpass

(mysql のルートのパスワードは適切に設定してください)

次に設定ファイルを作成します。ひな形はrpmで提供されているので、これを /etc/ 以下にコピーして、NDB Clusterに必要な設定を追加します。

% sudo cp /usr/share/doc/MySQL-Cluster-gpl-server-6.2.15/my-large.cnf /etc/my.cnf
% sudo vim /etc/my.cnf

追加するのは以下の内容です。
[mysqld]セクション内に以下の2行

ndbcluster
ndb-connectstring = 192.168.10.1

ファイル末尾に [mysql_cluster] セクションを追加して1行。

ndb-connectstring = 192.168.10.1

そしてファイアーウォールの設定をします。

% sudo /usr/sbin/lokkit

で、受信を許可する「その他のポート」に「63132:tcp mysql:tcp」と書きます。

また、これだけだと mysql が管理ノードにアクセスしに行くときに selinux に引っかかってエラーになるのですが、そのエラーをわざと一度起こして許可ルールを作るためのログを吐かせます。
もし、/var/log/audit というディレクトリが存在しない場合、audit をインストールしておいてください。

% sudo yum install audit
% sudo /etc/init.d/auditd start% sudo /etc/init.d/mysql start
% sudo grep denied /var/log/audit/audit.log

これで、

type=AVC msg=audit(1216111039.402:59893): avc:  denied { name_con
nect } for  pid=29878 comm="mysqld" dest=32960 scontext=user_u:sy
stem_r:mysqld_t:s0 tcontext=system_u:object_r:port_t:s0 tclass=tc
p_socket

というような行が見つかればOKです。(適当に改行してありますが、本当は一行です。)
mysql はこのまま起動に失敗してプロセスが残ったままになってしまうので、ちゃんとプロセスを kill しておいてください。
次にこのログから許可ルールを作成します。

% sudo audit2allow -a -M mysqlcluster

すると mysqlcluster.pp というファイルが生成されるのでこれをselinuxに取り込ませます。

% sudo /usr/sbin/semodule -i mysqlcluster.pp

ただ、これだとmysqlがネットワークにアクセスするのを全て許可してしまうので、宛先やポートを指定して許可したい場合には適切な te ファイルを作成して設定してください。
ちなみに、srv2 でこの pp ファイルを作れば、srv3 ではログを吐かせるあたりは省略して pp ファイルをコピーして読みこませるだけでOKです。

ここまで来たらあとはデータノードとSQLノードを起動するだけです。
まずデータノードを起動します。

% sudo -u mysql /usr/sbin/ndbd

この時点で srv1 の ndb_mgm から確認すると以下のようになっているでしょう。

ndb_mgm> show
Cluster Configuration
---------------------
[ndbd(NDB)]     2 node(s)
id=11   @192.168.10.2  (mysql-5.1.23 ndb-6.2.15, starting, Nodegroup: 0, Master)
id=12   @192.168.10.3  (mysql-5.1.23 ndb-6.2.15, starting, Nodegroup: 0)

[ndb_mgmd(MGM)] 1 node(s)
id=1   @192.168.10.1  (mysql-5.1.23 ndb-6.2.15)

[mysqld(API)]   2 node(s)
id=21 (not connected, accepting connect from 192.168.10.2)
id=22 (not connected, accepting connect from 192.168.10.3)

ここでndbdのどちらにもMasterの表示がない場合、外からndbdへのアクセスに失敗している可能性があります。srv1 の config.ini の [NDBD DEFAULT] セクションで SeverPort が 63132 に設定された上で、srv2 と srv3 でポートが空いているかどうか確認してください。

次にsrv2 とsrv3 でmysqlを起動します。

% sudo /etc/init.d/mysql start

そして srv1 で確認します。

ndb_mgm> show
Cluster Configuration
---------------------
[ndbd(NDB)]     2 node(s)
id=11   @192.168.10.2  (mysql-5.1.23 ndb-6.2.15, starting, Nodegroup: 0, Master)
id=12   @192.168.10.3  (mysql-5.1.23 ndb-6.2.15, starting, Nodegroup: 0)

[ndb_mgmd(MGM)] 1 node(s)
id=1   @192.168.10.1  (mysql-5.1.23 ndb-6.2.15)

[mysqld(API)]   2 node(s)
id=21   @192.168.10.2  (mysql-5.1.23 ndb-6.2.15)
id=22   @192.168.10.3  (mysql-5.1.23 ndb-6.2.15)

この画面がちゃんと表示されれば、インストールは成功です。

それでは srv2 と srv3 でデータが同期されることを確認しましょう。

まずは srv2 で。

% mysql -u root -p
mysql> create database cluster_test;
Query OK, 1 row affected (0.24 sec)

そして srv3 で。

% mysql -u root -p
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| cluster_test       |
| mysql              |
| ndb_12_fs          |
+--------------------+
4 rows in set (0.00 sec)

を!?

では srv3 で

mysql> use cluster_test
Database changed
mysql> create table foo(bar int(10) primary key, name varchar(255))
    -> engine=ndbcluster;
Query OK, 0 rows affected (0.82 sec)

そして srv2 で

mysql> use cluster_test
Database changed
mysql> show tables;
+------------------------+
| Tables_in_cluster_test |
+------------------------+
| foo                    |
+------------------------+
1 row in set (0.00 sec)

をを!?

では srv2 で

mysql> insert into foo values(1, 'ggrecus');
Query OK, 1 row affected (0.01 sec)

そして srv3 で

mysql> select * from foo;
+-----+---------+
| bar | name    |
+-----+---------+
|   1 | ggrecus |
+-----+---------+
mysql> drop database cluster_test;
Query OK, 2 rows affected (0.82 sec)
1 row in set (0.02 sec)

うむ。
そして srv2 で

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| ndb_11_fs          |
+--------------------+
3 rows in set (0.00 sec)

素敵ですね。

ちなみにテーブルを作るときに engine=ndbcluster を入れ忘れると同期されないので寂しいです。

さて、これでやっと MogileFS をインストールする準備ができました。

長かったですね。当初の目的を忘れるところでしたよ…