カテゴリー別アーカイブ: Zabbix

AWS RDSのログ監視をZabbixで。

| コメントをどうぞ

AWSのRDSはCLIツールでログの取得が出来きるのでZabbixサーバにRDSのログを取得して通常のログ監視設定と似たような感じで監視をします。ZabbixでRDSのログ監視をするには以下の条件が必要になります。

● RDSのログを取得できる権限(IAM)を持っていること。
● CLIツールを導入していること。

正確にはCLIツール無くてもプログラム書ける人ならとってこれるようですが、自分のような非プログラマでもAPIにアクセスしてデータを取得できるCLIツールをリリースしてくれているので使わない手は無いです。
CLIツールは複数の言語版がありますが、JAVA版とPython版を使います。

何故2種類使うのか?となりますが、前にJAVA版で色々とCLIツールで監視データ取得したりバックアップ運用していたのですがJAVA版は重いのです。t2.microでZabbixを動かしていたのですが、CLIを使ったスクリプトを複数個動かすとCPULoadがかなり高くなってました。t2.microでZabbixを動かす事自体問題あるのですが、ブラウザでのアクセスは反応遅いけどもその状態で1年くらいZabbixが落ちたりもせずAWSの障害通知メールも飛ばしてくれてたので放置してましたが、去年の4月にチーム編成が変わって同じチームになった人から「Python版使ってますが重いと感じたことないですけど?」と言われて試してみたら「本当だ軽い・・・」今まで使ってたスクリプトをPython版に書きなおして現在に至るまでZabbixサーバが重くなったことはありませんでした。

AmazonLinuxには最初からPython版CLIツールがセットアップされてるくらいだしPython版のみで行こう!

・・・と思ったらログをtail出来る機能がJAVA版にはあったけどpython版はやり方がわからない。もしくは無いかもしれない。。
(aws-cli/1.3.18 Python/2.6.6のバージョンではよくわからなかった。)

その為、いつかPython版でRDSのログtailの方法がわかったらいつでも全部Python版に変更出来る用に最初の部分はPythonコマンドで実行してtailの部分はJAVA版で実行しています。

● Python版CLIインストール
AmazonLinuxなら最初から入っていますが、CentOSではインストールします。yumで入るので楽です。

# yum install python -y
# yum install python-devel -y
# yum install python-setuptools -y
# easy_install pip
# pip install awscli

次に認証に使うファイルが必要なので作成します。AWSのアクセスキーとシークレットアクセスキーを中に記述します。リージョンはRDSが動いているところにします。ファイル名はアカウント/サービスごとに分けると後で楽です。

# vi 任意の名前

[default]
aws_access_key_id=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
aws_secret_access_key=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
region=ap-northeast-1

認証ファイルの場所を設定します。

# export AWS_CONFIG_FILE=任意の名前で作成したファイル

コマンドのタブ補完が効かないので効くようにします。毎回補完出来るように.bash_profileに書いておくのも良さそうです。

# complete -C aws_completer aws

セットアップがうまく行ったかか確認します。ログファイルがずらっと表示されればうまく行っています。

# aws rds describe-db-log-files --db-instance-identifier RDS名 --output text

            UNIXエポック  ファイル名     
DESCRIBEDBLOGFILES      1425877196000   error/postgresql.log.2015-03-09-04      4470072
DESCRIBEDBLOGFILES      1425880791000   error/postgresql.log.2015-03-09-05      5148177
DESCRIBEDBLOGFILES      1425884399000   error/postgresql.log.2015-03-09-06      581115
DESCRIBEDBLOGFILES      1425887996000   error/postgresql.log.2015-03-09-07      105250
DESCRIBEDBLOGFILES      1425888531000   error/postgresql.log.2015-03-09-08      36301

「–output」で指定した形式で表示してくれます。「table」と指定するとteble形式、「text」と指定するとテキスト形式で表示してくれます。何も指定しないと「json」形式で表示されて見にくいです。(jqとかかまさないと見づらい)

● JAVA版CLIセットアップ
JAVA版CLIのセットアップ方法はこのブログでも他の人が紹介されているので省略します。(手抜き)

RDSのログをtailするだけだとAWS側で定期的(1時間ごと?)にローテされて見失うので一定間隔で
ログが新しくなったかチェックして最新のログを吐き出すスクリプトを作成します。

●RDSログをtailするスクリプト

#!/bin/sh

# EC2-APITools settings
export JAVA_HOME=/usr

# keys
export AWS_CREDENTIAL_FILE=クレデンシャルファイルのPATH
export AWS_CONFIG_FILE=configファイルのPATH

# RDS CLI setting
export AWS_RDS_HOME=/usr/local/rds
export EC2_REGION="ap-northeast-1"
export PATH=$PATH:$JAVA_HOME/bin:$AWS_RDS_HOME/bin

COMMAND=スクリプトの絶対PATH
DBINSTANCEID=RDSの名前
LOGDIR=ログを保管するPATH

LOG=`aws rds describe-db-log-files --db-instance-identifier $DBINSTANCEID --output text| awk  '{ print $2"\t"$3"\t"$4 }' | awk '{print substr($0,1,length($1)-3)"\t"$2"\t"$3}' | awk '{ print strftime("%Y/%m/%d %H:%M:%S",$1)" "$2" "$3 }' | tail -1 | awk '{print $3}'`

LOGFILENAME=`echo $LOG | sed 's/[a-z]*\///g'`

rds-watch-db-logfile $DBINSTANCEID --log-file-name  $LOG > ${LOGDIR}/$LOGFILENAME 2>&1 &


C=0
while [ $C = 0 ]

do

LOG2=`aws rds describe-db-log-files --db-instance-identifier $DBINSTANCEID --output text| awk  '{ print $2"\t"$3"\t"$4 }' | awk '{print substr($0,1,length($1)-3)"\t"$2"\t"$3}' | awk '{ print strftime("%Y/%m/%d %H:%M:%S",$1)" "$2" "$3 }' | tail -1 | awk '{print $3}'`

if [ $LOG != $LOG2 ];then

pgrep -f $LOG | xargs kill -9

$CMDPATH

fi

sleep 300

done

AWS側のローテはおそらく一時間に一回くらいのようですが、スクリプト内では5分に一回チェックして
新しくなったら新たにログファイルを作り直してtailするようにしています。
このスクリプトをバックグラウンドで動かしっぱなしにして
あとはこのログをZabbixでログ監視すればRDSのログ監視が可能になります。

問題点として、古いファイルを消すようにしていないのでローテ後のログファイルが溜まっていく事と、
JAVAのCLIはやっぱり重い事です。

あと、身も蓋もないですが、RDSのログをリアルタイムで監視したいという要件自体がほぼほぼ無いです。

Zabbixの監視通信をStunnelで暗号化する。

| コメントをどうぞ

Zabbixの監視通信は平文で行われます。なのでパケットを眺めると通信内容などが盗み見されます。監視システムははLAN内で完結する事が多いので盗み見出来ても問題無いですが、リモート監視などを行っていると問題になる場合があります。個人的には監視データが見られてもさして問題じゃないのでは?と思いますが、セキュリティの厳しい要件やお客さんに「暗号化してません。平文です。」というのは何かとまずい事があります。ですので暗号化します。

試しに暗号していない通信を他のサーバでキャプチャしてみると・・・
(Zabbixサーバ宛に流れている通信をキャプチャ)

        0x0000:  4500 007e 9026 4000 4006 c20e ac16 c80b  E..~.&@.@.......
        0x0010:  ac16 c80c dca5 2742 331a 8fce 55ce 00f2  ......'B3...U...
        0x0020:  8018 0073 5e76 0000 0101 080a 9206 1fe9  ...s^v..........
        0x0030:  00b0 34a8 6e65 742e 6966 2e69 6e5b 5741  ..4.net.if.in[WA
        0x0040:  4e20 4d69 6e69 706f 7274 2028 4950 7636  N.Miniport.(IPv6
        0x0050:  292d 5379 6d61 6e74 6563 2045 6e64 706f  )-Symantec.Endpo
        0x0060:  696e 7420 5072 6f74 6563 7469 6f6e 2046  int.Protection.F
        0x0070:  6972 6577 616c 6c2d 3030 3030 5d0a       irewall-0000].

“net.if.in[WAN.Miniport.(IPv6)-Symantec.Endpoint.Protection.Firewall-0000].” と、人間が理解できる文字列で通信内容が覗き見出来ます。

以下は暗号化を施した通信になります。

        0x0000:  4500 0067 534c 4000 4006 fe89 ac16 c80b  E..gSL@.@.......
        0x0010:  ac16 c882 eb0c 274a e2cf a450 dcb4 2c70  ......'J...P..,p
        0x0020:  8018 007a 55df 0000 0101 080a 921e cdd0  ...zU...........
        0x0030:  7cc0 41e5 1403 0300 0101 1603 0300 28ac  |.A...........(.
        0x0040:  3564 cb7b 0072 0ce9 286f ecc3 1ff9 0b83  5d.{.r..(o......
        0x0050:  af2a da85 2d00 19fe 36ed 5efd ca2a 3734  .*..-...6.^..*74
        0x0060:  47a6 d9ce 1731 2d                        G....1-

通信内容が覗き見してもわからなくなっています。Zabbixの監視通信を行うのに良さそうな方法は2通りあります。

暗号化したVPNを張ってその中で通信。
通信を暗号化したトンネルを通す。

● VPNで暗号化のメリット
暗号化されたVPNで通信する方法はハードウェアもしくはソフトウェアでVPNを張って通信をすると全ての通信が暗号化されますのでZabbixの監視通信以外も暗号化出来ます。監視対象が多い場合もVPNに参加させるかVPNルータを経由させる形にすれば良いので容易に暗号化する監視対象を追加出来ます。

● VPNで暗号化のデメリット
VPNを張るという行為自体がNGな場合もあります。

● 暗号化したトンネルを張って通信を通す。のメリット
SSHトンネル等が有名です。手軽に1対1の通信を暗号化出来ます。監視対象が1台しか無いときでわざわざVPNを張らなくても・・・という場合に使いやすいです。

● 暗号化したトンネルを張って通信を通す。のデメリット
暗号化するソフトのポートの他に暗号化したい通信のポートが別途必要になります。複数ホストがある場合はその分数を掛け算で必要になります。

今回はStunnelで暗号化します。

Stunnelはサーバ、クライアント方式でStunnelで接続したトンネルを張り、その中に指定のポートを転送して通信します。Stunnelを起動すると自ホスト内に指定したポートが開きます。そこへのアクセスするとトンネルを張った相手ホストに転送します。

● Stunnelの概要図
stunnel

Stunnelは一つのデーモンでサーバとして動くポートとクライアントとして動くポートを指定して動かせますの
で一つのサーバ内でこのポートはクライアントとして外部のStunnelとトンネル張るがこのポートはサーバとして外部から受け付ける。というような事が可能です。

これを利用してZabbixサーバ側では、

● ログ等のアクティブチェックはStunnelのサーバモードで各エージェントからトンネル経由で受け取る。
● パッシブチェックは各エージェントに対してStunnelのクライアントモードでトンネル経由で問い合わせる。

と言った構成にしていきます。

Zabbixサーバ側の設定

  1. Stunnelのインストール


  2. CentOSならyum一発で導入出来ます。

    # yum install stunnel -y
    
  3. SSL証明書の作成
  4. OpenSSLを使って自前証明書を作成します。ブラウザでアクセスすることも無いので自前で何ら問題無いです。
    ここでよくある自前証明書作成コマンドで作成したものだと何故か私の環境では、

    Linux⇔Linux間は問題なくトンネル張れるが、Linux⇔WindowsとLinux⇔Linuxが混在する環境で全部にトンネル張ろうとすると失敗しました。失敗というか、Windows側で起動時に鍵のエラーが出ました。

    証明書作成コマンド

    # openssl genrsa 2048 > stunnel.key
    # openssl req -new -key stunnel.key > stunnel.csr
    # openssl x509 -days 3650 -req -signkey stunnel.key < stunnel.csr > stunnel.crt
    

    Stunnelのドキュメントに証明書/鍵の作成方法が書いてありますのでそちらで試すとWindowsとLinuxが混在した環境でも全部起動出来て繋がりました。

    To generate a key and self signed certificate, execute the following commands:
    
    cd /etc/pki/tls/certs
    make stunnel.pem
    
    Note that by default, the file containing the key and certificate has its
    permissions set to 0600, which means that any service using it needs to be
    started as root in order to read it.  Such a service should be configured
    to switch UIDs using stunnel's "-s" flag.
    

    証明書と鍵を一つのファイルにしないと駄目なのかもしれません。わかりませんが。。

    ※追記:書き忘れましたが、上のまんまで実行すると有効期限が365日で出来てしまいます。期限が切れるとStunnelが繋がらなくなります。深く考えずにやったので一度期限切れでStunnel経由の監視が全部出来なくなってしまった事があります。なので「make stunnel.pem」の前に「/etc/pki/tls/certs/Makefile」内の記述、「-days 365」を書き変えて長くしてから「make stunnel.pem」を実行します。今は「-days 9999」で作成して有効期限自体もZabbixで監視するようにして対策してあります。

  5. Zabbixサーバ側のStunnelの設定ファイルを書きます。
  6. ● /etc/stunnel/stunnel.conf

    cert = /etc/stunnel/stunnel.pem
    key = /etc/stunnel/stunnel.pem
    sslVersion = all
    options = NO_SSLv2
    options = NO_SSLv3
    setuid = nobody
    setgid = nobody
    pid = /etc/stunnel/stunnel.pid
    socket = l:TCP_NODELAY=1
    socket = r:TCP_NODELAY=1
    verify = 3
    CAfile = /etc/stunnel/stunnel.pem
    debug = 4
    output = stunnel.log
    [Zabbix passive HOST1]
    client = yes
    accept = 127.0.0.1:10060
    connect = XX.XX.XX.XX:10052
    [Zabbix passive HOST2]
    client = yes
    accept = 127.0.0.1:10062
    connect = XX.XX.XX.XX:10052
    
    [Zabbix Active]
    accept = 10061
    connect = 10051
    

    client=yes とするとクライアントモードでStunnelをサーバモードとして待ち受けているホストに繋ぎます。
    最初に自身の設定したポート、例えば10060に繋ぐと繋ぎたいホストの10052へ接続します。
    何もつけないとサーバモードで待ち受けます。ここをアクティブチェックの受け取り口にします。
    verify=3で証明書が一致しないと接続を蹴るようにします。そうしないとどこからでも接続されてしまいます。
    (単に暗号化したいならばverify指定しないと接続出来ます。)

Zabbixエージェント側の設定

インストール迄は同じです。証明書/鍵はサーバ側で作成したものをコピーして使います。

  1. Stunnelのインストール
  2. # yum install stunnel -y
    
  3. Zabbixエージェント側のStunnelの設定ファイルを書きます。
  4. ● /etc/stunnel/stunnel.conf(HOST1)

    cert = /etc/stunnel/stunnel.pem
    key = /etc/stunnel/stunnel.pem
    sslVersion = all
    options = NO_SSLv2
    options = NO_SSLv3
    setuid = nobody
    setgid = nobody
    pid = /etc/stunnel/stunnel.pid
    socket = l:TCP_NODELAY=1
    socket = r:TCP_NODELAY=1
    verify = 3
    CAfile = /etc/stunnel/stunnel.pem
    debug = 4
    output = stunnel.log
    [Zabbix passive]
    accept = 10060
    connect =10050
    [Zabbix Active]
    client = yes
    accept = 127.0.0.1:10051
    connect = XX.XX.XX.XX:10061
    

    ZabbixサーバからのパッシブチェックをStunnelが動いている10060で受け取り自身の10050へ渡します。アクティブチェックは自身から送信するのでZabbixサーバのStunnel待ち受けポートの10061へ飛ばします。
    こちらもサーバとして待ち受けるポートがあるのでverify=3として証明書が一致しない場合は接続しないようにします。

以上で設定そのものは完成です。Stunnelを起動すれば繋がるようになります。但しWIndows版は公式サイトのインストーラーで入れれば自動起動が出来ますがLinux版はinitスクリプトが存在しない為作成します。

● Linux版でStunnelのinitscript作成(サーバ、クライアント共通)
(/etc/init.d/stunnel)

#!/bin/sh
# chkconfig: 345 70 40
# description: stunnel

# Source function library.

. /etc/init.d/functions


STUNNEL=/usr/bin/stunnel
CONF=/etc/stunnel/stunnel.conf
prog=stunnel

start() {
                echo -n $"Start $prog: "
                daemon $STUNNEL $CONF
                echo
        }

stop() {
                echo -n $"Stop $prog: "
                killproc $STUNNEL
                echo
        }

case "$1" in
        start)
                start
                ;;
        stop)
                stop
                ;;
        restart)
                stop
                start
                ;;
        status)
                status $STUNNEL
                ;;
        *)
                echo "Usage:$0 {start|stop|restart|status}"
                ;;
esac

作成したら自動起動も設定しておきます。

# chkconfig --add stunnel
# chkconfig stunnel on

起動します。(サーバ、クライアント両方)

# /etc/init.d/stunnel start

Zabbixサーバからzabbix_getを使って動作確認します。

# zabbix_get -s 127.0.0.1 -p 10060 -k agent.hostname
HOST1

自身のローカルIPの10060ポートに対して実行したzabbix_getでエージェント側のホスト名が返ってきているのでトンネルがうまく張れているのが確認できます。

アクティブチェックがうまくとれているかはzabbix_senderでも出来ますが実際にZabbixでログ監視を作ったほうがわかりやすいです。

AWS上のZabbixをPacemakerで冗長化 その3(MySQLReplicate編)

| コメントをどうぞ

前回はAWS上のZabbixをPacemaker + DRBDで冗長化しましたので今回は、

● Pacemaker + MySQLレプリケーション(SemiSync)

をやります。MySQLは整合性の高いSemiSyncを採用します。SemiSyncはMySQL5.5以降で使えます。5.5以降はデフォルトのリポジトリには無いのでMySQL5.5以降があるリポジトリを追加するかソースからインストールします。


前提条件としてMySQLは既にインストール/Replication設定済みとします。(導入部分も書くと長くなる為。機会があれば別途導入方法も書きます。)

  • Pacemaker(HeartbeatV2) + MySQLレプリケーション(Semisync)

  • cluster3

    DRBDの時と同じように前回のheartbeatの設定ファイル、cib.xml等が/var/lib/heartbeat/crmに残っている為、一旦削除します。
    (稼働/待機両方で消します。残っていると同期されて元に戻ってしまう為)

    ● 稼働/待機系で前回の設定ファイル削除(/var/lib/heartbeat/crmの下を全消しでOK)

    # rm /var/lib/heartbeat/crm/* -fr
    

    ● 一旦heartbeatを起動

    # /etc/init.d/heartbeat start
    

    MySQL用のxmlファイルを置いて起動しても何故かうまく行かず初期のcibに上書きされてしまう場合は一旦起動後に置き換える事で上手く行きます。

    ● cib.xml無しで起動すると以下のようになります。(クラスタホストが認識されているだけの状態)

    ============
    Last updated: Fri Dec  5 12:46:25 2014
    Stack: Heartbeat
    Current DC: zabbixcluster-2 (e1c9433f-8e5b-8681-2867-5a4dd5880dfe) - partition w
    ith quorum
    Version: 1.0.13-30bb726
    2 Nodes configured, unknown expected votes
    0 Resources configured.
    ============
    
    Online: [ zabbixcluster-1 zabbixcluster-2 ]
    

    ● ここでZabbix+MySQLレプリケーション用のファイルを以下のようにどこかのディレクトリ(/tmpなどどこでもOK)用意します。

    ※nodeidなどは環境に合わせて適宜置き換えます。

    <cib epoch="19" num_updates="0" admin_epoch="0" validate-with="pacemaker-1.0" crm_feature_set="3.0.1" have-quorum="1" dc-uuid="f76af805-bfff-66bd-3d83-95a20a3807ef" cib-last-written="Mon Dec  8 16:12:17 2014">
      <configuration>
        <crm_config>
          <cluster_property_set id="cib-bootstrap-options">
            <nvpair id="cib-bootstrap-options-default-resource-stickiness" name="default-resource-stickiness" value="INFINITY"/>
            <nvpair id="cib-bootstrap-options-no-quorum-policy" name="no-quorum-policy" value="ignore"/>
            <nvpair id="cib-bootstrap-options-stonith-enabled" name="stonith-enabled" value="false"/>
            <nvpair id="cib-bootstrap-options-dc-version" name="dc-version" value="1.0.13-30bb726"/>
            <nvpair id="cib-bootstrap-options-cluster-infrastructure" name="cluster-infrastructure" value="Heartbeat"/>
          </cluster_property_set>
          <cluster_property_set id="mysql_replication">
            <nvpair id="mysql_replication-prm_mysqld_REPL_INFO" name="prm_mysqld_REPL_INFO" value="zabbixcluster-1|mysql-bin.000103|2698"/>
          </cluster_property_set>
        </crm_config>
        <nodes>
          <node id="f76af805-bfff-66bd-3d83-95a20a3807ef" type="normal" uname="zabbixcluster-1"/>
          <node id="e1c9433f-8e5b-8681-2867-5a4dd5880dfe" type="normal" uname="zabbixcluster-2"/>
        </nodes>
        <resources>
          <master id="ms_mysqld">
            <meta_attributes id="ms_mysqld-meta_attributes">
              <nvpair id="ms_mysqld-meta_attributes-master-max" name="master-max" value="1"/>
              <nvpair id="ms_mysqld-meta_attributes-master-node-max" name="master-node-max" value="1"/>
              <nvpair id="ms_mysqld-meta_attributes-clone-max" name="clone-max" value="2"/>
              <nvpair id="ms_mysqld-meta_attributes-clone-node-max" name="clone-node-max" value="1"/>
              <nvpair id="ms_mysqld-meta_attributes-notify" name="notify" value="true"/>
            </meta_attributes>
            <primitive class="ocf" id="prm_mysqld" provider="heartbeat" type="mysql">
              <instance_attributes id="prm_mysqld-instance_attributes">
                <nvpair id="prm_mysqld-instance_attributes-binary" name="binary" value="/usr/bin/mysqld_safe"/>
                <nvpair id="prm_mysqld-instance_attributes-replication_user" name="replication_user" value="replicate"/>
                <nvpair id="prm_mysqld-instance_attributes-replication_passwd" name="replication_passwd" value="bsp12345"/>
              </instance_attributes>
              <operations>
                <op id="prm_mysqld-start-0" interval="0" name="start" timeout="120s"/>
                <op id="prm_mysqld-stop-0" interval="0" name="stop" timeout="120s"/>
                <op id="prm_mysqld-monitor-20s" interval="20s" name="monitor" timeout="30s"/>
              </operations>
            </primitive>
          </master>
          <group id="group_zabbix">
            <primitive class="lsb" id="mysqld" type="mysqld">
              <operations>
                <op id="mysqld-start-0" interval="0" name="start" timeout="60">
                  <instance_attributes id="mysqld-start-0-instance_attributes">
                    <nvpair id="mysqld-start-0-instance_attributes-prereq" name="prereq" value="fencing"/>
                    <nvpair id="mysqld-start-0-instance_attributes-on_fail" name="on_fail" value="restart"/>
                  </instance_attributes>
                </op>
                <op id="mysqld-monitor-10" interval="10" name="monitor" timeout="60">
                  <instance_attributes id="mysqld-monitor-10-instance_attributes">
                    <nvpair id="mysqld-monitor-10-instance_attributes-on_fail" name="on_fail" value="restart"/>
                  </instance_attributes>
                </op>
                <op id="mysqld-stop-0" interval="0" name="stop" timeout="60">
                  <instance_attributes id="mysqld-stop-0-instance_attributes">
                    <nvpair id="mysqld-stop-0-instance_attributes-on_fail" name="on_fail" value="ignore"/>
                  </instance_attributes>
                </op>
              </operations>
            </primitive>
            <primitive class="lsb" id="httpd" type="httpd">
              <operations>
                <op id="httpd-start-0" interval="0" name="start" timeout="60">
                  <instance_attributes id="httpd-start-0-instance_attributes">
                    <nvpair id="httpd-start-0-instance_attributes-prereq" name="prereq" value="fencing"/>
                    <nvpair id="httpd-start-0-instance_attributes-on_fail" name="on_fail" value="restart"/>
                  </instance_attributes>
                </op>
                <op id="httpd-monitor-10" interval="10" name="monitor" timeout="60">
                  <instance_attributes id="httpd-monitor-10-instance_attributes">
                    <nvpair id="httpd-monitor-10-instance_attributes-on_fail" name="on_fail" value="restart"/>
                  </instance_attributes>
                </op>
                <op id="httpd-stop-0" interval="0" name="stop" timeout="60">
                  <instance_attributes id="httpd-stop-0-instance_attributes">
                    <nvpair id="httpd-stop-0-instance_attributes-on_fail" name="on_fail" value="ignore"/>
                  </instance_attributes>
                </op>
              </operations>
            </primitive>
            <primitive class="lsb" id="zabbix_server" type="zabbix_server">
              <operations>
                <op id="zabbix_server-start-0" interval="0" name="start" timeout="60">
                  <instance_attributes id="zabbix_server-start-0-instance_attributes">
                    <nvpair id="zabbix_server-start-0-instance_attributes-prereq" name="prereq" value="fencing"/>
                    <nvpair id="zabbix_server-start-0-instance_attributes-on_fail" name="on_fail" value="restart"/>
                  </instance_attributes>
                </op>
                <op id="zabbix_server-monitor-10" interval="10" name="monitor" timeout="60">
                  <instance_attributes id="zabbix_server-monitor-10-instance_attributes">
                    <nvpair id="zabbix_server-monitor-10-instance_attributes-on_fail" name="on_fail" value="restart"/>
                  </instance_attributes>
                </op>
                <op id="zabbix_server-stop-0" interval="0" name="stop" timeout="60">
                  <instance_attributes id="zabbix_server-stop-0-instance_attributes">
                    <nvpair id="zabbix_server-stop-0-instance_attributes-on_fail" name="on_fail" value="ignore"/>
                  </instance_attributes>
                </op>
              </operations>
            </primitive>
          </group>
        </resources>
        <constraints>
          <rsc_colocation id="zabbix_master" rsc="ms_mysqld" rsc-role="Master" score="INFINITY" with-rsc="group_zabbix"/>
          <rsc_order first="ms_mysqld" first-action="promote" id="mysql_master" score="INFINITY" then="group_zabbix" then-action="start"/>
        </constraints>
        <rsc_defaults>
          <meta_attributes id="rsc-options">
            <nvpair id="rsc-options-resource-stickiness" name="resource-stickiness" value="INFINITY"/>
            <nvpair id="rsc-options-migration-threshold" name="migration-threshold" value="1"/>
          </meta_attributes>
        </rsc_defaults>
      </configuration>
    </cib>
    

    ● 上記で作成したcib.xmlをheartbeatを起動したまま以下のコマンドで置き換えます。

    # cibadmin --replace --xml-file cib.xml.mysql_repl
    

    ● そうするとすぐにheartbeat側で反映されます。

    Online: [ zabbixcluster-1 zabbixcluster-2 ]
    
     Master/Slave Set: ms_mysqld
         Masters: [ zabbixcluster-1 ]
         Slaves: [ zabbixcluster-2 ]
     Resource Group: group_zabbix
         mysqld     (lsb:mysqld):   Started zabbixcluster-1
         httpd      (lsb:httpd):    Started zabbixcluster-1
         zabbix_server      (lsb:zabbix_server):    Started zabbixcluster-1
    

    heartbeatで用意されているOCFを使うとMySQLプロセスの他にMaster/Slaveの状態も監視して、フェイルオーバー時に自動で「CHANGE MASTER」迄実行してMasterとSlaveの切替をしてくれます。heartbeatのcolocationとorderで指定する事によって、MySQLがMasterで動いている方でZabbix、httpdを起動するクラスタが構成出来ます。(片系が壊れてもMasterで動いている方で稼働します。)

    ● MySQLレプリケーションで片系故障時

    Online: [ zabbixcluster-2 ]
    
     Master/Slave Set: ms_mysqld
         Masters: [ zabbixcluster-2 ]
         Stopped: [ prm_mysqld:0 ]
     Resource Group: group_zabbix
         mysqld     (lsb:mysqld):   Started zabbixcluster-2
         httpd      (lsb:httpd):    Started zabbixcluster-2
         zabbix_server      (lsb:zabbix_server):    Started zabbixcluster-2
    

    MySQLに障害が発生して長時間Slaveが止まっていたり、何等かの理由でMySQLが起動してもSlave側が同期してくれていない場合があります。この時pacemakerからはMaster/Slaveとして動作しているように見える為異常を検知しません。MySQLにログインしてSLAVEのステータス確認コマンドを実行しないとわかりません。

    ● スレーブの状態確認コマンド(スレーブ側で実行)

    mysql> show slave status\G
    

    ● コマンド結果

                   Slave_IO_State: Waiting for master to send event
                      Master_Host: zabbixcluster-2
                      Master_User: replicate
                      Master_Port: 3306
                    Connect_Retry: 60
                  Master_Log_File: mysql-bin.000136
              Read_Master_Log_Pos: 455117
                   Relay_Log_File: mysqld-relay-bin.000002
                    Relay_Log_Pos: 455263
            Relay_Master_Log_File: mysql-bin.000136
                 Slave_IO_Running: Yes
                Slave_SQL_Running: Yes
                  Replicate_Do_DB:
              Replicate_Ignore_DB:
               Replicate_Do_Table:
           Replicate_Ignore_Table:
          Replicate_Wild_Do_Table:
      Replicate_Wild_Ignore_Table:
                       Last_Errno: 0
                       Last_Error:
                     Skip_Counter: 0
              Exec_Master_Log_Pos: 455117
                  Relay_Log_Space: 455420
                  Until_Condition: None
                   Until_Log_File:
                    Until_Log_Pos: 0
               Master_SSL_Allowed: No
               Master_SSL_CA_File:
               Master_SSL_CA_Path:
                  Master_SSL_Cert:
                Master_SSL_Cipher:
                   Master_SSL_Key:
            Seconds_Behind_Master: 0
    Master_SSL_Verify_Server_Cert: No
                    Last_IO_Errno: 0
                    Last_IO_Error:
                   Last_SQL_Errno: 0
                   Last_SQL_Error:
      Replicate_Ignore_Server_Ids:
                 Master_Server_Id: 2
    1 row in set (0.00 sec)
    

    重要なところは、

                 Slave_IO_Running: Yes
                Slave_SQL_Running: Yes
    

    の2つがYesとなっていないとMaster/Slave動作出来ていても実際はレプリケーションされていません。(他にもレプリの遅延時間とか見ないとなりませんが、とりあえずこの2つがYesでないとはじまりませんので。)Master側は動いているので監視は継続されますが、フェイルオーバーした際に不整合でZabbixがおかしくなります。

    この部分をZabbixで監視します。Slave側のMySQLへ接続して「show slave status\G」を実行するスクリプトを作成してZabbixの外部チェックで監視します。内容はSlave側のMySQLへ接続して「show slave status\G」を実行するものなら何でも良いです。本構成ではZabbixはMySQLがMasterで動作しているサーバで動くようになっていますのでフェイルオーバー後も問題無くSlaveの状態監視を継続出来ます。

    ※ 双方向で「show slave status\G」が実行出来るように権限設定しておく必要があります。

    スクリプトはこんな感じのものでも期待した動作してくれます。

    #!/bin/sh
    
    SLAVEHOST=`sudo /usr/sbin/crm_mon -1 | grep Slaves | sed 's/^  *//g' | awk '{print $3}'`
    STATUS="show slave status\\G"
    
    case "$1" in
    io)
    mysql -h $SLAVEHOST -e "$STATUS" | grep -w "Slave_IO_Running" | grep "Yes" | sed 's/^  *//g'
    ;;
    sql)
    mysql -h $SLAVEHOST -e "$STATUS" | grep -w "Slave_SQL_Running" | grep "Yes"| sed 's/^  *//g'
    ;;
    esac
    

    ● ZabbixでのSlave状態監視画面
    slavestatus

    これでSlave側の同期していない状態を検知出来ます。障害検知したら手動でMySQLレプリケーションの不整合を修正します。修正パターンが何パターンかありここの自動化は見合わせました。(無理に自動化するとトドメさしかねない。。)

    以上で3回に渡ってAWS上のZabbix冗長構成を、

    ● Pacemaker + RDS (1回目)
    ● Pacemaker + DRBD (2回目)
    ● Pacemaker + MySQLレプリケーション(3回目)

    のパターンで構築する方法のご紹介を終了します。

    AWS上のZabbixをPacemakerで冗長化 その1(RDS編)

    | コメントをどうぞ

    前回はAWS上のZabbixを冗長化する方法を、

    ● Pacemaker + RDS
    ● Pacemaker + DRBD
    ● Pacemaker + MySQLレプリケーション

    の3つパターンで紹介しました。ここから3回に分けて実際に設定していきます。1回目は「Pacemaker + RDS」 を設定していきます。各冗長方式の違いは前回を参照してください。OSはCentOS6を使用します。

    個人的にはこの方式が一番しっくり来ます。AWSのRDSを採用しているので実装後の運用面において効率が良いです。フェイルオーバーにかかる時間が一番長いという欠点も数分長くかかるという程度ですので。

    PacemakerでZabbixを冗長化するのに用意するもの

    ● Pacemaker及びheartbeatのパッケージ
    ● ApacheのLSB
    ● ZabbixのLSB
    ● SwatchのLSB
    ● 上記のクラスタを制御する為のcib.xml

    Apache等のメジャーなものはOCFに標準で用意されていますのでそちらを使っても結構です。ただ、ZabbixのOCFが無いのでLSBを作成する関係上ついでにApacheもLSBで作ってしまえ!統一感だせるし。という事で全部LSBにします。OCFも頑張れば作成出来ますが、圧倒的にLSBの方が作成しやすいです。(理由は後述)

    LSBって?

    Linux Standard Baseの略。Linuxの標準のinitスクリプトを用いて冗長化が可能なリソースエージェントです。(OCFもリソースエージェント)
    OCFは専用?の書式で書いてある為作成の難易度は高いですが、LSBであれば普段Linuxを触っている方なら馴染みも深いので作成が容易です。initスクリプトで冗長化を行えるので、initスクリプトで制御しているデーモンはわざわざ作成しなくても即冗長化出来ます。(多少修正しないとならない場合もあります。)
    initスクリプト経由で起動しないデーモンでもinitスクリプトで制御するようにすれば冗長化出来ますし、デーモン以外のプロセスでもinitスクリプト作成してしまえば冗長化出来きます。

    というものがLSBですのでメジャーじゃないデーモンを冗長化したかったり自分でいろいろ設定してみたいという方たちにはお勧めのリソースエージェントです。OCFの方が多機能な場合が多いのですが、普段見慣れてるinitスクリプトで冗長化出来てしまうのですから。

    OCFは/usr/lib/ocf/resource.dの下にありますので冗長化を行う時は確認してある場合は使う。無い場合はLSB作成する。というのが良いと思います。(OCFのリスト一覧表示コマンドをつかっても見れます。)

    ● 現在のOCFを表示

    # ls
    AoEtarget     Raid1               conntrackd        nginx
    AudibleAlarm  Route               db2               oracle
    CTDB          SAPDatabase         dhcpd             oralsnr
    ClusterMon    SAPInstance         eDir88            pgsql
    Delay         SendArp             ethmonitor        pingd
    Dummy         ServeRAID           exportfs          portblock
    EvmsSCC       SphinxSearchDaemon  fio               postfix
    Evmsd         Squid               iSCSILogicalUnit  pound
    Filesystem    Stateful            iSCSITarget       proftpd
    ICP           SysInfo             ids               rsyncd
    IPaddr        VIPArip             iface-bridge      rsyslog
    IPaddr2       VirtualDomain       iface-vlan        scsi2reservation
    IPsrcaddr     WAS                 iscsi             sfex
    IPv6addr      WAS6                jboss             slapd
    LVM           WinPopup            ldirectord        symlink
    LinuxSCSI     Xen                 lxc               syslog-ng
    MailTo        Xinetd              mysql             tomcat
    ManageRAID    anything            mysql-proxy       varnish
    ManageVE      apache              named             vmware
    Pure-FTPd     asterisk            nfsserver         zabbixserver
    

    ・・・zabbixserver・・・? いつの間に・・・。前回ブログ書いた時点で一通りLSB作ってしまった後に気づきました。。
    調べてみると2012年にzabbixserverのOCFが追加されたようです。

    せっかくだから作ったLSB使って冗長化していきます。。

    Pacemakterのインストール

    まずは冗長化してくれるPacemakerをインストールします。バージョンによってクラスタ制御(切替など)コマンドがうまく動かないものがありますので正常動作が確認とれているバージョンを入れます。yumで入れると最新バージョンが入ってしまう為、Linux-HAからリポジトリをダウンロードしてインストールします。本ブログではAWS上のZabbixの冗長化に焦点をあてるのでPacemakerの設定方法についての説明は最小限の内容になっています。

    ※ Linux-HAのサイトを見ればかなり詳細レベルの説明や導入方法が見ます。

    ● Linux-HAのリポジトリダウンロードURL

    http://sourceforge.jp/frs/redir.php?m=jaist&f=%2Flinux-ha%2F60151%2Fpacemaker-1.0.13-1.2.el6.x86_64.repo.tar.gz
    

    ● Pacemakerのインストール(/tmpで作業します)
    ※ クラスタ対象のインスタンス両方に実施します。

    # tar zvxf pacemaker-1.0.13-1.2.el6.x86_64.repo.tar.gz
    # mv pacemaker-1.0.13-1.2.el6.x86_64.repo/ /tmp/
    # cd /tmp
    # yum -c pacemaker.repo install heartbeat-3.0.5 pacemaker-1.0.13 pm_extras-1.3 heartbeat-devel.x86_64 -y
    

    heartbeatの設定
    ※ クラスタ対象のインスタンス両方に実施します。

    起動はheartbeatから行うのでheartbeatの設定をしていきます。設定ファイルのひな形をコピーして設定し、クラスタ間で通信する時の認証鍵も作成します。

    ● 設定のひな形コピーと鍵作成の設定

    # cd /etc/ha.d
    # cp /usr/share/doc/heartbeat-3.0.5/ha.cf ./
    # vi authkeys
    ---------
    auth 1
    1 sha1 'パスワード'
    ---------
    # chmod 600 authkeys
    

    ● heartbeat設定ファイル編集

    # vi ha.cf
    ---------
    crm yes   ← アプリケーションレベルで制御可能にする(クラスタリソースマネージャを有効)
    logfacility local1 ← ログをsyslogに送る(rsyslog.confにha-logの設定も必要)
    keepalive 3
    deadtime 30
    deadping 40
    warntime 10
    initdead 60
    udpport 694
    node HOST-1 ← クラスタを組むインスタンス名
    node HOST-2 ← クラスタを組むインスタンス名
    # The cluster nodes communicate on their heartbeat lan (.68.*) interfaces
    ucast eth0 XX.XX.XX.XX ← クラスタを組むインスタンスのIP(相互監視用)
    ucast eth0 XX.XX.XX.XX ← クラスタを組むインスタンスのIP(相互監視用)
    uuidfrom nodename ← 識別する情報UUIDをノード名から生成
    ---------
    

    ● syslog設定ファイル編集

    # vi /etc/rsyslog.conf
    ---------
    # Log anything (except mail) of level info or higher.
    # Don't log private authentication messages!
    *.info;mail.none;authpriv.none;cron.none                /var/log/messages
    local1.*                                                /var/log/ha-log  ← 追記
    ---------
    # /etc/init.d/rsyslogd restart
    

    LSBの作成

    LSB対応のinitスクリプトを作成します。LSB対応には以下の要件があります。

    1. start,stop,statusが実行出来る事
    2. start,stop実行時に成功した場合は「0」を返す事
    3. status実行時に正常な場合は「0」、異常な場合は「3」を返す事

    Pacemakerはinitスクリプトのstart/stopを実行して戻り値で成否を判別し、status実行でリソースの状態を監視します。
    大抵のinitスクリプトは特に手を加えなくてもこの動きをしてくれますのでそのまま使える場合が多いです。

    ※ LSBの仕様についてはLinux-HAに詳しく書いてあります。

    ● ApacheのLSB作成

    Apacheのinitスクリプトは若干修正しないと正常動作しないので修正します。修正箇所はstatusの部分だけで行けます。

      status)
      #      status -p ${pidfile} $httpd ← コメントアウト
            status $httpd ← 追記
            RETVAL=$?
    

    ● zabbix_serverのLSB作成

    こちらも若干修正が必要になります。修正後のファイルはここからダウンロードします。

    ● swatchのLSB作成

    swatchを使う理由ですが、Multi-AZにしたRDSがフェイルオーバーするとZabbixが処理を停止してしまうがプロセスは上がったままなのでPacemakerもZabbixは正常と見えてしまいフェイルオーバーしてくれないので、swatchでZabbixのログ監視を行いRDSのフェイルオーバーを検知したらZabbixを再起動かける為に使います。

    ※ swatchの導入はepelリポジトリのyumで入るのであらかじめ導入しておきます。

    RDSフェイルオーバー時にzabbix_serer.logに以下のログがかならず出ます(今のところ)

    watchdog: database is down
    

    swatchでこのログを検知したらzabbix_serverの再起動で監視を継続させます。

    swatchはinitスクリプト経由で起動/停止するものではないので1から作成します。ここからダウンロードします。

    ● swatch動作用の設定
    以下のswatchの設定ファイルを/etc/zabbixの下に作成します。

    watchfor /watchdog: database is down/
            exec "/etc/rc.d/init.d/zabbix_server restart"
    

    cib.xmlの作成

    残りはPacemakterのクラスタ制御のcib.xml作成です。/var/lib/heartbeat/crmの下にcib.xmlの名前でファイルを作成します。ここからダウンロードします。

    ※ 「node id」等の作成する環境によって変わる部分は自動生成されるので初回起動時に上書きされます。
    ※ リソースの死活監視の間隔は10秒に設定しています。パラメーターの意味の説明はここでは省略します。公式サイトを
      参照してください。
    ※ スプリットブレイン対策のstonithはAWSなので実施しません。
    ※ 稼働系が故障した後に復旧したら自動でフェイルバックする設定となっています。

    とりあえずこれで動く状態になりました。まずは動くところを見てそこから自分好みの設定に変えて運用して下さい。

    heatbeat(pacemaker)の起動

    まずは動かしてみます。以下のコマンドで起動します。

    # /etc/init.d/heartbeat start
    

    以下のコマンドでクラスタの状態を確認します。

    # crm_mon -i1 ← 1秒間隔でステータス表示更新
    
    Online: [ HOST-1 HOST-2 ]
    
     Resource Group: zabbixcluster
         apache     (lsb:httpd):    Started HOST-1
         zabbix_server      (lsb:zabbix_server):    Started HOST-1
         swatch     (lsb:swatch):   Started HOST-1
    

    Zabbixを停止させて障害を起こしてみます。

    # /etc/init.d/zabbix_server stop
    
    Online: [ HOST-1 HOST-2 ]
    
     Resource Group: zabbixcluster
         apache     (lsb:httpd):    Started HOST-2
         zabbix_server      (lsb:zabbix_server):    Started HOST-2
         swatch     (lsb:swatch):   Started HOST-2
    
    Failed actions:
        zabbix_server_monitor_10000 (node=HOST-1, call=17, rc=7, status=com
    plete): not running
    

    稼働系で障害が発生して待機系がサービスを引き継いだのがわかります。他のデーモン(apache、swatch)でも切り替わるかテストします。RDSの場合はAWSコンソールからフェイルオーバーさせてZabbixが再起動されて動き続けるのを確認します。

    ELBへの登録

    この状態ではインスタンス間で冗長されてはいるものの、ブラウザでのアクセスは出来ない為、動いていないのと同じような状態です。オンプレミスではVIPをつけて稼働/待機で移動させてVIPにアクセスで問題ありませんがAWSではマルチキャストを通さない為VIPではなくELBに稼働/待機を80ポートのヘルスチェックで登録する事により冗長が完成します。

    次回は「Pacemaker + DRBD」 を使ってZabbixを冗長化をやってききたいと思います。

    WordPressを運用しているサーバーのApacheをZabbixで監視する方法

    | コメントをどうぞ

    前回は、ZabbixでApacheを監視するための設定手順を紹介しました。
    今回は、Wordpress(このブログサイト)を運用しているサーバー上での監視設定です。

    監視対象サーバーの環境

    • OS: Amazon Linux
    • zabbix-agent: 2.2.5
    • httpd: 2.2.29
    • WordPress: 4.0

    手順

    前回の記事の設定の続きです。

    server-statusをリダイレクトをしないように設定

    Apacheの監視設定をしたときにserver-statusが取得できませんでした。

    サーバー上で実行したコマンド

    curl http://localhost/server-status
    

    結果

    < !DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
    <html><head>
    
    </head><body>
    <h1>Found</h1>
    The document has moved <a href="https://localhost/index.php">here</a>.
    <hr />
    <address>Apache/2.2.29 (Amazon) Server at localhost Port 80</address>
    </body></html>
    

    どうやらWordpressの設定でリダイレクトされているようです。

    続きを読む

    AWS上のZabbixをPacemaker(HeartbeatV2)で冗長化

    | 1件のフィードバック

    AWS上で監視システムにZabbixを動かしておられる方も多いかと思います。AWSとZabbixは相性が良いので今後も増えていくと予想されます。しかしZabbix単体では冗長構成をとる機能が無い為、Zabbixが停止すると監視も止まります。「ちょっとくらい監視がとまっても業務は止まらないから良い。」と割り切れる場合はOKですが、監視が止まったら困るケースもあります。監視をサービス提供している場合は特にそうなります。じゃあ冗長化しましょうという事になりますが、商用のクラスタソフトはなかなかお高く手が出しづらい状況です。そこでオープンソースのツールを使って冗長化します。

    Pacemaker(Heartbeat)で無料でZabbixを冗長化

    Linuxでは古くからLinux-HAというプロジェクトがありHeartbeatというツールがあります。HeartbeatV1→V2→V3と進化してミドルウェアの制御部分を分離してPacemakerとなりました。V2(たぶんV3も)まではHeartbeatがミドルウェア部分も制御していました。
    (V2までしか触ってなかったのでここらへんの知識はあいまい。)
    歴史がありますので実績も十分です。(商用環境でも採用されています。)
    HeartbeatとLVS(LinuxVirtualServer)を組み合わせてロードバランサーを安価に構築したりする事も可能です。
    ただ、昔は実機のロードバランサーが高価だった為に結構構築されていましたが、今はAWSでELBとか出てきたのであまり見かけなくなりました。

    HeartbeatV1

    初期のころのHeartbeatでOS単位で冗長化出来ます。フェイルオーバー時に待機系でキックするミドルウェアを指定可能です。(メジャーなミドルウェア最初からリソースエージェントが用意されています。無い場合は作りますがシンプルなので容易に作成できると思います。)

    但しフェイルオーバーのトリガーに出来るのはOSの死活のみでミドルウェアが停止してもOSが生きていたらフェイルオーバーはしてくれません。この為当時は別途シェルスクリプトなどと連携させてミドルウェアが停止したらHeartbeatの切替コマンドを実行させるなどで強引に対応しました。また、クラスタ構成は1対1の2台構成までです。

    HeartbeatV2~

    V2になって進化してミドルウェアもフェイルオーバー対象に出来るようになりました。クラスタ構成も1対Nが
    可能になり、3台クラスター、5台クラスターという構成も可能になりました。但しcib.xmlファイルというものを作成する必要があり、更には冗長構成にするには色々と複雑な設定をしていく必要がありました。この為、この時代でもHeartbeatV1を利用しているケースが結構ありました。ただ、メジャーなミドルウェアは最初からOCF(OpenClusterFramework)というものが用意されているのでこちらを利用すると冗長化はしやすいです。(無い場合は自分で作成)

    Pacemaker

    V2にあったミドルウェアを制御するcrm(クラスタリソースマネージャ)分離してpacemakerになり、GUIで設定出来たり、crm configureで簡単にクラスタ構成を組めるようになったようです。何故「~ようです」と書いたかというと使ってみた感じ劇的に簡単になったか?と聞かれると微妙・・・。cib.xmlを書いた経験のある方ならcib.xmlを手書きしてしまっても構わないような感じではあります。ちなみにGUI版は触った事ないのでわかりません。

    AWS上でHeartbeatで冗長化するには?

    前置きが長くなりましたが、ここからAWSで冗長化を考えます。Heartbeat及びpacemakerはクラウドとか流行るより昔に生まれたので実機(オンプレミス)での冗長構成を念頭に開発されている部分があります。(シリアルケーブルで死活通信が可能など。)
    どのサーバがサービス稼働中なのかの区別にサービス稼働中にVIPをつける方式がとても多いです。WEBサーバを冗長構成で組んでいるとして、エンドユーザにはVIPにアクセスさせます。Heartbeatがフェイルオーバー時に待機系にVIPを付け替える事によってエンドユーザはサーバが切り替わっても継続したサービスを受けれる仕組みです。しかしAWSではこの方式だと問題があります。

    AWSはマルチキャストのパケットが通らない。

    仕様上許しておらずマルチキャストパケットは破棄されます。何が困るかというとVIPを付け替える際にブロードキャストして知らせるわけですが、AWSでは破棄されるので勝手にVIP名乗っているだけで誰も(周りのサーバは)VIPを知らないので通信できません。ですので、

    VIPの変わりにELBで代用します。

    エンドユーザのアクセスをELBにしてELBのヘルスチェックを使って稼働系のインスタンスへ振り分ける事でこの問題が回避出来きるのでELB+Pacemaker(HeartbeatV2)を基本設計にAWS上でのZabbixの冗長化を行います。ZabbixをAWSで冗長構成を組むのに大まかに以下のパターンがあります。

    1. Pacemaker(HeartbeatV2) + RDS

    2. cluster1

      ● AWS上でVPC内にAvailabilityZoneをActiveとStandbyで分けてZabbixを動かしDR対応させる。
      ● AWSではマルチキャストを通さない仕様でVIP方式の冗長が利用出来ない為、ELBによるヘルスチェックを実施。
      ● データベースをRDS Multi-Azを採用することにより、汎用性、運用効率を上げる。
      ● Pacemakerでミドルウェア単位でグループ化してActive-Standbyの冗長を構成。
         グループ:Apache,Zabbix,Swatch
              ※Apacheは常時起動でそれ以下をグループ化してもOK

      ・・・なんでSwatchがいるの?と言うとやってみて分かった事ですがRDSのフェイルオーバー後はZabbixサーバが止まります。毎回DBに接続するアプリであれば問題は無いのですがZabbixのようなDBに接続しっぱなしのdaemonなどは一旦切断して再接続しないとならないようです。ここにも書いてありました。

      Amazon Web Services ブログ
      http://aws.typepad.com/aws_japan/2012/05/multi-az-option-for-amazon-rds-for-oracle-database.html

      そこでこの問題を、

      ● RDSフェイルオーバー時にZabbixの監視が停止する問題をSwatchで対処。している為クラスタグループにSwatchがいます。(他に妙案が浮かばなかった。。)

      動かした状態のクラスタモニタ

      Online: [ zabbixcluster-1 zabbixcluster-2 ]
      
       Resource Group: zabbixcluster
           apache     (lsb:httpd):    Started zabbixcluster-1
           zabbix_server      (lsb:zabbix_server):    Started zabbixcluster-1
           swatch     (lsb:swatch):   Started zabbixcluster-1
      

    3. Pacemaker(HeartbeatV2) + DRBD

    4. cluster2

      ゾーンを分けてELBでヘルスチェックまでは基本同じで、
      ● データベースをMySQL、データ格納領域をDRBDで同期。
      ● Pacemakerでミドルウェア単位でグループ化してActive-Standbyの冗長を構成。 
         クラスタグループ:Apache,Zabbix,MySQL,DRBD
                  ※DRBDのMaster/Slave切替もPacemakerで制御。

      動かした状態のクラスタモニタ

      Online: [ zabbixcluster-1 zabbixcluster-2 ]
      
       Master/Slave Set: ms_drbd_r0
           Masters: [ zabbixcluster-1 ]
           Slaves: [ zabbixcluster-2 ]
       Resource Group: group_zabbix
           mount_r0   (ocf::heartbeat:Filesystem):    Started zabbixcluster-1
           httpd      (lsb:httpd):    Started zabbixcluster-1
           mysqld     (lsb:mysqld):   Started zabbixcluster-1
           zabbix_server      (lsb:zabbix_server):    Started zabbixcluster-1
      

    5. Pacemaker(HeartbeatV2) + MySQLレプリケーション

    6. cluster3



    ゾーンを分けてELBでヘルスチェックまでは基本同じで、
    ● データベースをMySQL、データをレプリケーションでSlaveに同期。(Semi-Sync方式)
    ● Pacemakerでミドルウェア単位でグループ化してActive-Standbyの冗長を構成。
       クラスタグループ:Apache,Zabbix,MySQL
                ※MySQLのMaster/Slave切替もPacemakerで制御。

    動かした状態のクラスタモニタ

    Online: [ zabbixcluster-1 zabbixcluster-2 ]
    
     Master/Slave Set: ms_mysqld
         Masters: [ zabbixcluster-1 ]
         Slaves: [ zabbixcluster-2 ]
     Resource Group: group_zabbix
         mysqld     (lsb:mysqld):   Started zabbixcluster-1
         httpd      (lsb:httpd):    Started zabbixcluster-1
         zabbix_server      (lsb:zabbix_server):    Started zabbixcluster-1
    

    それぞれのメリット/デメリット

    RDS採用のメリット/デメリット
    ● メリット

    1. AWSコンソールからLaunch出来るので導入がし易い。
    2. バックアップ/リカバリの方法もスナップショットで行える。
    3. EC2インスタンスとRDSが分離しているのでEC2インスタンスだけインスタンスタイプを変更したり、RDSだけインスタンスタイプを変更したりといった運用が可能。

    ● デメリット

    1. EC2インスタンスとRDSインスタンスの料金が発生する。Multi-AZにする場合は更に費用が発生。
    2.      ※結構馬鹿にならない料金になります。ここが最大のネック。

    3. RDSはデータベースの管理者権限が取得出来ない為、それに伴う諸々の不便さが存在する。
    4. RDSは時刻がUTCだったりと日本仕様で無い部分があり対策が必要。
    5. フェイルオーバーにかかる時間がDRBDやMySQLレプリケーションより遅い。

    DRBD採用のメリット/デメリット
    ● メリット

    1. 離れたディスク(Volume)をRAID1のように利用出来る為、データの整合性が高い。
    2. カーネルモジュールで動作する為、CPUやメモリへの負担が小さい。
    3. Volume間を繋ぐ回線速度が速いほどデータのディスク性能を上げる事が出来る。
    4. RDS採用よりもコストを抑えられる。

    ● デメリット

    1. ディスク性能が回線速度に大きく依存する為、速い回線にする必要がある。AWSではインスタンスタイプで回線速度が決まっている為、CPU、メモリに余裕があってもDRBDの為だけにインスタンタイプを高スペックにする必要がある。
    2. データを同時に書き込む仕様で不整合が発生しにくいはずだが、AWSでは発生しやすく、同期がはずれてStandAloneの状態になりやすい。
    3. ※特に大きいファイルが一瞬で書き終わる時に発生しやすい模様。有り得ない早さで書き終わる時があるのでAWS側のパフォーマンスを上げる為の仕組みか何かが作用しているかもしれません。ストレージゲートウェイでも似たような事象があるのでEC2インスタンスもデータを書き込む時にキャッシュしたりしてるかもしれません。

    4. 不整合発生時のリカバリ時など運用面で効率はRDSに劣る。

    MySQLレプリケーションのメリット/デメリット
    ● メリット

    1. 広く利用されてきた方式の為、情報が豊富で導入や運用がし易い。
    2. DRBDよりも同期速度は速い。
    3. MySQL5.5以降の機能のSemi-Syncを使うとデータの整合性が高くなる。
    4. RDS採用よりもコストを抑えられる。

    ● デメリット

    1. DRBD程ではないが、性能は回線速度に依存する。
    2. CPUやメモリへの負担はDRBDよりも高い。
    3. Semi-Syncを採用してもDRBDより整合性では劣る。
    4. 不整合発生時のリカバリ時など運用面で効率はRDSに劣る。



    これらを踏まえて実際に構築して比べてみると性能面では、

    RDS > MySQLレプリ > DRBD
    

    耐障害性(フェイルオーバーの迅速さ)では、

    DRBD > MySQLレプリ > RDS
    

    導入の容易さや運用効率では、

    RDS > MySQLレプリ > DRBD
    

    と、感じましたがここらへんはもっと時間をかけて調査しないと何とも言えない部分もあります。。
    DRBDはmicroだとかなり厳しいパフォーマンスでしたが、largeに上げたら一昔前のハードディスクくらいの性能出しましたし、MySQLレプリもSemi-SyncだとDRBDじゃなくても良いんじゃないか?という整合性を保ってくれます。更にはAWSのDRBDは単に構築した段階ではうまく同期とれているように見えましたが、ディスクに大きいデータを書き込むような状況下では不整合しやすかったりなど(DRBDって同時書込みのはずなのに)
    まだまだテストや工夫しないとならないようです。

    では、各パターンの実際の設定やちょっとしたテストに入って行きたいと思いますが、長くなりましたので次回書きます。次回はパターンの1つめの、

  • Pacemaker(HeartbeatV2) + RDS
  • の設定とテスト結果を書きます。

    ZabbixでApacheを監視するための設定手順

    | コメントをどうぞ

    今回は、ZabbixでApacheを監視するための設定手順です。

    監視対象サーバーの環境

    • OS: Amazon Linux
    • zabbix-agent: 2.2.5
    • httpd: 2.2.27

    手順

    mod_statusを有効にする

    監視対象サーバーのmod_statusを有効にして、http://localhost/server-statusで稼働状況を確認できるようにします。

    httpd.confを2箇所編集します。

    vi /etc/httpd/conf/httpd.conf
    

    1 以下の行のコメントアウトを解除します。

    ExtendedStatus On
    

    2 以下のコメントアウトを解除して一部修正します。

    Before

    #<Location /server-status>
    #    SetHandler server-status
    #    Order deny,allow
    #    Deny from all
    #    Allow from .example.com
    #</Location>
    

    After

    <Location /server-status>
        SetHandler server-status
        Order deny,allow
        Deny from all
        Allow from 127.0.0.1
    </Location>
    

    ここでは、ローカルからしかアクセスできないように設定しています。
    Apacheを再起動します。

    /etc/init.d/httpd restart
    

    続きを読む