はじめに
Percona XtraDB Clusterのクラスタ周りの検証をするのにDockerを使ってます。
素早く作りなおしたり、いい感じに使えてるので紹介します。
検証用として使ってください。
環境
今回の環境はこんな感じ。
- Percona XtraDB Cluster 5.5
- Docker 1.3.1
- (Dockerホスト) CentOS 6.5
- (Vagrantホスト) Mac OS X
Percona XtraDB Cluster
Percona XtraDB Clustertって?
Percona XtraDB Cluster(PXC)は、マルチマスタでクラスタ構築が可能なMySQL互換RDBMSです。
主にPercona社がOSSとして開発しています。
基礎になっているのはPercona ServerというオープンソースのMySQLフォークです。
PXCはPercona Serverをベースに、Codership Oy社が開発しているGalera libraryというマルチマスタ同期レプリケーションを実現するためのライブラリを利用しています。
同じくMySQLのフォークでGaleraを利用したものにMariaDB Galera Clusterがあります。
日本ではMariaDBのほうが有名でしょうか。
PerconaはMariaDBよりもMySQLとの互換性を重視しているため、今までMySQLを利用してた人は乗り換えやすいと思います。
マルチマスタレプリケーション
一般的にMySQLのレプリケーションはMaster、Slave構成です。
書き込みはマスターのみで、Masterがダウンした時はFailoverが発生します。
Galeraを使ったマルチマスタ構成では、クラスタを構成する全ノードがMasterであり書き込み可能です。
(擬似)同期レプリケーションにより、ノード間をまたいだトランザクション処理も可能です。
また、全ノードがマスタなので障害時にFailoverが発生しません。
ノードの追加や削除も楽にできるので、運用が非常に楽になります。
性能面では、読み込み性能はスケールアウトにより向上しますが、書き込みはそれほど効果はありません。
あるノードへの書き込みは、同時に全ノードへ書き込むという同期レプリケーションの性質のためです。
構成
この記事ではPercona XtraDB Clusterのコンテナを3台立ち上げ、クラスタを構築します。
(Percona XtraDB Clusterの推奨最小ノード数が3台)
DockerホストにはCentOS 6を使います。
Dockerホスト準備
では実際に作業していきます。
まずDockerホストのCentOSをVagrantで立ち上げ、もろもろを準備します。
Vagrant
Dockerが動けばなんでもいいですが、今回はVagrantを使います。
$ vagrant add cent65 https://github.com/2creatives/vagrant-centos/releases/download/v6.5.3/centos65-x86_64-20140116.box
$ mkdir ~/pxctest
$ cd ~/pxctest
$ vagrant init cent65
$ vagrant up
$ vagrant ssh
Dockerインストール
ここから、CentOS上での操作になります。
まずはDockerをインストールします。
$ sudo yum update -y
$ sudo yum install -y epel-release
$ sudo yum install -y docker-io
Dockerを起動して、自動起動も設定しておきます。
$ sudo service docker start
$ sudo chkconfig docker on
vagrantユーザからDockerが使えるように、vagrantユーザをdockerグループに所属させます。
$ sudo gpasswd -a vagrant docker
Dockerイメージ作成
Percona XtraDB Cluster用のイメージを作成します。
イメージはDocker Hubにもあるので、Pullすれば使えます。
git clone
起動スクリプトとか色々一式をクローンします。
$ git clone https://github.com/nownabe/docker-test_pxc.git
$ cd docker-test_pxc
イメージをビルドする場合
SSH鍵作成
コンテナにSSH接続するための鍵ペアを作成します。
$ ssh-keygen -t rsa -N '' -f id_rsa
ビルド
$ docker build --rm=true -t nownabe/test_pxc .
docker pullする場合
$ docker pull nownabe/test_pxc
Dockerfile
Dockerfileはこんな感じです。
FROM centos:centos6
MAINTAINER nownabe
RUN yum -y update
RUN echo 'root:password' | chpasswd
## Setup SSH
RUN yum install -y openssh-server
RUN sed -ri 's/^UsePAM yes/UsePAM no/' /etc/ssh/sshd_config
RUN mkdir -p /root/.ssh
RUN chmod 700 /root/.ssh
ADD id_rsa.pub /root/.ssh/authorized_keys
RUN chmod 600 /root/.ssh
RUN service sshd start && service sshd stop
## Setup Supervisor for SSH
RUN yum install -y python-setuptools
RUN easy_install supervisor
ADD supervisord.conf /etc/supervisord.conf
## Setup Percona XtraDB Cluster
RUN yum install -y epel-release
RUN rpm -ivh http://www.percona.com/redir/downloads/percona-release/redhat/0.1-3/percona-release-0.1-3.noarch.rpm
RUN yum install -y compat-readline5 which
RUN yum install -y Percona-XtraDB-Cluster-55
ADD my.cnf /etc/my.cnf
## Port
EXPOSE 22 3306 4444 4567 4568
CMD ["/usr/bin/supervisord"]
epelはPerconaインストールするときにsocatのインストールを求められるので追加します。
compat-readline5はsocatのインストールに必要でした。
whichがないとSSTでrsyncのパスを見つけられず失敗するためインストールが必要です。
検証用ということでSSHを使えるようにしています。
sshdの起動にはsupervisordを使ってます。
Docker 1.3より前の環境で作成したので、SSHでPerconaの起動をしてたりします。
1.3が入っていればdocker exec
コマンドで事足りると思います。
Percona XtraDB Cluster 起動
起動スクリプト
gitレポジトリに同梱されてるbootstrap.sh
というスクリプトを使用します。
このスクリプトでは、
- コンテナ起動
- コンテナ内でPerconaサービス起動
- 1台目:
--wsrep_cluster_address=gcomm://
オプションで最初のノードとして起動します - 2台目以降:既に起動しているコンテナのIPはわかるので、
--wsrep_cluster_address=gcomm://<起動済みコンテナのIP>
オプションでクラスタに参加します
- 1台目:
- 全コンテナを起動したら、全コンテナの
/etc/my.cnf
のwsrep_cluster_address
の書き換え
を行います。
起動
使い方は、単純に実行するだけです。ノード数などを変更する場合はスクリプトの先頭を書き換えてください。
$ sh bootstrap.sh
実行例
以下実行例です。
[vagrant@vagrant-centos65 docker-test_pxc]$ sh bootstrap.sh
==== Setup container test_pxc0 ====
* exec: docker run -d --name="test_pxc0" nownabe/test_pxc
08aaecd1590fd2851e0b3b446a00a7f5aedf040817f8603b98b38203f399640d
ID of test_pxc0: 08aaecd1590f
IP address of test_pxc0: 172.17.0.11
Waiting...
Start MySQL service in test_pxc0
* exec: ssh root@172.17.0.11 -i ./id_rsa -oStrictHostKeyChecking=no "service mysql start --wsrep_cluster_address=gcomm://"
Warning: Permanently added '172.17.0.11' (RSA) to the list of known hosts.
Starting MySQL (Percona XtraDB Cluster).. SUCCESS!
==== Finish to setup container test_pxc0 ====
==== Setup container test_pxc1 ====
* exec: docker run -d --name="test_pxc1" nownabe/test_pxc
ce8fd87cdf03ca5cf93e4686a2788672fd7dd2cc2b8fd3a82a4e3445f05a38e1
ID of test_pxc1: ce8fd87cdf03
IP address of test_pxc1: 172.17.0.12
Waiting...
Start MySQL service in test_pxc1
* exec: ssh root@172.17.0.12 -i ./id_rsa -oStrictHostKeyChecking=no "service mysql start --wsrep_cluster_address=gcomm://172.17.0.11,"
Warning: Permanently added '172.17.0.12' (RSA) to the list of known hosts.
Starting MySQL (Percona XtraDB Cluster)..State transfer in progress, setting sleep higher
. SUCCESS!
==== Finish to setup container test_pxc1 ====
==== Setup container test_pxc2 ====
* exec: docker run -d --name="test_pxc2" nownabe/test_pxc
7902bae8ed8c14e245cb39a174b168cb7e27fd6ba303eee2c8251dee5babafa2
ID of test_pxc2: 7902bae8ed8c
IP address of test_pxc2: 172.17.0.13
Waiting...
Start MySQL service in test_pxc2
* exec: ssh root@172.17.0.13 -i ./id_rsa -oStrictHostKeyChecking=no "service mysql start --wsrep_cluster_address=gcomm://172.17.0.12,172.17.0.11,"
Warning: Permanently added '172.17.0.13' (RSA) to the list of known hosts.
Starting MySQL (Percona XtraDB Cluster)..State transfer in progress, setting sleep higher
. SUCCESS!
==== Finish to setup container test_pxc2 ====
Rewrite my.cnf of 172.17.0.11
* exec: ssh root@172.17.0.11 -i ./id_rsa -oStrictHostKeyChecking=no "sed -i 's|gcomm://|gcomm://172.17.0.13,172.17.0.12,172.17.0.11,|' /etc/my.cnf"
Rewrite my.cnf of 172.17.0.12
* exec: ssh root@172.17.0.12 -i ./id_rsa -oStrictHostKeyChecking=no "sed -i 's|gcomm://|gcomm://172.17.0.13,172.17.0.12,172.17.0.11,|' /etc/my.cnf"
Rewrite my.cnf of 172.17.0.13
* exec: ssh root@172.17.0.13 -i ./id_rsa -oStrictHostKeyChecking=no "sed -i 's|gcomm://|gcomm://172.17.0.13,172.17.0.12,172.17.0.11,|' /etc/my.cnf"
レプリケーション確認
実際にクラスタが組めてるか確認します。
ステータス確認
コンテナにSSHで接続して、show status
してみます。
SSHの接続先は、bootstrap.sh
のログを参照してください。
$ ssh root@172.17.0.11 -i ./id_rsa
[root@08aaecd1590f ~]# mysql -uroot -e'show status like "wsrep%"'
+----------------------------+----------------------------------------------------+
| Variable_name | Value |
+----------------------------+----------------------------------------------------+
| wsrep_local_state_uuid | 85f1c3f9-8079-11e4-8426-0ae04c8da14d |
| wsrep_protocol_version | 4 |
| wsrep_last_committed | 0 |
| wsrep_replicated | 0 |
| wsrep_replicated_bytes | 0 |
| wsrep_received | 10 |
| wsrep_received_bytes | 728 |
| wsrep_local_commits | 0 |
| wsrep_local_cert_failures | 0 |
| wsrep_local_replays | 0 |
| wsrep_local_send_queue | 0 |
| wsrep_local_send_queue_avg | 0.000000 |
| wsrep_local_recv_queue | 0 |
| wsrep_local_recv_queue_avg | 0.000000 |
| wsrep_flow_control_paused | 0.000000 |
| wsrep_flow_control_sent | 0 |
| wsrep_flow_control_recv | 0 |
| wsrep_cert_deps_distance | 0.000000 |
| wsrep_apply_oooe | 0.000000 |
| wsrep_apply_oool | 0.000000 |
| wsrep_apply_window | 0.000000 |
| wsrep_commit_oooe | 0.000000 |
| wsrep_commit_oool | 0.000000 |
| wsrep_commit_window | 0.000000 |
| wsrep_local_state | 4 |
| wsrep_local_state_comment | Synced |
| wsrep_cert_index_size | 0 |
| wsrep_causal_reads | 0 |
| wsrep_incoming_addresses | 172.17.0.11:3306,172.17.0.12:3306,172.17.0.13:3306 |
| wsrep_cluster_conf_id | 3 |
| wsrep_cluster_size | 3 |
| wsrep_cluster_state_uuid | 85f1c3f9-8079-11e4-8426-0ae04c8da14d |
| wsrep_cluster_status | Primary |
| wsrep_connected | ON |
| wsrep_local_bf_aborts | 0 |
| wsrep_local_index | 0 |
| wsrep_provider_name | Galera |
| wsrep_provider_vendor | Codership Oy <info@codership.com> |
| wsrep_provider_version | 2.11(r318911d) |
| wsrep_ready | ON |
| wsrep_thread_count | 3 |
+----------------------------+----------------------------------------------------+
ちゃんと3台でクラスタが組めています。
書き込み
適当に書き込んでレプリケーションを確認します。
まず、先ほどログインしたコンテナのローカルでDB作成、テーブル作成、挿入を行います。
[root@08aaecd1590f ~]# mysql -uroot -e'create database pxctest'
[root@08aaecd1590f ~]# mysql -uroot -e'create table dockers (id int)' pxctest
[root@08aaecd1590f ~]# mysql -uroot -e'insert into dockers values (1)' pxctest
[root@08aaecd1590f ~]# exit
別のコンテナにログインして、select
してみます。
$ ssh root@172.17.0.12 -i ./id_rsa
[root@ce8fd87cdf03 ~]# mysql -uroot -e'select * from dockers' pxctest
+------+
| id |
+------+
| 1 |
+------+
ばっちり同期できてます。
おわりに
以上です。
Galera Clusterの性質上コンテナの起動後にPerconaサービスを起動したり、設定ファイルを書き換えたりしてます。
Dockerの使い方としてはトリッキーなんだと思いますが、いい方法があれば教えて下さい。
Percona XtraDB Clusterのそもそもの構築方法や/etc/my.cnf
の設定などもがっつり省いてしまったので、そのうちやろうと思います。
(順番逆というツッコミが聞こえます)