s_tajima:TechBlog

渋谷で働くインフラエンジニアのTechブログです。

Puppet3.6環境のpuppet.confでmodulepathがdeprecatedとなっている件

puppet-masterのversion3.6.2をセットアップしていて、

Jul 29 14:47:20 localhost puppet-master[2042]: Setting modulepath is deprecated in puppet.conf. See http://links.puppetlabs.com/env-settings-deprecations

と怒られたので
http://links.puppetlabs.com/env-settings-deprecations
にアクセスするも

Access not possible

となりなんの情報も得られず。

Puppet3.6のドキュメントを読むと
f:id:s_tajima:20140729152812p:plain
http://docs.puppetlabs.com/puppet/latest/reference/config_file_main.html
に普通にmodulepathが設定されていたのでなんだこれと思っていた。


よく調べてみるとここにあった。

Config File Environments Are Deprecated

If your puppet.conf file:

Contains any environment config blocks
Sets global values for the manifest, modulepath, or config_version settings

…then the puppet master will log deprecation warnings. (Interpolating the $environment variable won’t log warnings, since it’s benign without the global settings and is useful in environment.conf files.)

In a future version of Puppet (probably Puppet 4), directory environments will always be enabled, and the default production environment will take the place of the global manifest/modulepath/config_version settings.

When you have time, you should read up on directory environments and start using them.

http://docs.puppetlabs.com/puppet/latest/reference/environments_classic.html


Config File Environments(従来の設定方法)をやめてDirectory Environmentsに移れということらしい。
Directory Environmentsの説明はこちら。
http://docs.puppetlabs.com/puppet/latest/reference/environments.html

MySQLのリクエストをHAproxy経由にした時のパフォーマンスの計測

目的

現在運用している環境で、複数台のSlaveの参照をインフラレイヤで振り分けるためにHAproxyの導入を検討している。
HAproxyを経由した場合とそうでない場合に、パフォーマンス/負荷の点でどれほど差があるのかを検証してみた。

尚、HAproxyは各Webサーバ内に同居させることを想定している。

検証環境

  • 検証マシン: 2台(Webサーバ, DBサーバ)
  • OS: Scientific Linux release 6.1 (Carbon)
  • MySQL: MySQL-5.6.16
  • HAproxy: haproxy-1.4.18

HAproxyの設定は以下の通り。

global
  log 127.0.0.1 local2
  chroot      /var/lib/haproxy
  pidfile     /var/run/haproxy.pid
  maxconn     1000
  user        haproxy
  group       haproxy
  daemon
  stats socket /var/lib/haproxy/stats

defaults
  mode                    tcp
  log                     global
  option tcplog

listen mysql
  bind 127.0.0.1:3306
  mode tcp
  retries                 1
  server node01 mysqlserver-a:3306 check port 3306

検証方法

Webサーバから以下のスクリプト(mysqlslapを実行)を交互に3回ずつ実行し、
その実行時間と、実行中のWebサーバーの負荷を計測。

  • mysqlslap_direct.sh
mysqlslap \
--user=testuser \
--password=testpass \
--host=mysqlserver-a \
--port=3306 \
--concurrency=10 \
--iterations=3 \
--engine=innodb \
--auto-generate-sql \
--auto-generate-sql-load-type=write \
--number-of-queries=10001 \
--create-schema=test_mysqlslap 
  • mysqlslap_via_haproxy.sh
mysqlslap \
--user=testuser \
--password=testpass \
--host=127.0.0.1 \
--port=3306 \
--concurrency=10 \
--iterations=3 \
--engine=innodb \
--auto-generate-sql \
--auto-generate-sql-load-type=write \
--number-of-queries=10001 \
--create-schema=test_mysqlslap 

検証結果

f:id:s_tajima:20140516215805p:plain

HAproxyを通した結果、10数%ほどパフォーマンスに影響が出そうなことがわかった。
また、当初はdstatで取得した実行時のWebサーバの負荷についても比較する予定だったが、
どちらもほぼ負荷のない状態だったので割愛。

検証結果のデータはこちら。
https://gist.github.com/vg-s-tajima/aada13917a18b489046b/revisions

RDSからのinnodb_file_per_tableについて

背景

一つ前の記事とも関連するが、
RDSでテーブル数のそれほど多くないインスタンスでも、
こちらの記事にかかれているような警告がでてしまうことがある模様。

http://dev.classmethod.jp/server-side/db/rds-mysql-innodb_file_per_table/

DB Instance XXXX-XXXX has a large number of tables and
has the parameter innodb_file_per_table set to 1, which can increase
database recovery time significantly.
Consider setting this parameter to 0 in the parameter group
associated with this DB instance to minimize database downtime
during reboots and failovers.

心当たりとしては、
この警告が出たDBインスタンスはそれほどテーブルは多くないが、
いくつかののテーブルはRANGEパーティションを切っている。
そして、期間の過ぎたパーティションをTRUNCATE PARTITIONするだけでDROP PARTITIONをしていない。
これが影響している可能性が高そうなので検証してみた。

検証

mysqlserver-a> CREATE TABLE t1 (
    ->  id INT NOT NULL PRIMARY KEY auto_increment,
    ->  cola char(255)
    -> )
    -> PARTITION BY RANGE(id) (
    ->  PARTITION p0 VALUES LESS THAN (64),
    ->  PARTITION p1 VALUES LESS THAN (128),
    ->  PARTITION p2 VALUES LESS THAN (192)
    -> );
Query OK, 0 rows affected (0.20 sec)
mysqlserver-a# ll
合計 308
-rw-rw---- 1 mysql mysql    61  5月 12 18:23 2014 db.opt
-rw-rw---- 1 mysql mysql 98304  5月 16 15:21 2014 t1#P#p0.ibd
-rw-rw---- 1 mysql mysql 98304  5月 16 15:21 2014 t1#P#p1.ibd
-rw-rw---- 1 mysql mysql 98304  5月 16 15:21 2014 t1#P#p2.ibd
-rw-rw---- 1 mysql mysql  8586  5月 16 15:21 2014 t1.frm
-rw-rw---- 1 mysql mysql    32  5月 16 15:21 2014 t1.par
  • TRUNCATE PARTITIONを実行
mysqlserver-a> ALTER TABLE t1 TRUNCATE PARTITION p0;
Query OK, 0 rows affected (0.09 sec)
  • ibdファイルは削除されていない模様。
mysqlserver-a# ll
合計 308
-rw-rw---- 1 mysql mysql    61  5月 12 18:23 2014 db.opt
-rw-rw---- 1 mysql mysql 98304  5月 16 15:23 2014 t1#P#p0.ibd
-rw-rw---- 1 mysql mysql 98304  5月 16 15:21 2014 t1#P#p1.ibd
-rw-rw---- 1 mysql mysql 98304  5月 16 15:21 2014 t1#P#p2.ibd
-rw-rw---- 1 mysql mysql  8586  5月 16 15:21 2014 t1.frm
-rw-rw---- 1 mysql mysql    32  5月 16 15:21 2014 t1.par
  • DROP PARTITIONを実行。
mysqlserver-a> ALTER TABLE t1 DROP PARTITION p0;
Query OK, 0 rows affected (0.14 sec)
Records: 0  Duplicates: 0  Warnings: 0
  • ibdファイル毎削除されたのを確認。
mysqlserver-a# ll
合計 212
-rw-rw---- 1 mysql mysql    61  5月 12 18:23 2014 db.opt
-rw-rw---- 1 mysql mysql 98304  5月 16 15:21 2014 t1#P#p1.ibd
-rw-rw---- 1 mysql mysql 98304  5月 16 15:21 2014 t1#P#p2.ibd
-rw-rw---- 1 mysql mysql  8586  5月 16 15:23 2014 t1.frm
-rw-rw---- 1 mysql mysql    28  5月 16 15:23 2014 t1.par

RDSが何を元にこの警告を出しているのかは確認できていないが、
おそらくPARTITIONをDROPしていないために、ibdファイルが増え続けていたので、
それをRDS側で検知して警告を出したのではないかという推測。

MySQLのinnodb_file_per_tableについての検証

背景

innodb_file_per_tableを有効にしている場合に、
テーブル数が多くなるとMySQLの起動/停止や、innodbのクラッシュリカバリに時間がかかるようになるとの噂を聞いたので、
その辺りを含めた簡単な検証をしてみたメモ。
あまりしっかりとした調査はしていないので参考程度に。

尚、innodb_file_per_tableについての説明は割愛。

検証環境

検証した環境は、

実運用サービスの開発機で使用しているデータを使用。
同一のデータをそれぞれinnodb_file_par_tableをon/offした状態でimport。
参考までにデータの規模としては

  • テーブル数: 2232
  • DBのdumpサイズ(gzip圧縮): 4.1G

程度のもの。

検証内容

上記の検証環境に対して、

  • 通常の再起動
  • mysqld, mysqld_safeをkill -9した後に起動。

という操作をした時にかかる時間を計測した。

検証結果

ケース1: innodb_file_par_table -> ON

  • DBのデータディレクトリ: 49GB
  • ibdata1: 844M
  • 通常再起動: 4秒ほどで再起動完了
2014-05-16 18:47:50 8515 [Note] /opt/MySQL-server-5.6.16/sbin/mysqld: Normal shutdown
2014-05-16 18:47:54 2216 [Note] /opt/MySQL-server-5.6.16/sbin/mysqld: ready for connections.
  • mysqld, mysqld_safeをkill -9: 13秒ほどで起動完了。
140516 14:10:51 mysqld_safe Starting mysqld daemon with databases from /var/lib/mysql10
2014-05-16 14:10:52 8515 [Note] InnoDB: Starting crash recovery.
2014-05-16 14:10:52 8515 [Note] InnoDB: Reading tablespace information from the .ibd files...
2014-05-16 14:11:04 8515 [Note] InnoDB: Restoring possible half-written data pages 
2014-05-16 14:11:05 8515 [Note] /opt/MySQL-server-5.6.16/sbin/mysqld: ready for connections.

ケース2: innodb_file_par_table -> OFF

  • DBのデータディレクトリ: 38MB
  • ibdata1: 42GB
  • 通常再起動: 4秒ほどで再起動完了
2014-05-16 18:46:32 28222 [Note] /opt/MySQL-server-5.6.16/sbin/mysqld: Normal shutdown
2014-05-16 18:46:36 19375 [Note] /opt/MySQL-server-5.6.16/sbin/mysqld: ready for connections.
  • mysqld, mysqld_safeをkill -9: 5秒ほどで起動完了。
140516 14:14:48 mysqld_safe Starting mysqld daemon with databases from /var/lib/mysql11
2014-05-16 14:14:49 28222 [Note] InnoDB: Starting crash recovery.
2014-05-16 14:14:49 28222 [Note] InnoDB: Reading tablespace information from the .ibd files...
2014-05-16 14:14:50 28222 [Note] InnoDB: Restoring possible half-written data pages
2014-05-16 14:14:53 28222 [Note] /opt/MySQL-server-5.6.16/sbin/mysqld: ready for connections.

結果はこんな感じ。

以下の参考資料によると、innodb_file_per_tableだと、
大量のテーブルがあるDBのcrash recoveryプロセスでは、
idbファイルを読み込むのに時間がかかるとの事だったが、この検証ではそれほど気にならない時間で完了している模様。
(尚、RDSのドキュメントによるとテーブル数1000以上ではinnodb_file_per_tableはoffを推奨。)

MHA + HAproxyによるMySQLの冗長構成の検証 (フェイルオーバー編)

前回の記事で作成したMHA + HAproxyのMySQLクラスタで、フェイルオーバーの実験をしてみた。

想定する状況

フェイルオーバー時のレプリケーションの状態は、上のスライドの図1のような状態を想定。

  • master(mysqlserver-a), slave*2台の構成。
  • slv1(mysqlserver-b)はt1までをDBに反映済み。t3までのrelay-logを受信済み。
  • slv2(mysqlserver-c)はt0までをDBに反映済み。t2までのrelay-logを受信済み。

この状況でmasterが(物理障害などで)OSごと停止した状況を想定。
MHAがどのようにリカバリを行うかを調査する。

検証環境構築の準備

MySQLレプリケーション構成、MHAの設定などは前回の記事の通り。
今回はレプリケーションの状況をt0 -> t5の状況にする手順を記載。

t0 -> t1

  1. masterに対して書き込みを行う。
    1. 正常にレプリケーションされているのでslv1, slv2にもその書き込みが反映される。

t1 -> t2

  1. slv2のSQLスレッドを停止
  2. masterに対して書き込みを行う。
    1. slv1: t0 -> t1と同様masterに書き込んだデータが反映される。
    2. slv2: SQLスレッドが停止しているので、relay-logの転送は行われるが、DBへの反映はされない。

t2 -> t3

  1. slv1のSQLスレッドを停止
  2. masterに対して書き込みを行う。
    1. slv1: SQLスレッドが停止しているので、relay-logの転送は行われるが、DBへの反映はされない。
    2. slv2: SQLスレッドが停止しているので、relay-logの転送は行われるが、DBへの反映はされない。

t3 -> t4

  1. slv2のIOスレッドを停止
  2. masterに対して書き込みを行う。
    1. slv1: SQLスレッドが停止しているので、relay-logの転送は行われるが、DBへの反映はされない。
    2. slv2: IOスレッドが停止しているので、relay-logの転送が行われない。

t4 -> t5

  1. slv1のIOスレッドを停止
  2. masterに対して書き込みを行う。
    1. slv1: IOスレッドが停止しているので、relay-logの転送が行われない。
    2. slv2: IOスレッドが停止しているので、relay-logの転送が行われない。

実行したコマンドやその時のステータスは こちら:https://gist.github.com/s-tajima/9483097

フェイルオーバー時の挙動検証

スライドに添って解説。

masterの停止, MHAによる検知(スライド:図2)

サーバーがOSごと停止した状況を擬似的に再現するために、以下のコマンドを実行。

mysqlserver-a# nohup sh -c "kill -9 <mysqldのpid>; kill -9 <mysqld_safeのpid>; /etc/init.d/sshd stop; sleep 300; /etc/init.d/sshd start" &

sshdとmysqldをほぼ同時に停止(kill)する。

数秒すると、manager.logに以下のようなログが流れる。

Mon Mar 10 17:41:08 2014 - [warning] Got error on MySQL ping: 2006 (MySQL server has gone away)
ssh: connect to host 10.0.0.1 port 22: Connection refused
Mon Mar 10 17:41:08 2014 - [warning] HealthCheck: SSH to mysqlserver-a is NOT reachable.
Mon Mar 10 17:41:11 2014 - [warning] Got error on MySQL connect: 2013 (Lost connection to MySQL server at 'reading initial communication packet', system error: 111)
Mon Mar 10 17:41:11 2014 - [warning] Connection failed 1 time(s)..
Mon Mar 10 17:41:14 2014 - [warning] Got error on MySQL connect: 2013 (Lost connection to MySQL server at 'reading initial communication packet', system error: 111)
Mon Mar 10 17:41:14 2014 - [warning] Connection failed 2 time(s)..
Mon Mar 10 17:41:17 2014 - [warning] Got error on MySQL connect: 2013 (Lost connection to MySQL server at 'reading initial communication packet', system error: 111)
Mon Mar 10 17:41:17 2014 - [warning] Connection failed 3 time(s)..
Mon Mar 10 17:41:17 2014 - [warning] Master is not reachable from health checker!
Mon Mar 10 17:41:17 2014 - [warning] Master mysqlserver-a(10.0.0.1:3306) is not reachable!
Mon Mar 10 17:41:17 2014 - [warning] SSH is NOT reachable.

最新のrelay-logを持つSlaveを特定(スライド:図3)

slv1が最新のrelay-logを持つslaveであることを特定。

Mon Mar 10 17:41:17 2014 - [info] The latest binary log file/position on all slaves is mysqld-bin.000007:24179
Mon Mar 10 17:41:17 2014 - [info] Latest slaves (Slaves that received relay log files to the latest):
Mon Mar 10 17:41:17 2014 - [info]   mysqlserver-b(10.0.0.2:3306)  Version=5.6.16-log (oldest major version between slaves) log-bin:enabled
Mon Mar 10 17:41:17 2014 - [info]     Replicating from 10.0.0.1(10.0.0.1:3306)

masterにSSHで接続。可能であればbinary logの回収を行う。(スライド:図4)

今回はmasterがOS毎落ちてしまった場合を想定しているため、
slv1に送信されていなかったbinary logは回収不可能。

Mon Mar 10 17:41:17 2014 - [warning] Dead Master is not SSH reachable. Could not save it's binlogs. Transactions that were not sent to the latest slave (Read_Master_Log_Pos to the tail of the dead master's binlog) were lost.

新masterの選定。relay-logの適用。(スライド:図5)

slv2が最新のrelay-logを持っていることが確認できたため、
新masterに選出される。

Mon Mar 10 17:41:18 2014 - [info] OK. mysqlserver-b has all relay logs.
Mon Mar 10 17:41:18 2014 - [info] HealthCheck: SSH to mysqlserver-c is reachable.
Mon Mar 10 17:41:19 2014 - [info] Searching new master from slaves..
Mon Mar 10 17:41:19 2014 - [info]  Candidate masters from the configuration file:
Mon Mar 10 17:41:19 2014 - [info]  Non-candidate masters:
Mon Mar 10 17:41:19 2014 - [info] New master is mysqlserver-b(10.0.0.2:3306)
Mon Mar 10 17:41:19 2014 - [info] Starting master failover..

新masterのrelay-logが、全て適用されるのを待つ。

Mon Mar 10 17:41:19 2014 - [info] Starting recovery on mysqlserver-b(10.0.0.2:3306)..
Mon Mar 10 17:41:19 2014 - [info]  This server has all relay logs. Waiting all logs to be applied..
Mon Mar 10 17:41:19 2014 - [info]   done.
Mon Mar 10 17:41:19 2014 - [info]  All relay logs were successfully applied.

slaveのデータ復旧(スライド:図6, 図7)

slv1とslv2のrelay-logを比較し、slv2が持っていない(relay-logがない)データを特定。
slv1のrelay-logから差分のbin-logを生成し、scpでslv2に送信する。

Mon Mar 10 17:41:19 2014 - [info] Server mysqlserver-c received relay logs up to: mysqld-bin.000007:23133
Mon Mar 10 17:41:19 2014 - [info] Need to get diffs from the latest slave(mysqlserver-b) up to: mysqld-bin.000007:24179 (using the latest slave's relay logs)
Mon Mar 10 17:41:19 2014 - [info] Connecting to the latest slave host mysqlserver-b, generating diff relay log files..
Mon Mar 10 17:41:19 2014 - [info] Executing command: apply_diff_relay_logs --command=generate_and_send --scp_user=root --scp_host=10.0.0.3 --latest_mlf=mysqld-bin.000007 --latest_rmlp=24179 --target_mlf=mysqld-bin.000007 --target_rmlp=23133 --server_id=2 --diff_file_readtolatest=/var/log/mha4mysql//relay_from_read_to_latest_mysqlserver-c_3306_20140310174117.binlog --workdir=/var/log/mha4mysql/ --timestamp=20140310174117 --handle_raw_binlog=1 --disable_log_bin=0 --manager_version=0.52 --relay_log_info=/var/lib/mysql/relay-log.info
Mon Mar 10 17:41:20 2014 - [info]  Generating diff files succeeded.
Mon Mar 10 17:41:20 2014 - [info] End of log messages from mysqlserver-c.
Mon Mar 10 17:41:20 2014 - [info] -- Slave diff log generation on host mysqlserver-c(10.0.0.3:3306) succeeded.
Mon Mar 10 17:41:20 2014 - [info] Generating relay diff files from the latest slave succeeded.

slv2が持っていたrelay-logがすべて適用されるのを待ち、
続いてslv1から送信されたbin-logを適用する。

Mon Mar 10 17:41:20 2014 - [info] Starting recovery on mysqlserver-c(10.0.0.3:3306)..
Mon Mar 10 17:41:20 2014 - [info]  Generating diffs succeeded.
Mon Mar 10 17:41:20 2014 - [info] Waiting until all relay logs are applied.
Mon Mar 10 17:41:20 2014 - [info]  done.
Mon Mar 10 17:41:20 2014 - [info] Getting slave status..
Mon Mar 10 17:41:20 2014 - [info] This slave(mysqlserver-c)'s Exec_Master_Log_Pos equals to Read_Master_Log_Pos(mysqld-bin.000007:23133). No need to recover from Exec_Master_Log_Pos.
Mon Mar 10 17:41:20 2014 - [info] Connecting to the target slave host mysqlserver-c, running recover script..
Mon Mar 10 17:41:20 2014 - [info] Executing command: apply_diff_relay_logs --command=apply --slave_user=root --slave_host=mysqlserver-c --slave_ip=10.0.0.3  --slave_port=3306 --apply_files=/var/log/mha4mysql//relay_from_read_to_latest_mysqlserver-c_3306_20140310174117.binlog --workdir=/var/log/mha4mysql/ --target_version=5.6.16-log --timestamp=20140310174117 --handle_raw_binlog=1 --disable_log_bin=0 --manager_version=0.52 --slave_pass=xxx
Mon Mar 10 17:41:20 2014 - [info]
Applying differential binary/relay log files /var/log/mha4mysql//relay_from_read_to_latest_mysqlserver-c_3306_20140310174117.binlog on mysqlserver-c:3306. This may take long time...
Applying log files succeeded.
Mon Mar 10 17:41:20 2014 - [info]  All relay logs were successfully applied.

レプリケーションの参照先の変更(スライド: 図8)

レプリケーションの参照先を、新masterに変更する。

Mon Mar 10 17:41:20 2014 - [info]  Resetting slave mysqlserver-c(10.0.0.3:3306) and starting replication from the new master mysqlserver-b(10.0.0.2:3306)..
Mon Mar 10 17:41:20 2014 - [info]  Executed CHANGE MASTER.
Mon Mar 10 17:41:20 2014 - [info]  Slave started.

以上がMHAによるフェイルオーバーの流れ。
manager.logの全文は こちら: https://gist.github.com/s-tajima/9481507

MHA + HAproxyによるMySQLの冗長構成の検証 (環境構築編)

現在運用中の、Heartbeat + DRBDによるMySQLクラスタ環境の改善を試みるために、
MHA + HAproxyによるMySQLクラスタ環境をテスト中。

今回は環境を整えるところまで。

環境構築

AWS上に以下の図と文章で示すような環境を構築。

  • webserver, manageserver, mysqlserver * 3台(master, slave, slave)
  • webserverは同ホスト上で稼働しているHAproxy経由でMySQLサーバーにアクセス
    • 初期状態
      • 127.0.0.1:3310でmysqlserver-aのmysql(master)に接続。WRITE処理を行う想定。
      • 127.0.0.1:3311でmysqlserver-[bc]のmysql(slave)に接続。READ処理を行う想定。
    • フェイルオーバー後
      • 127.0.0.1:3310でmysqlserver-bのmysql(master)に接続。WRITE処理を行う想定。
      • 127.0.0.1:3311でmysqlserver-cのmysql(slave)に接続。READ処理を行う想定。
  • managerで稼働しているMHAデーモンがmasterを監視。
    • slaveを監視していないのはMHAの基本的な挙動。MHAは基本的にはmasterの動作しか監視していない。
  • フェイルオーバーの動作
    • master障害時にはmysqlserver-[bc]から新たなmasterを選出する。
    • mysqlserver-[bc]のうち、slaveのままになった方のレプリケーションの参照先の切り替えもMHAが担当。
    • HAproxyの設定変更は、MHAがフェイルオーバー時にキックするスクリプトによって実現
  • OSはScientificLinux6.4を使用。

構築手順

mysqlのインストール, レプリケーションの設定(@mysqlserver-[abc])

MySQL Community Server 5.6.16 をインストール。
mysqlserver-a -> mysqlserver-[bc]のレプリケーションを設定する。
細かい手順は割愛。

作業用ディレクトリの作成(@全サーバー)

作業用のディレクトリとして、

/etc/mha4mysql
/var/log/mha4mysql

を全サーバーに作成しておく。

MHAのインストール、設定(@全サーバー)

以下のページからrpmをダウンロード。

MHA(manager)
http://code.google.com/p/mysql-master-ha/downloads/detail?name=mha4mysql-manager-0.52-0.noarch.rpm

MHA(node)
http://code.google.com/p/mysql-master-ha/downloads/detail?name=mha4mysql-node-0.52-0.noarch.rpm

managerserverにはmanagerとnodeを
mysqlserver-[abc]にはnodeを
それぞれインストールする。

MHAの細かい設定手順については
https://code.google.com/p/mysql-master-ha/wiki/Tutorial
この辺りに詳しく載っているので割愛。

/etc/mha4mysql/manager.confの設定は以下の通り。

設定ファイルを指定して起動。実際にはnohupと&を付けてbackgroundで起動。

 managerserver# masterha_manager --conf=/etc/mha4mysql/manager.conf

ここまでの設定で、MySQLレプリケーションクラスタがMHAによってフェイルオーバーする仕組みは完成。
続いてはHAproxyによってwebserverからのMySQLサーバーの接続先を切り替える環境を構築する。

HAproxyのインストール、設定(@webserver)

HAproxyについてはSL6.4のEPELリポジトリに登録されているのでyumで普通にインストールできる。

haproxyの設定はMHAと連携して書き換わる必要があるので、
以下のような設定を行う。

  • 初期状態の/etc/haproxy/haproxy.cfgを配置。
  • /etc/haproxy/haproxy.cfg.erbにフェイルオーバー時に切り替えるためのhaproxy.cfgのテンプレートを準備
  • /etc/mha4mysql/manager.confのmaster_ip_failover_scriptに、フェイルオーバー時のスクリプト/etc/mha4mysql/scripts/rewrite_haproxy_config.rbを設定

設定ファイルとスクリプトの設置が完了したら、HAproxyを起動する。

 webserver# /etc/init.d/haproxy start

尚、今回はwebserverとmanagerserverが同一インスタンスなのでmaster_ip_failover_scriptで直接rewrite_haproxy_config.rbを指定したが、
本来はリモートサーバーにあるrewrite_haproxy_config.rbを呼び出すスクリプトを指定する必要がありそう。

以上で、MHA + HAproxyによるMySQLの冗長構成環境が作成完了。
これからこの環境でいろいろと検証していく予定。

(おまけ)環境構築時に詰まった問題

libのインストールディレクトリの問題

masterha_check_ssh実行時に以下のようなエラーに。

managerserevr# masterha_check_ssh --conf /etc/mha4mysql/manager.conf
Can't locate MHA/SSHCheck.pm in @INC (@INC contains: /usr/local/lib64/perl5 /usr/local/share/perl5 /usr/lib64/perl5/vendor_perl /usr/share/perl5/vendor_perl /usr/lib64/perl5 /usr/share/perl5 .) at /usr/bin/masterha_check_ssh line 25.
BEGIN failed--compilation aborted at /usr/bin/masterha_check_ssh line 25.

本環境では/usr/lib64/perl5/vendor_perl/以下にインストールされなければならないMHAが、
/usr/lib/perl5/vendor_perl/にインストールされているのが原因の模様。

managerserevr# rpm -ql mha4mysql-manager-0.52-0.noarch | grep lib
/usr/lib/perl5/vendor_perl/MHA/Config.pm
/usr/lib/perl5/vendor_perl/MHA/DBHelper.pm
/usr/lib/perl5/vendor_perl/MHA/FileStatus.pm
/usr/lib/perl5/vendor_perl/MHA/HealthCheck.pm
/usr/lib/perl5/vendor_perl/MHA/ManagerAdmin.pm
/usr/lib/perl5/vendor_perl/MHA/ManagerAdminWrapper.pm
/usr/lib/perl5/vendor_perl/MHA/ManagerConst.pm
/usr/lib/perl5/vendor_perl/MHA/ManagerUtil.pm
/usr/lib/perl5/vendor_perl/MHA/MasterFailover.pm
/usr/lib/perl5/vendor_perl/MHA/MasterMonitor.pm
/usr/lib/perl5/vendor_perl/MHA/MasterRotate.pm
/usr/lib/perl5/vendor_perl/MHA/SSHCheck.pm
/usr/lib/perl5/vendor_perl/MHA/Server.pm
/usr/lib/perl5/vendor_perl/MHA/ServerManager.pm

managerserevr# rpm -ql perl-5.10.1-119.el6.x86_64 | grep /usr/lib
/usr/lib64/perl5/5.10.0
/usr/lib64/perl5/5.10.0/x86_64-linux-thread-multi
/usr/lib64/perl5/5.10.0/x86_64-linux-thread-multi/CORE
.. snip ..

シンボリックリンクを貼ることで回避。

managerserevr# ln -s /usr/lib/perl5/vendor_perl/MHA /usr/lib64/perl5/vendor_perl/MHA 

※よくある質問に載ってた。
https://code.google.com/p/mysql-master-ha/issues/detail?id=30

fluentdの設定管理サーバーを構築

概要

fluentdによるログの回収の構成を広げていくと、
多くのインスタンスにfluentdがインストールされることになるため、
全体に影響するような設定変更が面倒になりそうである。

そこで、fluentdの設定ファイルの中で

include http://config-server/path/

このようにinclude対象にhttp(s)でのリソース取得ができることに注目し、
この仕組を利用した構成を組むことで設定変更時の手間を減らす工夫をした。

構成

f:id:s_tajima:20140303224155j:plain

  • CONTROLLERと呼ばれるサーバーにfluentdの設定を配布するためのWebサーバー(config-server)を立てる。
    • config-serverは、GETパラメータによって返す内容(設定)を変更するようなものとする。
    • 大した処理をしないので、今回はsinatraで実装。
    • 今回実装した例で言えばGETパラメータにはホスト名を指定。config-serverにはホスト毎に必要な設定を定義した。
  • CLIENT(ログの取得元)側では、cronによって定期的にSIGHUPをかける。
    • config-serverで設定を変更した際、その設定が定期的に反映される。
    • 事前に--dry-runを実施し、httpによる設定の取得のエラーや、設定ファイルのエラーがあればSIGHUPは中止する。
    • fluentdのプロセスが停止している場合には、SIGHUPではなく再起動(service td-agent restart)する。
    • 設定には以下のようにGETパラメータにhostnameを付与したものを指定
include https://config-server/?hostname=CLIENT
  • STREAM(ログの収集サーバー)は、台数が少ないのと設定の不備があった場合に広い範囲に影響が出る可能性があるため定期SIGHUPはなし。

まとめ

  • fluentdの死活監視/buffer監視等については別途環境整備済みなので、この構成で運用を開始してみて副作用を検証。
  • 毎回SIGHUPをかけるのではなく、予めcurlなどで設定ファイルを取得してmd5を計算してどこかにおいておき、前回のものと差分があったらSIGHUPでもいいかも。
  • 設定変更時、最初に少数のtd-agentで別のinclude先を指定(同サーバーの別virtualhost等)して、設定をテストする。みたいなことも可能。