2014年1月4日土曜日

MySQL5.6で準同期レプリケーションを試す

MySQLの準同期レプリケーションを試す。基本は公式のマニュアル通り進める。
環境は以下の通り。
  • CentOS release 6.2
  • MySQL-server-5.6.14
MySQL準同期レプリケーションを構築する前に、まず非同期レプリケーションを作り、その後準同期レプリケーションを作る 。

作業の前提として、MySQLのインストールが終わり、バイナリログが出力できているものとする。

まずは非同期レプリケーションの構築

マスタ側での作業

レプリケーション用のユーザを作る
GRANT REPLICATION SLAVE ON *.* TO repl@'(スレーブのIP)' IDENTIFIED BY 'repl';
マスタのバイナリログの場所を控える
SHOW MASTER STATUS;
+----------------+-----------+--------------+------------------+-------------------+
| File           | Position  | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+----------------+-----------+--------------+------------------+-------------------+
| bin-log.000004 | 450002352 |              |                  |                   |
+----------------+-----------+--------------+------------------+-------------------+
出力結果の FileとPositionを控える

スレーブ側での作業

マスタの指定
CHANGE MASTER TO  
MASTER_HOST = '(マスタのIP)' , 
MASTER_USER = 'repl' , 
MASTER_PASSWORD = 'repl' ,
MASTER_PORT = 3306, 
MASTER_LOG_FILE = '(バイナリログのファイル名)' ,
MASTER_LOG_POS  = (バイナリログのポジション);
スレーブの開始
START SLAVE;
スレーブの状態確認
SHOW SLAVE STATUS\G;
→slave_IO_State: Waiting for master to send event ならOK

次に準同期レプリケーションの構築

マスタ側での作業

プラグインのインストール
INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
準同期レプリケーションの有効化
SET GLOBAL rpl_semi_sync_master_enabled = 1;
必要に応じて、準同期レプリケーションのタイムアウト(ミリ秒)を設定。タイムアウトが発生すると、動作が非同期になり、スレーブのackを待たなくなる。
SET GLOBAL rpl_semi_sync_master_timeout = 20000;
設定の確認
SHOW GLOBAL VARIABLES LIKE "rpl%";
+------------------------------------+----------+
| Variable_name                      | Value    |
+------------------------------------+----------+
| rpl_semi_sync_master_enabled       | ON       | →ONならOK
| rpl_semi_sync_master_timeout       | 20000    |
| rpl_semi_sync_master_trace_level   | 32       |
| rpl_semi_sync_master_wait_no_slave | ON       |
| rpl_stop_slave_timeout             | 31536000 |
+------------------------------------+----------+

スレーブ側での作業

プラグインのインストール
INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
準同期レプリケーションの有効化
SET GLOBAL rpl_semi_sync_slave_enabled = 1;
設定値の確認
SHOW GLOBAL VARIABLES LIKE "rpl%";
+---------------------------------+----------+
| Variable_name                   | Value    |
+---------------------------------+----------+
| rpl_semi_sync_slave_enabled     | ON       |→ONならOK
| rpl_semi_sync_slave_trace_level | 32       |
| rpl_stop_slave_timeout          | 31536000 |
+---------------------------------+----------+
状態の確認
SHOW STATUS LIKE 'Rpl_semi_sync%';
+----------------------------+-------+
| Variable_name              | Value |
+----------------------------+-------+
| Rpl_semi_sync_slave_status | OFF   |
+----------------------------+-------+
この状態ではまだIOスレッドが準同期モードになっていない。
そこで、IOスレッドを再起動する。
STOP SLAVE IO_THREAD;
START SLAVE IO_THREAD;
再度状態を確認
SHOW STATUS LIKE 'Rpl_semi_sync%';
+----------------------------+-------+
| Variable_name              | Value |
+----------------------------+-------+
| Rpl_semi_sync_slave_status | ON    |    ←準同期レプリケーションになった
+----------------------------+-------+

設定永続化

マスタ側のmy.cnfに追記
[mysqld]
rpl_semi_sync_master_enabled=1
rpl_semi_sync_master_timeout=20000 # 20 second
スレーブ側のmy.cnfに追記
[mysqld]
rpl_semi_sync_slave_enabled=1
※)プラグインを入れる前にこの設定を書いても怒られるだけなので注意。

準同期レプリケーションの動作確認

正常時

マスタ側でSHOW STATUSを叩いて状態を確認する
SHOW STATUS LIKE 'Rpl_semi_sync%';
| Rpl_semi_sync_master_clients               | 1        | ←クライアントが1つ見えている
| Rpl_semi_sync_master_status                | ON       | ←準同期で動いている

スレーブが停止した場合

スレーブが停止してしまうと以下のような状態になるだろう
SHOW STATUS LIKE 'Rpl_semi_sync%';
| Rpl_semi_sync_master_clients               | 0        | ←クライアントが見えていない
| Rpl_semi_sync_master_status                | OFF      | ←非同期になってしまっている
| Rpl_semi_sync_master_no_tx                 | 3        | ←スレーブからackが得られなかったトランザクション数が増加

スレーブが復旧して、バイナリログの転送が追いつくと、非同期から準同期に戻り、Rpl_semi_sync_master_status はONになる。

スレーブが遅い場合

スレーブが遅く、タイムアウトが発生してしまうと以下のような状態になるだろう

SHOW STATUS LIKE 'Rpl_semi_sync%';
| Rpl_semi_sync_master_clients               | 1        | ←クライアントは見えている
| Rpl_semi_sync_master_status                | OFF      | ←非同期になってしまっている
| Rpl_semi_sync_master_no_tx                 | 3        | ←スレーブからackが得られなかったトランザクション数が増加

2013年12月28日土曜日

FTPクライアントは転送が失敗してもリターンコードが0な理由をさぐる

会社の先輩から「FTPはファイル転送が失敗しても気付けないから気付けろ!」と注意を受けた。
 「そんな馬鹿な」と思って調べていくと、どうやらそれが「常識」らしい。。。

再現させてみた

とりあえず本当かどうか目で見るまで信じられなかったので、再現を試みることに。

意外とあっさり再現できた。

まずftp.confを用意する ftp.confの内容
open 192.168.1.2
user fetaro P@ssw0rd
bin
prompt
get CentOS-5.6-i386-bin-DVD.iso
bye
次に、設定ファイルをftpクライアントに食わせてコマンドを実行
# ftp -n < ftp.conf
この時、ファイル転送中にサーバをkillしたりすると、
[root@localhost ~]# ftp -n < ftp.conf
Interactive mode off.
OOPS: child died
[root@localhost ~]# echo $?
0
まじかよ!ほんとに0だ。
ちなみにサーバが起動していなくてもリターンは0だ。
なんて不親切なんだFTPクライアント!

なぜそうなっているのか


なぜこんなことになっているか気になったので、C言語はあまり得意じゃないけど、ソースコードを調べてみることにした。 ソースコードのRPMをダウンロード。
# wget http://ftp.redhat.com/redhat/linux/enterprise/6Server/en/os/SRPMS/ftp-0.17-54.el6.src.rpm
RPMをインストールして中身を確認。
# rpm -ivh ftp-0.17-54.el6.src.rpm
# cd rpmbuild/SOURCES/
# ls 
netkit-ftp-0.17-C-Frame121.patch
netkit-ftp-0.17-fprintf.patch
netkit-ftp-0.17-runique_mget.patch
(略)
netkit-ftp-0.17.tar.gz
パッチと本体が入っているので、本体を解凍。
# tar zxvf netkit-ftp-0.17.tar.gz
# cd netkit-ftp-0.17/ftp
# ls
Makefile  cmds.c  cmds.h  cmdtab.c  domacro.c  ftp.1  ftp.c  ftp_var.h  glob.c  glob.h  main.c  netrc.5  pathnames.h  ruserpass.c
main.c の中を見ていくと、main関数の最後はコマンドをパースする無限ループがある。
101 int
102 main(volatile int argc, char **volatile argv)
103 {
(略)
217         for (;;) { # ←ここがコマンドをパースする無限ループ
218                 cmdscanner(top);
219                 top = 1;
220         }
221 }
うーん。
この無限ループは抜け道がいないということは、cmdscanner関数の中のどこかでexitしているということになる。。。

C言語はこういう実装が普通なんだろうか、なんて追いにくいんだ。。。

この中を追って行ってもらちがあかなそうだったので、調査方法を変えてexitをgrepすることにした。
[root@localhost netkit-ftp-0.17]# grep -r "exit(" *
ftp/cmds.c:1505:                exit(1);
ftp/cmds.c:1732:        exit(0);
ftp/cmds.c:1790:        exit(1);
ftp/main.c:115:         exit(1);
ftp/main.c:175:                         exit(0);
ftp/main.c:180:                         exit(1);
ftp/main.c:207:                 exit(0);
意外に少なくexit(1)は4か所。
それぞれ見ていくとexit(1)に至る処理は以下の場合であることがわかった。

  •  "ftp: ftp/tcp: unknown service" のエラーが出るとき 
  •  "unknown option" のエラーが出るとき 
  •  shell関数の中 (ただしshell関数は呼ばれていなそう) 
  •  fatal関数の中 (Out of memoryの時っぽい) 

というわけで、上記の4パターン以外はftpクライアントは0でリターンするようだ。

結論!


FTPクライアントはメモリが溢れるか、オプションを間違えない限りは0リターン!
(と思われる)

ruby の ftpクライアント使おうっと。。。

2013年11月14日木曜日

MongoDBのEnterprise版って実は無料で落とせるんですよ

あまり知られていないけれども、MongoDBのEnterprise版って無料で落とせます。

普通に、MongoDB社のホームページに行って、一番下にあるDownload Enterprise MongoDB Editionのリンクをクリックして、名前などを入れれば落とす画面に行けます。

MongoDB Enterprise版だとSNMPができるので、それを触ってみたくて落としました。
他にもEnterprise版はケルベロス認証にも対応しているみたいだけど、これは誰得なんだろう。


ちなみに同じページからEnterprise版のMongoDBだけでなく、MMS(MongoDB Monitoring System)のオンプレ版のRPMもダウンロードできます。

これはわざわざインターネットのMMSを使わないでも自前でMMSが使えるらしいので、ぜひ試してみたいが、それは今度の機会に。

2013年3月26日火曜日

ZabbixでMongoDBを監視する

表題の通りZabbixでMongoDBを監視してみようと思います。 環境
  • Zabbix Server
    • CentOS release 6.2 (Final)
    • zabbix-server 1.8.16-1.el6.JP.x86_64
    • mikoomi mongodb plugin (Rev 78)
  • MongoDB & Zabbix Agent
    • CentOS release 6.3 (Final)
    • MongoDB 2.2.1

はじめに

今回は、mikoomiさんに作っていただいたMongoDB Zabbixテンプレートを使います。
仕組みとしては、zabbixのextentionにMongoDBドライバをつかったPHPのスクリプトを置き、PHPのスクリプトがMongoDBに接続して、各種ステータスをクエリでとってきて、zabbixに渡すというもの(zabbix-agentは使いません)。 これにより、時系列でのクエリ件数やらいろんな統計情報が取得できます。

[処理シーケンス]
Zabbix --> Zabbixテンプレート --> PHPスクリプト --> MongoDB-PHPドライバ --> MongoDB

手順

基本的にmikoomiさんブログ通り進めていきます。 ZabbixとMongoDBのインストールは割愛します。

MongoDB-PHPドライバのインストール

まず、必要なライブラリをyumでインストール。
# yum install php-devel php-pear gcc make
次に、Mongo-phpドラインをインストール
# pecl install mongo
最後に/etc/php.iniに以下の行を追加。
extension=mongo.so
MongoDB-PHPドライバの稼働確認には以下のスクリプトを書いて、phpで実行し、成功するかどうかを確認すればOKです。
<?php
new MongoClient("mongodb://server:27017");
?>

Zabbix-MongoDB監視テンプレートのインストール

まず、mikoomiさんの作ったphpとshをzabbixのexternalscriptsに置きます(私がとったときはSVNのリビジョンは78でした。) そして、実行権限を与えます。
# cd /etc/zabbix/externalscripts/
# wget http://mikoomi.googlecode.com/svn/plugins/MongoDB%20Plugin/mikoomi-mongodb-plugin.php
# wget http://mikoomi.googlecode.com/svn/plugins/MongoDB%20Plugin/mikoomi-mongodb-plugin.sh
# chmod 755 mikoomi-mongodb-plugin.*
# chwon zabbix:zabbix mikoomi-mongodb-plugin.*
次に、このZabbixテンプレートのXMLをダウンロードして、zabbixのテンプレートに追加します。これで完了です。

MongoDBのサーバをZabbixAgentとして登録

まず、Zabbixのホストを追加して、「リンクしているテンプレート」に「Template_MongoDB」を選択します。
次に、これが唯一のハマりどころ(※)ですが、「マクロ」のところに、以下の二つの値を定義します。
  • マクロ = "{$SERVER}" , 値 = MongoDBのサーバのIPアドレス
  • マクロ = "{$PORT}" , 値 = MongoDBのポート番号

これで以下の図のようにMongoDBの各種統計情報がとれていると思います。


※)ハマりどころについて

mikoomiさんのブログには{$MONGODB_HOSTNAME}、{$MONGODB_PORT}、{$MONGODB_ZABBIX_NAME}の3つの値をマクロにセットしろと書いてあるんですが、これだとうまくいきません。phpやshにうまく引数が渡りません。
テンプレートのXMLをみると
item type="10" key="mikoomi-mongodb-plugin.sh[-h {$SERVER} -p {$PORT} -z {HOSTNAME}]" value_type="3"
と書いてあるので、ここに合わせて{$SERVER}と{$PORT}を定義したところうまく動きました。

2013年1月5日土曜日

git pushでThe requested URL returned error: 403

githubにpushしようとしたところ、以下のエラーがでた。
The requested URL returned error: 403 
これはgitのプロトコルをsshではなくhttpでクローンしたため、pushすることができなかった。sshでクローンしたら問題なくできた。

こんな単純なことで結構はまってしまいましたので、情報共有まで。

2012年11月23日金曜日

逆引きKVM(Kernel-based Virtual Machine)

この記事はKVM(Kernel-based Virtual Machine)の逆引きTipsです。 CentOS 6.3のKVMを基にしています。


最小構成のCentOS 6.3 64bitにKVMをインストール

CentOS 6.3 64bitを最小構成でインストールする
SELinuxを切る
# setenforce 0
# vi /etc/sysconfig/selinux
---
SELINUX=disabled
---
Firewallを切る
# /etc/init.d/iptables stop
# chkconfig iptables off
ネットワークインターフェースをブリッジにする
# vi /etc/sysconfig/network-scripts/ifcfg-eth0
---
DEVICE=eth0
ONBOOT=yes
BRIDGE=br0
---
# vi /etc/sysconfig/network-scripts/ifcfg-br0
---
DEVICE=br0
ONBOOT=yes
TYPE=Bridge
IPADDR=192.168.1.2
NETMASK=255.255.255.0
GATEWAY=192.168.1.1
---
# /etc/init.d/network restart
# ifconfig eth0 0.0.0.0 promisc up
kvmをyumで入れる
# yum -y groupinstall "Virtualization" "Virtualization Client" "Virtualization Platform" "Virtualization Tools" "X Window System"
virt-manager用に日本語fontを入れる
# yum -y install "vlgothic-p-fonts"
mDNS クライアントの作成失敗のエラー回避のためavahiを入れる
# yum -y install avahi
# /etc/init.d/messagebus restart
# /etc/init.d/avahi-daemon restart
# chkconfig messagebus on
# chkconfig avahi-daemon on
# /etc/init.d/libvirtd start
libvirtdの起動
# /etc/init.d/libvirtd start
# chkconfig libvirtd on

WindowsからGUI(virt-manager)でKVMを管理する

Linux付属の仮想マシンマネージャ(virt-manager)を利用します。
sshのX11 Forwadingという機能で、仮想マシンマネージャのX Windowをローカルに転送します。
手順
  • X11サーバをクライアントに入れます (xmingがお勧め)
  • X11サーバを起動します
  • sshクライアントで、X11のフォワーディングを有効にする
    • puttyならば「メニュー」→「接続」→「SSH」→「X11」→「X11フォワーディングを有効にする」をチェック
    • teratermならば「設定」→「SSH転送」→「リモートの(X)アプリケーションをローカルのXサーバに表示する」をチェックして、設定を保存。再度teratermを立ち上げる必要あり。
  • その状態で sshでKVMホストにログイン
  • ログインしたら「virt-manager」とコマンドを打てば、仮想マシンマネージャが起動します。
# virt-manager

MacからGUI(virt-manager)でKVMを管理する

Linux付属の仮想マシンマネージャ(virt-manager)を利用します。
sshのX11 Forwadingという機能で、仮想マシンマネージャのX Windowをローカルに転送します。
手順
KVMにssh。その際X11を飛ばすためにオプション -Xをつける
# ssh -X root@(KVMホスト)
virt-magagerを起動すると、Macに画面だけ飛んできます。
# virt-manager
注意
仮想マシンのコンソールにアクセスしたときに alt+ctrlが効かなくてマウスを出せなくなるので、
ユーザのホームディレクトリに .Xmodmapを作成して、下の設定する必要があります
# vi ~/.Xmodmap
---
clear Mod1
keycode 66 = Alt_L
keycode 69 = Alt_R
add Mod1 = Alt_L
add Mod1 = Alt_R
---

コンソールからvirshでKVMを管理する

コンソールでKVMを管理する場合、Linux付属のvirshコマンドを使います

起動中の仮想マシン一覧表示

# virsh list

全ての仮想マシン一覧表示

# virsh list --all

仮想マシンの情報

# virsh dominfo (仮想マシン名)

仮想マシンの起動

# virsh start (仮想マシン名)

仮想マシンの停止

# virsh shutdown (仮想マシン名)

仮想マシンの強制停止(電源OFF)

# virsh destroy (仮想マシン名)

仮想マシンの一時停止

# virsh suspend (仮想マシン名)

仮想マシンの一時停止の再開

# virsh resume (仮想マシン名)

仮想マシンの保存(メモリをファイルに書き出す)

# virsh save (仮想マシン名) (保存ファイル名)

保存した仮想マシンの復元(ファイルからメモリに戻す)

# virsh restore (保存ファイル名)

仮想マシンの構成変更(メモリ量変更など)

  1. 仮想マシン停止
  2. /etc/libvirt/qemu/(仮想マシン名).xml を変更
  3. 変更を反映
    # virsh define /etc/libvirt/qemu/(仮想マシン名).xml
  4. 起動

仮想マシンのコンソールログインする設定

以下の設定を入れる これをすると、ホストOSからvirsh consoleで接続できるようになる。
grubの設定ファイル変更(CentOS 5系&6系共に実施が必要)
# vi /etc/grub.conf
---
serial --speed=115200 --unit=0 --word=8 --parity=no --stop=1 # この行を追加
terminal --timeout=5 serial console # この行を追加
title CentOS (2.6.18-128.4.1.el5)
       root (hd0,0)
       kernel /vmlinuz (中略) console=ttyS0,115200n8 # console以降を追加
       initrd /initrd-2.6.18-128.4.1.el5.img
---
コンソール端末を作成 (CentOS 5 系のみで必要)
# vi /etc/inittab
---
S0:12345:respawn:/sbin/agetty ttyS0 115200 # この行を追加
1:2345:respawn:/sbin/mingetty tty1
---
コンソールからrootでログインできるようにする。(CentOS 5 系のみで必要)
# vi /etc/securetty
---
ttyS0 #追記
---

仮想マシンのコンソールに接続

# virsh console (ドメイン名)
※ 抜ける場合はctrl + ]

仮想マシンを起動&そのままコンソール接続

# virsh start (ドメイン名) --console

KVMの運用

仮想マシンのバックアップ

基本的には、以下の二つのファイルをバックアップしておけばOK
  • 仮想マシン設定ファイル
    • /etc/libvirt/qemu/(仮想マシン名).xml
  • 仮想ディスクイメージファイル
    • 上記設定ファイルにイメージファイルの場所は書いてあります
    • 通常は /var/lib/libvirt/images/(仮想マシン名).img

仮想マシンのバックアップからのリストア

  • 仮想ディスクイメージファイルを適切な場所(設定ファイルあるパス)に置く
    • 通常は /var/lib/libvirt/images/(仮想マシン名).img
  • 仮想マシン設定ファイルを適切な場所に置く
    • 通常は /etc/libvirt/qemu/(仮想マシン名).xml
  • 以下のコマンドで仮想マシン設定ファイルの読み込み
# virsh define (仮想マシン設定ファイル)

バックアップスクリプト

rubyのバックアップスクリプト作ったので、もしよかったら使ってください→ コチラ

VMWareの仮想ディスクマシンをKVM用に変換

vmwareの仮想ディスクイメージ(vmdk)をkvmに変換するときは以下のコマンドを打つ。
qemu-img convert (vmdkファイル) -O raw (kvmイメージファイル)

KVMのトラブルシューティング(CentOS6系)

mDNS クライアントの作成に失敗

/var/log/libvirt/libvirtd.logのエラーメッセージ
2012-07-17 15:47:49.240+0000: 15548: info : libvirt version: 0.9.10,
package: 21.el6_3.1 (CentOS BuildSystem <[http://bugs.centos.org>,]
2012-07-03-16:15:49, c6b8.bsys.dev.centos.org)
2012-07-17 15:47:49.240+0000: 15548: error : virNetServerMDNSStart:460
: 内部エラー mDNS クライアントの作成に失敗しました: Daemon not running
対応
# yum -y install avahi
# /etc/init.d/messagebus restart
# /etc/init.d/avahi-daemon restart
# /etc/init.d/libvirtd restart
# chkconfig messagebus on
# chkconfig avahi-daemon on
# chkconfig libvirtd on
参考

virt-managerの日本語fontが表示されない

fontが足りていない
対応
# yum install "vlgothic-p-fonts"

適切なエミュレーターを見つけられない

/var/log/libvirt/libvirtd.logのエラー
2012-07-24 01:43:07.595+0000: 2126: error : qemuCapsExtractVersion:1566 : 内部エラー x86_64 の適切なエミュレーターを見つけられません
対応
# ln -s /usr/libexec/qemu-kvm /usr/bin/qemu-system-x86_64
# /etc/init.d/libvirtd restart

KVMのカーネルモジュールが読み込まれない

KVM を利用できません。これは KVM パッケージがインストールされていない。また
は、KVM のカーネルモジュール (kvm.ko) が読み込まれていないことを意味します。
QEMU が使われるので動作が遅くなるでしょう。

warning: KVM is not available. This may mean the KVM package is not installed, or the KVM kernel modules are not loaded. Your virtual machines my perform poorly
一時的な対応はカーネルモジュールの読み込めばOK
# modprobe kvm
# modprobe kvm-intel
再起動後も設定を継続させる場合は、 /etc/rc.d/rc.sysinitに以下を記載
modprobe kvm
modprobe kvm-intel

仮想マシンがKVMの内部のネットワークから外に出れない。

仮想マインのインターフェースがプロミスきゃすになっていない
対応
# ifconfig eth0 0.0.0.0 promisc up

2012年11月20日火曜日

Rubyでバッチを書きやすくするフレームワーク作りました

私はよくRubyでバックアップやディレクトリ同期等のバッチスクリプトを書くのですが、
ログ出力とか設定ファイル読み込みとか勝手にやってくれるものがほしかったので、作りました。

コチラです→RBatch:Ruby-baseバッチスクリプトフレームワーク