2013-09-27
MySQL Cluster Casual Talks
一応仕事でMySQLをよく触っている身として、軽く検証はしてみたものの、担当している業務では参照メインのDBが多いこともあって実運用では使ったことがなかったMySQL Cluster。改めて利点も欠点も聞いておきたいと思ったのと、会社からすぐ近くのGMOさんが会場ということもあって参加してみた。
MySQL Clusterの本も書かれている@nippondanjiこと奥野さんから、MySQL Clusterは何に向いていて、どう使えばよさを引き出せるのかを聞いたうえで、そのサポートを受けながら4年間運用されている@tsakuradaさんの実運用上のハマりどころを聞くことで、どういうところにMySQL Clusterを使えばいいのかイメージが浮かんだので、非常に今後の役に立ちそう。
発表者のみなさま、会場提供していただいたGMOのみなさまありがとうございましたm(__)m さくらのクラウド2万円分クーポンももらったし、GMOクラウドのキャラクタのシールもたくさんもらったので宣伝しますw
既にまとめはgarage-kid さんが書いてくれている ので、これは個人的なポイントのまとめ。
@RKajiyama さん MySQL Cluster大地に立つ!「5.6とは違うのだよ、5.6とは!」
MySQL Clusterの概要
使用しているユーザ
元々はモバイル通信の位置情報をリアルタイムかつ高可用性を持って保存するためにできた
SQLインタフェースは昨今ゲーム業界などで使われ始めてから追加されてきた機能
艦○れでも使われている?
@nippondanji さん カジュアルにMySQL Clusterを使ってみよう
データノード、SQLノード、管理ノードの3種類からなる
1台だけならndb(MySQL Clusterのエンジン)よりInnoDBの方が速い
ただしNDB APIを使うならClusterの方が圧倒的に速い
ノードを増やすとスケールしていく点に優位性があるが、いつでも速くなるとは限らない(後述)
新しいバージョン使いましょう
シェアードナッシング型
データノードは2台ペアでノードグループを構成
データをフラグメントに分けて、それをノードグループ内で同期レプリする
RAID10的な感じでグループ内で1台落ちてもデータは保全される
InnoDBとは特性が違う & いつでもノードを増やせばスケールするとは限らない
主キーを使った検索 → データノード数に応じてスケール
(少数の行を取ってくる)スキャンは苦手
データがノードに分散しているので複数ノードをスキャンする必要があるため
フェッチするレコードが多いと並列処理できるので早くなる
Engine Condition Pushdown : where句部分を丸ごとデータノードに渡して並列処理して高速化する仕組み
sysbenchをただ走らせると遅いのはこのせい
ユーザ定義パーティション
スキャンを高速化させる仕組み
2つのテーブルの関連を考慮してデータノードへの分散を定義すれば、読み書きを特定のノードに抑えられるので高速に
レプリケーション
ndbに不得意な処理があるならInnoDB のスレーブを作るという手もある
データノードが書き込みしたことをSQLノードに通知し、それをbinlogに書き込んでスレーブに送るという仕組み
通知を受け取るのがbinlog injector thread
インメモリDBだけど永続化処理が多いのでディスク書き込み多い=速いディスクがいい
blobを別テーブルに保存するのでJOIN的処理が発生して遅くなる
NoSQLインタフェースを使えば爆速
各種言語のインタフェースあり
InnoDBのmemcachedインタフェースよりMySQL Clusterの方が現時点では賢い
まとめ(MySQL Clusterの使いどころ)
大量の更新をさばきたい
HA機能が欲しい
高速JOINしたい
@tsakurada さん MySQL Clusterと丸4年の付き合いを振り返ってのよもやま話と、Version 7.3への期待(もっとユーザが増えるといいな~)
使用開始時の期待と使ってみたギャップ、現在の期待
インメモリだから速いはず
参照に関していえばFIO+InnoDBでも変わらないかも
スケールアウト簡単
高可用性
ライセンスがGPLでオープンソース
7.3でInnoとの互換性が上がって期待
サーバの構成
SQLノードと管理ノードは同居してもよい、データノード2台と合わせて最低4台からが現実的
データが多いならデータノードを増やす(が制約はあるので注意)
アクセスが多いならSQLノードを増やす。制約は少ないので割と簡単
せっかくのMySQL ClusterなんだからHW構成上もSPOFを減らそう
クエリがキャンセルされた時それを検出して後続処理をやるアプリ作り込み必須
InnoDBとの組み合わせ
Innoと同じ感覚でテーブル設計してもよいか?
場合による。最近のバージョンではやってみる価値あり
InnoDBスレーブとの組み合わせ
ハマりどころ(資料が詳しいのでそちら参照)
GCP Stop
ローリングリスタート
ボトルネックが見えづらい
データのライフサイクルを考えよう
リストアが大変
4年間でだいぶ地雷を踏んだのでもう大丈夫w 皆さんMySQL Cluster使いましょう
@yyamasaki1 さん MySQL Cluster Auto-Installerのデモ
Auto-Installer簡単なので使いましょう
ブラウザベースでぽちぽちやればインストール可能
初期パラメータをいくつかいじった方がいい
@yoku0825 さん ウチがNDBCLUSTERを使わない理由をもう一度考える
MySQL Clusterというと紛らわしいので、NDB Clusterと言いましょう<table border=0>
</table>
2013-06-12
Nagiosの設定ファイルをパースする簡単な方法ないかなと思って調べてたら、pynag という超便利なパッケージ発見。日本語の情報ほとんどないけど、Fedoraの標準パッケージになっているってことは割と一般的なんだろうか。
Nagiosのプラグインを簡単に作りたい
Nagiosの設定ファイルをパースして値を取りたい
Nagiosの設定をコマンドラインやプログラムから取得・変更したい
って時に重宝する。pynagという名の通り、pythonで書かれている。公式ページのそのまんま訳に近いけど、使い方ご紹介。
インストール
Fedoraの最近のバージョンには標準で含まれており、CentOSやRHELならepelを使えるようにしておけばyumでインストールできる。
$ sudo yum install http://ftp-srv2.kddilabs.jp/Linux/distributions/fedora/epel/6/x86_64/epel-release-6-8.noarch.rpm
$ sudo yum install pynag
pipが使えるならpipでもインストールできる。
設定ファイルのパース
pynagパッケージのModelモジュールを使えば、 /etc/nagios など代表的なパスから nagios.cfg を探し出して読み込んでくれる。含まれるホストとそのホストに関連づいたContact groupを表示する例。
from pynag import Model
# Get all hosts
all_hosts = Model.Host.objects.all
for i in all_hosts:
print i.host_name, i.contact_groups
設定書き換え
同じようにして、設定を保存することもできる。ホスト名がexamplehostのホストのContact groupを「mycontactgroup」にする例。
from pynag import Model
services = Model.Service.objects.filter(host_name='examplehost')
for i in services:
i.contactgroups = "mycontactgroup"
i.save()
ステータスの取得
監視結果が保存されているstatus.datファイルのパースもしてくれるので、ホストやサービスのステータス取得もできる。
ホストグループ名とサービス名を引数に与えてやると、ホストグループに所属するホスト全てに関するサービスのステータスを返すスクリプト。
import sys
from pynag import Model
from pynag.Parsers import status
argvs = sys.argv
argc = len(argvs)
status = status()
if (argc != 3):
print
print("Usage: ./%s hostgroup service" % argvs[0])
print
sys.exit()
hostgroups = Model.Hostgroup.objects.filter(hostgroup_name=argvs[1])
for hostgroup in hostgroups:
print("Hostgroup: %s" % hostgroup.hostgroup_name)
print("Member:")
for host in hostgroup.members.split(','):
print("%s %s" % (host, status.get_servicestatus(host, argvs[2])['current_state']))
status.datのパースにはやや時間がかかるので、監視対象サーバの台数が多いと使用に耐えない。そういう場合は、高速にステータスを取得できるMK Livestatus と組み合わせることもできる。インストール方法は割愛するのでWebページを参照するべし。MK Livestatusを使って、上のスクリプトと同じようにホストグループとサービス名を引数に与えてホストのステータスを取得する例。
import sys
from pynag import Model
from pynag.Parsers import mk_livestatus
argvs = sys.argv
argc = len(argvs)
livestatus = mk_livestatus()
if (argc != 3):
print
print("Usage: ./%s hostgroup service" % argvs[0])
print
sys.exit()
hostgroups = Model.Hostgroup.objects.filter(hostgroup_name=argvs[1])
for hostgroup in hostgroups:
print("Hostgroup: %s" % hostgroup.hostgroup_name)
print("Member:")
for host in hostgroup.members.split(','):
print(host)
print(livestatus.get_service(host,argvs[2])['host_services_with_info'])
コマンドラインから使う
Pythonのスクリプト内だけでなく、pynagコマンドとしてシェルから直接使うこともできる。where句で対象を絞ることが可能。
全ホストオブジェクトを表示する例。
$ pynag list where object_type=host
object_type shortname filename
——————————————————————————-
host server01 /etc/nagios/Default_collector/hosts.cfg
host server02 /etc/nagios/Default_collector/hosts.cfg
(中略)
———-123 objects matches search condition———————————-
MySQL_Connect_cというサービスのチェックコマンドを表示する例。
$ pynag list effective_command_line where service_description=MySQL_Connect_c
effective_command_line
——————————————————————————-
/usr/lib64/nagios/plugins/check_mysql_health -hostname -user nagios -password nagios -mode connection-time -database test -critical 1
———-1 objects matches search condition————————————
もちろんコマンドラインから設定の変更も可能。ホスト名server01をserver02に変更する例。
$ pynag update set host_name=server02 where host_name=server01 and object_type=host
where句にはlikeのような部分一致が使えないようだ。複雑なクエリを発行したいときは、pythonスクリプトとして作った方がいいかもしれない。コマンドラインでの使い方はWiki にもう少し詳しく書いてある。
Nagiosプラグイン作成時に使う
個人的に一番ツボなのがこの機能。自作のプラグインに、Nagiosのプラグインを書く際のガイドラインに準じた引数の処理などを簡単に加えることができる。
/proc/loadavgの中身から、ロードアベレージを引いてくる簡単な例。
#!/usr/bin/python
import os,sys
## プラグインのオプションを生成
np = Plugin()
## コマンドライン引数を追加
np.add_arg("l","load-file", "Enter a load average file", required=None)
## プラグインをアクティベート
np.activate()
## load-fileオプションが指定されたらそのファイルからLAを読み込む
## デバッグと、add_argメソッドのサンプルとして
if np['load-file']:
load_file = np['load-file']
else:
load_file = "/proc/loadavg"
## ちょっとしたエラーチェック
if not os.path.isfile(load_file):
np.nagios_exit(np.UNKNOWN, "Missing Load average file %s" % load_file)
## チェックに使う値を取得
current_load = os.popen("cat %s" % load_file).readline().split()[0]
## パフォーマンスデータを付加
np.add_perfdata("1min", current_load)
## チェック実行
np.check_range(current_load)
上のスクリプトをcheck_cpu.pyとして保存しておく。5行目のPlugin()で、プラグインとして必要なオプションが用意されるので、以下のようにスクリプトに引数を指定しないで実行しただけで、簡易ヘルプが表示される。
$ ./check_load.py
usage: check_load.py [options]
check_load.py: error: You must provide a WARNING and/or CRITICAL value
さらに、-hオプションをつけると、詳細なヘルプが表示される。
$ ./check_load.py -h
usage: check_load.py [options]
options:
-h, -help show this help message and exit
-l LOAD-FILE, -load-file=LOAD-FILE
Enter a load average file
-v VERBOSE, -verbose=VERBOSE
Verbosity Level
-H HOST, -host=HOST Target Host
-t TIMEOUT, -timeout=TIMEOUT
Connection Timeout
-c CRITICAL, -critical=CRITICAL
Critical Threshhold
-w WARNING, -warning=WARNING
Warn Threshhold
ここで、スクリプト内の8行目、add_argメソッドで追加したオプションが、ヘルプの中に「-l LOAD-FILE, -load-file=LOAD-FILE」として表示されている。また、-Hでの監視対象ホスト指定や-c,-wによる閾値の指定オプションがはじめから用意されていることがわかる。自作スクリプトを書くたびにオプションのパースから書いていた事を考えれば、なんという簡単さ!
もちろん、ヘルプでみたとおりのオプションを与えてやれば、プラグインとして使用可能。
$ uptime
13:16:19 up 396 days, 22:32, 3 users, load average: 0.60, 1.08, 1.04
$ ./check_load.py -w 1 127.0.0.1
OK: 0.60 is inside warning=1 and critical=None | '1min'=0.60;;;;
元々やりたかったのは「同一ホストグループ内のある台数のチェック失敗まではWARNING、その台数以上のチェック失敗でCRITICALアラートを上げたい」ということだったのだが、以下のような短いプラグインスクリプトで実現できた。
#!/usr/bin/python
import sys
from pynag import Model
from pynag.Parsers import status
from pynag.Plugins import simple as Plugin
np = Plugin()
status = status()
np.add_arg("g", "hostgroup", "Hostgroup name", required=1)
np.add_arg("s", "service", "Service name", required=1)
np.activate()
errornum = 0
hostgroups = Model.Hostgroup.objects.filter(hostgroup_name=np['hostgroup'])
for hostgroup in hostgroups:
for host in hostgroup.members.split(','):
if status.get_servicestatus(host, np['service'])['current_state'] != "0":
errornum = errornum + 1
np.add_perfdata("WARN/CRIT", errornum)
np.check_range(errornum)
2台のチェックに失敗している時の例。
# 2より多いとwarn、3より多いとcrit
$ python check_wipeout.py -hostgroup=common_dbs -service=ifSpeed_eth0_w -w 2 -c 3
OK: 2 is inside warning=2 and critical=3 | 'WARN/CRIT'=2;;;;
$ echo $?
# 1より多いとwarn、3より多いとcrit
$ python check_wipeout.py -hostgroup=common_dbs -service=ifSpeed_eth0_w -w 1 -c 3
WARNING: 2 is outside warning range: 1 | 'WARN/CRIT'=2;;;;
$ echo $?
1
# 1より多いとcrit
$ python check_wipeout.py -hostgroup=common_dbs -service=ifSpeed_eth0_w -c 1
CRITICAL: 2 is outside critical range: 1 | 'WARN/CRIT'=2;;;;
$ echo $?
2
というわけで、pynagがあるとNagiosプラグインを書くのが超簡単になる! pynag万歳!
ドキュメントはGithub上のWiki を見るとよい。Wikiからだと分からない部分も多いが、ソース自体 はそれほど複雑ではないので読んでみればわかるのでは。
2013-06-10
Nagiosの設定ファイルを編集するツールには、NagiosQL などいくつかある が、あれこれ触ってみた感じnconf がよさげだった。JQueryなどを適宜使って動きは軽快だし、メニューの構成などもストレートで直感的に使えるところがNagiosQLよりも気にいった。
監視の設定はできる限り自動生成するくらいが大規模なシステムでは最近の主流かもしれないが、そこまでの大きさのシステムではない時でも、設定ファイルを手で編集するのはいただけない。Nagiosを使うならとりあえずnconfも一緒に入れて設定すべし。
最新版が2011年で開発が活発でないのは気になるが、基本的な機能は網羅されており不自由は感じないので、しばらく使っている。ってことで、CentOS6.4にNagiosとnconfをインストールして、監視を始めるまでの手順。
Nagiosのインストール
epelリポジトリにNagiosが含まれているので、epelをインストールしてからNagiosと、監視に使うプラグインをインストール。
$ sudo yum install http://ftp-srv2.kddilabs.jp/Linux/distributions/fedora/epel/6/x86_64/epel-release-6-8.noarch.rpm
$ sudo yum install nagios nagios-plugins
Nagiosと一緒に、PHPやPerl、Apacheなども一緒にインストールされる。
$ sudo /etc/init.d/nagios start
$ sudo /etc/init.d/httpd start
NagiosとApacheを起動したら、 http://(サーバのIP)/nagios をブラウザで開いて、ユーザ名 nagiosadmin、パスワード nagiosadmin でログインするとNagios管理画面が開ければNagiosの準備は一旦終わり。
MySQLのインストール
nconfの特徴として、設定をMySQLに入れておいて、そこからNagiosの設定ファイルを生成することが挙げられる。そのためにMySQLをインストール。nconfはPHPで書かれており、PHPからMySQLへ接続するためのphp-mysqlも一緒にインストール。
$ sudo yum install mysql-server php-mysql
mysql, mysql-libsなどもインストールされる。
この辺 参照して、/etc/my.cnf の [mysqld] セクションに最低限の設定をしてから、MySQLを起動。
$ sudo /etc/init.d/mysqld start
nconf用データベースと、MySQLへ接続するためのアカウントも作成。以下の例では、データベース名がnconf、ユーザ名がnconf、パスワードはnconfpasswordとしているが、任意のものにできるので適宜変更すべし。
$ mysql -uroot
mysql> create database nconf;
Query OK, 1 row affected (0.00 sec)
mysql> grant SELECT, INSERT, UPDATE, DELETE, CREATE, ALTER, DROP on nconf.* to 'nconf'@'localhost' identified by 'nconfpassword';
Query OK, 0 rows affected (0.00 sec)
nconfのインストール
nconfのサイト のDownloadからnconf-1.3.0-0.tgzをダウンロードして適当なディレクトリに配置。CentOSのApacheのDocumentRootに展開する。
cd /var/www/html
sudo tar zxvf /fuga/hoge/nconf-1.3.0-0.tgz
chown -R apache. nconf
インストールに必要な設定は、GUIで行える。http://(サーバのIP)/nconf/ をブラウザで開く。
ここで画面がforbiddenになる場合、SELinuxが有効になっている可能性がある(/var/log/audit/audit.logにその旨出力されているはずなので確認すべし)。そんな時は頑張って動くように設定するか、そっと/etc/sysconfig/selinuxのSELINUX=enabledをdisabledに書き換えてOSを再起動する。
必須のパッケージが全てインストールされていれば、最初の画面でOKが並ぶので、Nextをクリック。
前項でMySQLに作成したデータベース名とアカウントを入力してNextを押すとチェックが走るので、OKが並んだらNext。
nconfの接続に認証を必要とするかどうかの設定。後でも変更できるので一旦そのまま(AUTH_ENABLEDがFALSE)でNext。
全て完了したらFinishをクリック。
インストールしたディレクトリ内のファイル、ディレクトリを削除しろというメッセージが出るので、リネームする(別に使わないと思うが一応)。
$ cd /var/www/html/nconf
$ sudo mv INSTALL INSTALL.org
$ sudo mv INSTALL.php INSTALL.php.org
$ sudo mv UPDATE UPDATE.org
$ sudo mv UPDATE.php UPDATE.php.org
ここまででnconfの設定画面にはアクセスできるようになる。
nconfの設定・Nagiosの追加設定
前述の通りnconfはMySQLに設定を書いていて、それをNagiosの設定ファイルとして書き出し、Nagiosを再起動して設定を反映させるところまでnconfでやることができる。そのための追加設定がここから。
/var/www/html/nconf/config/nconf.php (nconfのメイン設定ファイル)を以下の通り書き換え。
23行目。Nagios本体のパスを指定する。
\# 変更前
define('NAGIOS_BIN', '/var/www/html/nconf/bin/nagios');
\# 変更後
define('NAGIOS_BIN', '/usr/sbin/nagios');
75行目。Nagiosのメイン設定ファイル(nagios.cfg)の構文チェックを無効化。手元の環境では、有効にしてしまうと、正しいはずの設定ファイルのチェックがどうしてもエラーになってしまったのでやむなく。
\# 変更前
define('CHECK\_STATIC\_SYNTAX', 1);
\# 変更後
define('CHECK\_STATIC\_SYNTAX', 0);
80行目。この配列に入っているユーザが、通知先などに自動で追加されてしまうので削除。
\# 変更前
$SUPERADMIN_GROUPS = array ("+admins");
\# 変更後
$SUPERADMIN_GROUPS = array ("");
/var/www/html/nconf/config/deployment.ini (nconfの自動デプロイ設定ファイル)を以下の通り書き換え。
「;; LOCAL deployment ;;」の下、6行目から29行目までの以下のセクションの行頭のセミコロンを外して有効化。
;[extract config]
;[copy collector config]
;[copy global config]
;[copy nagios.cfg]
また、nconfが生成するNagios設定ファイルのアーカイブを指定する、8行目を以下のとおり変更。
\# 変更前
source_file = "/var/www/nconf/output/NagiosConfig.tgz"
\# 変更後
source_file = "/var/www/html/nconf/output/NagiosConfig.tgz"
Apacheの起動ユーザapacheがNagiosを再起動できるようにsudoersを編集。
以下の1行を末尾に追加。
apache ALL=(ALL)NOPASSWD: /etc/rc.d/init.d/nagios reload
nconfが生成した設定ファイルをNagiosの設定ファイルディレクトリ(/etc/nagios)に配置できるように細々した設定。
$ cd /etc/nagios
$ sudo mkdir Default_collector global
$ sudo chown apache. Default_collector global nagios.cfg
nconfからnagios.cfgを編集・配置することもできるので、一応nconfのディレクトリ以下にnagios.cfgを置いておく。
$ sudo cp /etc/nagios/nagios.cfg /var/www/html/nconf/static_cfg/
nconfが配置するファイルを設定ファイルとして使用するように、コピーした先の/var/www/html/nconf/static_cfg/nagios.cfgを編集。
\# cfg\_fileとcfg\_dirを全てコメントアウトして以下の2行を追加。
cfg_dir=/etc/nagios/global
cfg\_dir=/etc/nagios/Default\_collector
これで設定はおしまい。ApacheとNagiosを再起動して一息つく。
$ sudo /etc/init.d/httpd stop
$ sudo /etc/init.d/nagios restart
$ sudo /etc/init.d/httpd start
動作確認
http://(サーバのIP)/nagios/ を開いて、左側のCurrent Status → Servicesをクリックすると、Nagios側では以下のようにデフォルトでlocalhostの監視のみが設定されている。
一方、 http://(サーバのIP)/nconf/ を開いて、左側のBasic Items → Hostsをクリックすると、nconf側ではlocalhost以外にサンプルとしてhplj2605dnなど合わせて4台分の設定が入っていることが分かる。
ここで、nconfの左側のメニューからBasic Items → Generate Nagios configをクリックすると、設定ファイルが生成される。以下の画面で「Deploy」をクリックする。
以下の画面のように、全てOKになれば、設定ファイルのデプロイとNagiosの再起動が終わっているはず。
ここで、Nagiosの画面を開くと、以下のようにnconfに入っていた設定が有効になって、ホストが増えていれば成功。
後は、nconfからあれこれ設定を入れて監視を始めるべし。