Ganglia の mysqld プラグインを導入してみた
前回に引き続き Ganglia のお話です。
元々 MySQL のチューニングの効果検証のために導入したので、MySQL 関係のメトリックを追加します。
手軽にメトリックを追加しようと思うと、Ganglia 3.1 以降では ganglia/gmond_python_modules のものを使うのが良いみたいです。
MySQL 関係だと mysql と mysqld というのがあるんですが、graph.d があるというのと比較的最近に更新されているという理由で mysqld を使ってみることにしました。元々 Ganglia を導入して効果検証しようと思ったのは id:hirose31 さんによる「実録MySQLのチューニング 春の陣 - (ひ)メモ」がきっかけなので、mysql を使うべきかもしれませんが・・・。
mysqld プラグインのインストール
監視対象クライアントでのインストール
更新の度にアーカイブをダウンロードするのも何なんで、リポジトリをクローンします。
# mkdir /var/git
# cd /var/git/
# git clone https://github.com/ganglia/gmond_python_modules.git
次の内容で /etc/ganglia/conf.d/modpython.conf を作成します。/etc/ganglia/conf.d がない場合は作成します。
modules {
module {
name = "python_module"
path = "/usr/lib/ganglia/modpython.so"
params = "/usr/lib/ganglia/python_modules"
}
}
include('/etc/ganglia/conf.d/*.pyconf')
必要なファイルを移動します。
# mkdir /usr/lib/ganglia/python_modules
# cp /var/git/gmond_python_modules/mysqld/python_modules/* /usr/lib/ganglia/python_modules/
# cp /var/git/gmond_python_modules/mysqld/conf.d/mysql.pyconf /etc/ganglia/conf.d/
mysql.pyconf に書いてあるように gmond 用の MySQL ユーザを作成します。
# mysql -uroot -p -e 'GRANT SUPER, PROCESS ON *.* TO health@localhost IDENTIFIED BY "hogehoge";'
/etc/ganglia/conf.d/mysql.pyconf の host と passwd をセットします。
modules {
module {
name = "mysql"
language = "python"
param host {
value = 'localhost'
}
param user {
value = 'health'
}
param passwd {
value = 'hogehoge'
}
必要な Python モジュールをインストールします。特にこだわらないので virtualenv + pip でインストールするとかじゃなくて APT でインストールします。
# aptitude install python-mysqldb
試しに起動してみます。
# /etc/init.d/ganglia-monitor stop
# gmond --debug=2
Python のバージョンの関係か、ここで次のようなエラーが出るかもしれません。
# gmond --debug=2
loaded module: core_metrics
loaded module: cpu_module
loaded module: disk_module
loaded module: load_module
loaded module: mem_module
loaded module: net_module
loaded module: proc_module
loaded module: sys_module
loaded module: python_module
udp_recv_channel mcast_join=NULL mcast_if=NULL port=8649 bind=NULL
tcp_accept_channel bind=NULL port=8649
udp_send_channel mcast_join=NULL mcast_if=NULL host=172.16.199.5 port=8649
Unable to find the metric information for 'mysql_innodb_pending_normal_aio_reads'. Possible that the module has not been loaded.
Unable to find the metric information for 'mysql_innodb_pending_log_writes'. Possible that the module has not been loaded.
(後略)
mysql_innodb_pending_normal_aio_reads とか定義されているけど、そんな情報取得できなかったよって意味です。
その場合は /usr/lib/ganglia/python_modules/mysql.py を次のように変更するとうまくいくかもしれません。変更したら忘れずに mysql.pyc を削除しましょう。
--- mysql.py.orig 2012-10-08 19:18:43.000000000 +0900
+++ mysql.py 2012-10-08 18:53:22.000000000 +0900
@@ -124,7 +124,7 @@
if get_innodb:
cursor = conn.cursor(MySQLdb.cursors.Cursor)
cursor.execute("SHOW /*!50000 ENGINE*/ INNODB STATUS")
- innodb_status = parse_innodb_status(cursor.fetchone()[0].split('\n'))
+ innodb_status = parse_innodb_status(cursor.fetchone()[2].split('\n'))
cursor.close()
logging.debug('innodb_status: ' + str(innodb_status))
ちなみに使用している Python はシステムに組み込みのもので古く、次のようになっています。
# python --version
Python 2.6.6
# python -c 'import MySQLdb; print MySQLdb.version_info'
(1, 2, 2, 'final', 0)
問題なく起動したら再起動します。
# /etc/init.d/ganglia-monitor restart
これで監視対象クライアントへのインストールは完了です。
管理サーバでのインストール
こちらでもクローンします。
# mkdir /var/git
# cd /var/git/
# git clone https://github.com/ganglia/gmond_python_modules.git
グラフを表示するためのファイルをコピーします。
# cp /var/git/gmond_python_modules/mysqld/graph.d/mysql_* /usr/share/ganglia-webfrontend/graph.d/
管理サーバは以上です!
あとは Web Frontend にアクセスして MySQL 関係のメトリックも追加されていることを確認してみてください。
以上、MySQL 関係のメトリックの追加方法でした!
追記
SHOW INNODB STATUS の Buffer pool hit rate とかも取りたかったので次のように変更しました。
/etc/ganglia/conf.d/mysql.pyconf
--- mysql.pyconf.orig 2012-10-08 19:48:22.000000000 +0900
+++ mysql.pyconf 2012-10-08 22:43:14.000000000 +0900
@@ -460,5 +460,22 @@
metric {
name = "mysql_aborted_clients"
}
+
+ metric {
+ name = "mysql_innodb_pages_reads_per_sec"
+ }
+
+ metric {
+ name = "mysql_innodb_pages_creates_per_sec"
+ }
+
+ metric {
+ name = "mysql_innodb_pages_writes_per_sec"
+ }
+
+ metric {
+ name = "mysql_innodb_buffer_pool_hit_rate"
+ }
+
}
/usr/lib/ganglia/python_modules/DBUtil.py
--- DBUtil.py.orig 2012-10-08 19:46:19.000000000 +0900
+++ DBUtil.py 2012-10-08 23:14:34.000000000 +0900
@@ -65,6 +65,7 @@
dict.__repr__(self))
import MySQLdb
+import re
def longish(x):
if len(x):
@@ -178,6 +179,14 @@
innodb_status['pages_created'] = longish(istatus[4])
innodb_status['pages_written'] = longish(istatus[6])
+ elif re.match('.*? reads/s, .*? creates/s, .*? writes/s', line):
+ innodb_status['pages_reads_per_sec'] = float(istatus[0])
+ innodb_status['pages_creates_per_sec'] = float(istatus[2])
+ innodb_status['pages_writes_per_sec'] = float(istatus[4])
+
+ elif "Buffer pool hit rate" in line:
+ innodb_status['buffer_pool_hit_rate'] = float(istatus[4]) / 1000
+
# ROW OPERATIONS
elif 'Number of rows inserted' in line:
innodb_status['rows_inserted'] = longish(istatus[4])
/usr/lib/ganglia/python_modules/mysql.py
--- mysql.py.orig 2012-10-08 19:50:56.000000000 +0900
+++ mysql.py 2012-10-08 22:45:56.000000000 +0900
@@ -1068,6 +1068,30 @@
'value_type':'uint',
'units': 'txns',
},
+
+ innodb_pages_reads_per_sec = {
+ 'description': "",
+ 'value_type':'float',
+ 'units': 'reads/s',
+ },
+
+ innodb_pages_creates_per_sec = {
+ 'description': "",
+ 'value_type':'float',
+ 'units': 'creates/s',
+ },
+
+ innodb_pages_writes_per_sec = {
+ 'description': "",
+ 'value_type':'float',
+ 'units': 'writes/s',
+ },
+
+ innodb_buffer_pool_hit_rate = {
+ 'description': "Buffer pool hit rate",
+ 'value_type':'float',
+ 'units': '',
+ },
)
update_stats(REPORT_INNODB, REPORT_MASTER, REPORT_SLAVE)