作成者別アーカイブ: kimitakayoshikawa

AWSのVPCの予約IPについての勘違い

| コメントをどうぞ

AWSで中にサブネットを複数持つVPCのIPについて勘違いしていたので書きます。

サブネットを作成するとCIDRの最初の4つ(正確には3つ?)最後の1つはAWS側で予約されているので
使えないのはAWSを利用している方ならご存知かと思います。

例えば192.168.0.0/24のCIDRのサブネットの場合、

●192.168.0.0はネットワーク全体を表すのでAWSだからとでなく使えません。
●192.168.0.1はAWS側で予約で使えません。
●192.168.0.2はAWS側で予約で使えません。
●192.168.0.3はAWS側で予約で使えません。
●192.168.0.254はAWS側で予約で使えません。

で、実際に使ってみるとどうやら、

●192.168.0.1はゲートウェイIPになっている模様。
●192.168.0.2はDNSになっている模様。
●192.168.0.3は何やってるかわからない。
●192.168.0.254は何やってるかわからない。

一般的にアドレスの一番最初は大抵DNSとかゲートウェイとかDHCPにしている場合が多いので
納得いきます。最後の1つもゲートウェイにしている場合が多いので納得いきます。

で、サブネットを二つ持つVPCでも各サブネットごとにAWSは予約IPが同じようにあります。
公式サイトにも以下のように書いてあります。

Important

AWS は、各サブネット CIDR ブロックの最初の 4 つの IP アドレスと最後の IP アドレスの両方を
予約します。これらのアドレスをユーザーが使用することはできません。
たとえば、CIDR ブロック 10.0.0.0/24 を持つサブネットの場合、
IP アドレス 10.0.0.0、10.0.0.1、10.0.0.2、10.0.0.255、
および 10.0.0.3 が予約されます。

http://docs.aws.amazon.com/ja_jp/AmazonVPC/latest/UserGuide/VPC_Subnets.html

なので、サブネットを2つ持つVPC、例えば、

ゾーンA:192.168.0.0/25
ゾーンB:192.168.0.128/25

の場合は、

ゾーンAは、192.168.0.0,192.168.0.1,192.168.0.2,192.168.0.3,192.168.0.127
ゾーンBは、192.168.0.128,192.168.0.129,192.168.0.130,192.168.0.131,192.168.0.254

はAWS側で予約されていて使えません。実際に使ってみた経験から、

ゾーンAのゲートウェイは192.168.0.1
ゾーンBのゲートウェイは192.168.0.129

になると推測出来き、実際に確認するとその通りになっています。
次にDNSはこれまでの経験から、

ゾーンAのDNSは192.168.0.2
ゾーンBのDNSは192.168.0.130

と推測出来ます。そして実際に確認すると・・・

ゾーンAのDNSは192.168.0.2
ゾーンBのDNSは192.168.0.2

・・・?ゾーンBにいるのにゾーンAのIPのDNSに聞きにいってる。。
ここで以下の疑問がわきます。

●ゾーンBにいるサーバが名前解決するのにゾーンAのDNSに聞きに行くのは距離が離れている分遅くなるのではないか?

●ゾーンAとゾーンBで冗長化している場合はゾーンAが落ちたらゾーンBのサーバも名前解決出来なくなるではないか?

●ゾーンBの192.168.0.130は何やってるの?DNSじゃないの?

色々ドキュメントを漁る。グーグル先生に聞く。自分であれこれコマンド実行で調べる。
・・・をやってみましたがわかりませんでした。

わからないのでAWSサポートに聞きました。で、回答はこんな感じでした。

DNSはVPCのCIDRの2番目のアドレスです。

そうなんですか。各サブネットごとに存在するのかと思っていました。予約されているし。
でもVPCのCIDRの2番目のアドレスのみなら遠回りの問題とDNSが存在するゾーンが拠点障害
起きたらまずいのかと・・・。

それに対して以下の回答が。



DNSサーバーは冗長化されていて
特定のVPC サブネット上に
配置されたものではありません。 
Availability Zone で機能します。 
DNS の IP アドレスは仮想的なものとご理解下さい。


だそうです。見かけ上は192.168.0.2に対してゾーンBから名前解決しているように見えても
同じゾーン内にあるDNSに問い合わせいってるとの事です。

自分と同じ勘違いをしている人もいるかもしれませんので共有します。

ゾーンAの192.168.0.2とDNSの仮想IPの192.168.0.2でかぶってるけどどう処理してるんだろう?とかゾーンBからの192.168.0.2のパケットはゾーンB内のIPに変換されているのだろうか?
とか、予約されているIPは何に使われているのだろうか?

などは今もわかりませんが。。(最初のIPはほぼほぼゲートウェイとは思います。)

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 Market Placeから作成したインスタンスのVolumeを他インスタンスにアタッチしたい。

| コメントをどうぞ

AWSのMarketPlaceから作成したインスタンスのVolumeってProductCodeがついていて、他のインスタンスにセカンダリディスクとしてつけようとすると、Rootデバイス以外にはアタッチ出来ないメッセージが出てはじかれます。

ログイン出来なくなってしまったようなトラブル時に復旧作業が出来ません。。

でも、前は出来たような・・・?自分もiptablesでSSHを閉じちゃってしかも自動起動で
にっちもさっちもの状態になったんですが、前にAWSセミナーに参加した際にエバンジェリストにその事を質問したら「別のインスタンスのセカンダリディスクとしてつければ復旧可能ですよ」と言われて戻った時に試したらそれで復旧できた記憶があります。

・・・で、ちょっと前にSSHを起動できなくしたインスタンスのVolumeを別のインスタンスのセカンダリにつけて復旧させてようとしたらこれが出来ない。rootデバイスじゃないと駄目だよってメッセージでます。ネットで検索してみるとどうやらMarketPlaceから作ったインスタンスのVolumeは他のインスタンスのセカンダリデバイスとしてアタッチ出来ない制限があるらしい。
ログイン出来ないようなトラブル時には一度AWSサポートへお願いして制限を解除してもらうしかない模様。

・・・そうなんだ。。AWSサポート画面を開いてみる。

・・・サービス上限緩和のメニューしか無いよ?

このAWSアカウントは無料サポートのBASICにしか加入してないからこの手のサポートが受けれない・・・?

フォーラムに投げてみると個別対応しますね。というレスついてメールが来たけど文面から察するに有料サポートよろしく的な事っぽかった。

ログイン出来ないインスタンスはTerminateしてやりました。

どうやらMarketPlaceから作ったインスタンスのVolumeにはProductCodeがひっついていて、これがあるとrootデバイス以外にはアタッチできない仕様になっていた!
(前はこんな制限無かった記憶が・・・。上にも書きましたが。)

無料サポートのBASICの人はMarketPlaceから作ったインスタンスでログイン不能にすると詰みます!

ここで海外の掲示板で抜け道を発見。ProductCodeはOS内部にデータとしてあるわけではないようでMarketPlaceで作成したインスタンスのVolumeの中のデータを新規作成したVolumeに移してしまえばOKと書いてある。やってみよう。

  1. MarkePlaceからインスタンス作成
  2. 同じサイズのまっさらのVolumeを作成した↑のインスタンスにセカンダリとしてアタッチ
  3. まっさらのVolumeをフォーマット(ここではxvdj)
  4. # mkfs -t ext4 /dev/xvdj
    
  5. ddコマンドでコピー
  6. # dd bs=65536 if=/dev/xvde of=/dev/xvdj
    
  7. ProductCodeが無いVolumeの出来上がり!

やってみたところ出来上がったVolumeはrootデバイスとして起動出来るし他のインスタンスにセカンダリデバイスとしてもアタッチ出来ました。これなら起動不能やログイン不能になっても復旧作業出来ます。

ただ、この作業をしたインスタンスを使用していく必要があるので普通に作成して使用していたインスタンスがトラブル発生した場合は当然手も足もでません。

インスタンス作成時に最初にこの作業してから使っていった方が良いかもしれませんね。

しかし・・・

ProductCodeを除去するこのような作業をしたインスタンスを使っていく場合は以降AWSのサポート外になる模様。。

うーん。。でもそもそも無料サポートのBASICは上限緩和しかサポートメニュー無いから恐れる事はないか・・・?

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で冗長化 その2(DRBD編)

    | コメントをどうぞ

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

    ● Pacemaker + DRBD

    をやります。


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

  • Pacemaker(HeartbeatV2) + DRBD

  • cluster2

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

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

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

    ● 一旦heartbeatを起動

    # /etc/init.d/heartbeat start
    

    DRBD用のxmlファイルを置いて起動するつもりでしたが、何故かうまく行かず一旦起動後に置き換える
    方法を取らないとならなくなっている為。heartbeatでxmlを修正したのにうまく行かない事がありますが
    その場合も置き換えで上手く行く場合が多いです。

    ● 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+DRBD用のファイルを以下のようにどこかのディレクトリ(/tmpなどどこでもOK)用意します。

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

    <cib validate-with="pacemaker-1.0" crm_feature_set="3.0.1" have-quorum="1" dc-uuid="e1c9433f-8e5b-8681-2867-5a4dd5880dfe" admin_epoch="0" epoch="20" num_updates="0" cib-last-written="Wed Sep 17 10:46:40 2014">
      <configuration>
        <crm_config>
          <cluster_property_set id="cib-bootstrap-options">
            <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"/>
            <nvpair id="cib-bootstrap-options-default-resource-stickiness" name="default-resource-stickiness" value="200"/>
            <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"/>
          </cluster_property_set>
        </crm_config>
        <nodes>
          <node id="f76af805-bfff-66bd-3d83-95a20a3807ef" uname="zabbixcluster-1" type="normal"/>
          <node uname="zabbixcluster-2" type="normal" id="e1c9433f-8e5b-8681-2867-5a4dd5880dfe">
            <instance_attributes id="nodes-e1c9433f-8e5b-8681-2867-5a4dd5880dfe"/>
          </node>
        </nodes>
        <resources>
          <master id="ms_drbd_r0">
            <meta_attributes id="ms_drbd_r0-meta_attributes">
              <nvpair id="ms_drbd_r0-meta_attributes-master-max" name="master-max" value="1"/>
              <nvpair id="ms_drbd_r0-meta_attributes-master-node-max" name="master-node-max" value="1"/>
              <nvpair id="ms_drbd_r0-meta_attributes-clone-max" name="clone-max" value="2"/>
              <nvpair id="ms_drbd_r0-meta_attributes-clone-node-max" name="clone-node-max" value="1"/>
              <nvpair id="ms_drbd_r0-meta_attributes-notify" name="notify" value="true"/>
            </meta_attributes>
            <primitive class="ocf" id="drbd_r0" provider="linbit" type="drbd">
              <instance_attributes id="drbd_r0-instance_attributes">
                <nvpair id="drbd_r0-instance_attributes-drbd_resource" name="drbd_resource" value="r0"/>
              </instance_attributes>
              <operations>
                <op id="drbd_r0-monitor-20" interval="20" name="monitor" role="Slave" timeout="20"/>
                <op id="drbd_r0-monitor-10" interval="10" name="monitor" role="Master" timeout="20"/>
                <op id="drbd_r0-start-0" interval="0" name="start" timeout="240"/>
                <op id="drbd_r0-stop-0" interval="0" name="stop" timeout="100"/>
              </operations>
            </primitive>
          </master>
          <group id="group_zabbix">
            <primitive class="ocf" id="mount_r0" provider="heartbeat" type="Filesystem">
              <instance_attributes id="mount_r0-instance_attributes">
                <nvpair id="mount_r0-instance_attributes-device" name="device" value="/dev/drbd0"/>
                <nvpair id="mount_r0-instance_attributes-fstype" name="fstype" value="ext4"/>
                <nvpair id="mount_r0-instance_attributes-directory" name="directory" value="/drbd0"/>
                <nvpair id="mount_r0-instance_attributes-options" name="options" value="noatime"/>
              </instance_attributes>
              <operations>
                <op id="mount_r0-monitor-10" interval="10" name="monitor" timeout="60"/>
                <op id="mount_r0-start-0" interval="0" name="start" timeout="60"/>
                <op id="mount_r0-stop-0" interval="0" name="stop" on-fail="stop" timeout="60"/>
              </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="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="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="db_on_drbd" rsc="mount_r0" score="INFINITY" with-rsc="ms_drbd_r0" with-rsc-role="Master"/>
          <rsc_order first="ms_drbd_r0" first-action="promote" id="order_db_after_drbd" score="INFINITY" then="group_zabbix" then-action="start"/>
        </constraints>
      </configuration>
    </cib>
    

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

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

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

    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
    

    heartbeatで用意されているOCFを使うとDRBDプロセスの他にMaster/Slaveの状態も監視してくれるのでheartbeatのcolocationとorderで指定する事によって、DRBDがMasterで動いている方でZabbix、mysql、httpdを起動するクラスタが構成出来ます。(片系が壊れてStandAloneになってもMasterで動いている方で稼働します。)

    ● DRBDで片系故障時

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

    Zabbixサーバに意図的に障害を起こさせるテストをしていた際に気づいたのですが、状況によってはZabbixサーバが完全に死なない場合があります。親プロセス(usr/sbin/zabbix_server -c /etc/zabbix/zabbix_server.conf)のみがしぶとく生き残る為にheartbeatからは生きているように見えるのですが、実際は監視自体は止まってしまっている場合があります。今回発生が確認出来たのはMySQLは動いているけどZabbixは接続出来ないという状態を動作中に発生させた場合になりました。何らかの対処が必要になります。

    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を冗長化をやってききたいと思います。

    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
  • の設定とテスト結果を書きます。

    AWSの新サービス Zocaloをリミテッドプレビュー申請してみました。

    | 3件の返信

    7月18日(金)のAWS SUMMIT 2014に参加した際にAWSのブースでZocaloなる共有ストレージが紹介されていて興味があったのですが、現段階で配布用の資料などが無かったようで手ぶらで帰ってきました。「テスト(リミテットプレビュー)利用だけならもう出来ますよ」とAWSの方が言っていましたので利用してみました。

    その前にZocaloが何なのか自分が今理解出来ている範囲の概要が以下になります。

    AWS Zocalo概要

    ● 利用可能リージョンはUS、EU。日本リージョンはまだ来ていません。

    ● クラウド上の共有ストレージでブラウザを経由して利用する為特別なアプリケーションのインストール不要で利用が出来る。(同期用の無料専用アプリもあります。)

    ● ブラウザでアクセスする為のURLの一部は自分で任意のものを設定して外部からアクセス出来る。

    ● デスクトップ上のファイルをZocaloにアクセスしているブラウザにドラッグ&ドロップでファイルをアップロード出来る。

    ● ユーザを追加したり権限を設定したり出来る。ActiveDirectoryとも連携出来る。

    ● ブラウザ経由なのでスマートフォン、タブレットからも利用可能。

    ● 1ユーザにつき月額5ドル。ファイルを置ける容量は1ユーザにつき200GBまで。それ以上は1TB迄は0.003ドル/1GB。

    ※ 最初の30日間は無料トライアル

    AWS Zocaloテスト利用申請(リミテッドプレビュー)

    使ってみないとわからない部分が多いので申請して使ってみます。

    AWS Zocaloテスト利用申請

    1. AWSコンソールから申請
    2. 1

      「Zocalo」とメニューが増えているので選択します。

    3. 必要事項記入
    4. 2

    5. AWSからメール受信
    6. 6

      すぐにAWSからメールが届きます。ここで数日待ちます。

    7. 利用可能メール通知
    8. 4

      自分の場合は5日ほどで来ました。

    AWS Zocaloテスト利用開始

    1. AWSコンソールから利用開始
    2. 3

      7

      再度AWSコンソールから利用したリージョンを選択して「Get Started Now」を選択して「Quick Start」と進めていきます。

      8

      Regionを選択した後、SiteURLで任意の部分を記入します。最後に管理者のメールアドレス、名前を入力して「Complete Setup」をクリックします。

      9

      すぐに管理者として設定したメールアドレスにメールが届きます。メール本文内の「Get Started!」をクリックするとZocaloのログイン画面に飛びます。

      ※ 初回はログイン用パスワードを設定します。

      10

      Zocaloログイン後メニュー画面。

      1

    3. ファイルアップロード
    4. ログイン後のメニュー画面。「+Add Content」でローカルPCのファイルを選択するかブラウザ上にファイルをドラッグ&ドロップで追加出来ます。

      ※ フォルダごとアップロードは出来ません。

      フォルダで管理したい場合は「+Create Folder」でコンソールから作成します。

      2

    5. 共有ユーザ作成
    6. 4

      ファイルを共有したいユーザを作成します。「Administration」から「Invite Users」を選択します。

      5

      「Type an Email」の欄に共有ユーザにしたいユーザのメールアドレスを入力するとそのユーザに招待メールが飛びます。

      9

      招待されたユーザに飛ぶメール。招待されたユーザは管理者と同様の手順でZocaloの利用が可能になります。

    7. ファイル共有
    8. ファイルを置いた後にフォルダもしくはファイルを選択して「Shared」を選択します。フォルダを共有した場合は中のファイルが全て共有され以降置いたファイルも共有されます。

      1

      2

      「Share」をクリックします。

      4

      共有したいユーザを入力すると共有出来ます。

      共有された側の画面
      5

      「Shared with me」の項目に表示されます。

    文書の共有をしてみる

    1. ワードファイルを開く




    2. PCで開く

      1

      問題無く見れます。

      iphoneで開く

      image (4)

      問題無く見れます。

    3. パワーポイントを開く


    4. PCで開く

      2

      問題無く見れます。

      iphoneで開く

      image (5)

      問題無く見れます。

    5. エクセルを開く
    6. PCで開く

      3

      問題無く見れます。

      iphoneで開く

      image (6)

      問題無く見れます。ここまでは順調・・・ただしエクセルは枠線は消えます。(罫線は消えません)

    7. テキストを開く
    8. PCで開く

      4

      ・・・文字化けしてます。iphoneで開いても同じように文字化け。どうやらShift-jisのテキストファイルは化けるようです。アップロードする際にUTF-8に変換してからアップロードすると化けないようです。

      UTF-8に変換したテキストファイル

      5

      ここまででわかったこと

      ●インターネット環境とブラウザがあればファイルの閲覧が可能。
      ●ワード、パワーポイント、エクセルがスマートフォンやタブレットでも見れる。
      ●共有したファイルにコメントをつけれる。コメントがつくとメールで通知される。
      ●ファイルを更新するとバージョンが上がり前のバージョンも見れる為、バージョン管理が出来る。
      ●ブラウザから直接ファイルを編集は出来ない模様。

      と、ここまで利用した感じですが申請・利用がインターネット経由で手軽に行える上にスマートフォンやタブレットでも利用が可能な為、外出先から共有資料を見たり、離れた拠点の人にファイルを渡したりなど色々利用できそうです。

    クライアントアプリケーションを使ってみる

    ブラウザのみで使っても便利ですが、直接編集が出来ず一旦ダウンロードして編集して再アップロードしたり、ファイルを一括で削除したりが出来ないようですのでクライアントアプリケーションを利用してみます。クライアントアプリケーションは以下の特徴があります。

    ●ローカルPCの指定フォルダ内とZocaloを同期出来ます。
    ●指定したローカルフォルダ内のファイルを編集すると自動でZocalo側のファイルも更新されます。(バージョン管理付)
    ●同期している為ローカル内を消すとZocaloから消えて、Zocaloから消すとローカル内が消えます。
    ●現在の対応OSはWindows7,Windows8,Windows2003,Windows2008,Mac,iOS,Android。

    Zocaloのメニューからクライアントのダウンロードリンクがあるのですが、今クリックすると何故かダウンロードへ飛ばない為、以下のURLからダウンロードします。

    http://docs.aws.amazon.com/zocalo/latest/userguide/sync_client_help.html#sync_install_windows

    ダウンロードしたファイルをダブルクリックするとインストールが始まります。

    ※ 結構時間かかります。

    1

    インストール後起動するとZocaloのアカウント設定、同期フォルダの設定をします。

    356

    設定完了後は自身のローカルに「zocalo」フォルダが出来上がります。ここにファイルを作成するとZocalo側に同期されます。フォルダを作成するとZocalo側にフォルダが出来ます。ここでワードやエクセル等を編集すればZocalo側も更新され、バージョン管理される為、便利です。

    6

    追記 Zocaloへの同期フォルダを変更したい場合

    クライアントアプリケーションのインストール時にZocaloへ同期するフォルダを設定しますが、これを後からやっぱりNASなどの大きいストレージをマウントしたところに変更したい。という場合はタスクレイのZocaloから一旦登録解除をして再度登録すれば出来ます。

    7

    タスクトレイに常駐している「Zocalo」右クリックして「登録解除」して再度登録時に別のフォルダを登録すれば変更可能です。この時にAWSのZocalo側にあるファイルが変更したローカルPCのフォルダに同期(ダウンロード)されてきますのでたくさんファイルをZocalo上に置いてたりする場合は注意が必要です。この方法でストレージゲートウェイのマウントしているドライブをZocaloに同期して外部へ共有という変わったやり方もできました。

    AWSのSESとPostfixを連携してメール送信

    | 1件のフィードバック

    前回AWSのSESを設定してses-toolsを使ってEC2インスタンスからメールを送信しました。今回はSESとPostfixを連携してメールを送信します。そうすることによって通常のメールサーバ利用と同じ感覚でEC2インスタンスからメールを送信出来ます。ses-toolsを使う場合はアプリケーションがメール送信したい場合そこらへんを書き直さないとなりませんが、Postfixと連携してしまえばこれまで通りの方法を変える事なくメールが送信出来ます。Postfix使った方が配信性能高いでしょうし。(とは言ってもSES側の1秒あたりの送信上限にひっかかれば送れません。ここは実績積んで上限値を上げていけるので。)

    ● 必要な手順

    1. SESとPostfix連携に必要なパッケージのインストール
    2. SES用のユーザのSMTP UsernameとSMTP Password
    3. Postfixの設定変更

    SESとPostfixの連携方法ですが、TLSを利用してSESと連携する方法とStunnelを利用してSESと連携する方法があります。設定方法はどちらを選ぶにしてもAWSのSESの設定方法のページを見てそのままそのとおりに従えってやれば出来てしまいます。。
    (http://docs.aws.amazon.com/ses/latest/DeveloperGuide/postfix.html)

    これで今回は終わり。にしてしまうとなんかまずそうなので、自分が少しはまったポイントと実際の設定ファイルを記載します。特に事情が無い限りはTLSでの接続で良いと思います。Stunnelを使う場合はStunnelの起動も必要になりますし一回ローカルに投げてトンネル通してメール送信したいという要件が無ければTLSでもセキュリティは担保されてますので。

    認証用のユーザ名とパスワードの設定でハマッた

    自分の勘違いが多いに関係してるのですが、ses-toolsを使ってコマンドラインでメール送信する認証情報とSESとPostfixで連携してメール送信に使用する認証情報は別ものです。

    ● ses-toolsでコマンドラインでメール送信に使用する認証情報はses用ユーザの「アクセスキー」「シークレットキー」

    21

    ● SESとPostfix連携で使用する認証情報は「ユーザ名」「パスワード」

    17

    前回は「アクセスキー」「シークレットキー」を使い、「ユーザ名」「パスワード」は今回は使用しませんと言った方が必要になります。

    ユーザ名はAWSユーザ名(ここでいうses-smtp-xxxx)では無いです。「SMTP Username」の欄を使用します。この情報はユーザ作成時に取得出来るのですが、後で取得する方法がわからないです。。なのでユーザ作成時に大事に保存しておきましょう。

    SESとPostfixの連携設定

    ここは冒頭に述べたようにAWSのSES設定方法のサイトを見たまま設定すればほぼほぼいけます。導入に必要なパッケージはyumですぐ入れれます。

    ● 必要なパッケージ導入

    # yum install cyrus-sasl-md5 -y
    # yum -y install cyrus-sasl-plain cyrus-sasl-md5
    

    SESと連携するのに暗号化が必要の為、上記のパッケージが入っていないと送信時にエラーが出ます。

    認証用ファイルを/etc/postfix/sasl_passwdのファイル名で作成します。作成後パーミッションは600にします。

    ● 認証ファイル作成

    email-smtp.us-east-1.amazonaws.com:25 smtpユーザ名:smtpパスワード
    

    ※最初のエンドポイントは利用しているSESのエンドポイントを記述します。

    ● 作成後はファイルを変換します。

    postmap hash:/etc/postfix/sasl_passwd
    

    ● main.cfを記述します。(例です。inet_interfacesなどは適宜変更して下さい。)

    queue_directory = /var/spool/postfix
    command_directory = /usr/sbin
    daemon_directory = /usr/libexec/postfix
    data_directory = /var/lib/postfix
    mail_owner = postfix
    inet_interfaces = localhost
    inet_protocols = all
    mydestination = $myhostname, localhost.$mydomain, localhost
    unknown_local_recipient_reject_code = 550
    relayhost = email-smtp.us-east-1.amazonaws.com:25
    smtp_sasl_auth_enable = yes
    smtp_sasl_security_options = noanonymous
    smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
    smtp_use_tls = yes
    smtp_tls_security_level = encrypt
    smtp_tls_note_starttls_offer = yes
    alias_maps = hash:/etc/aliases
    alias_database = hash:/etc/aliases
    debug_peer_level = 2
    debugger_command =
             PATH=/bin:/usr/bin:/usr/local/bin:/usr/X11R6/bin
             ddd $daemon_directory/$process_name $process_id & sleep 5
    sendmail_path = /usr/sbin/sendmail.postfix
    newaliases_path = /usr/bin/newaliases.postfix
    mailq_path = /usr/bin/mailq.postfix
    setgid_group = postdrop
    html_directory = no
    manpage_directory = /usr/share/man
    sample_directory = /usr/share/doc/postfix-2.6.6/samples
    readme_directory = /usr/share/doc/postfix-2.6.6/README_FILES
    smtp_tls_CAfile = /etc/ssl/certs/ca-bundle.crt
    smtp_tls_loglevel = 1
    

    以上でPostfixを再起動すればSESとPostfixが連携されてメール送信出来ます。

    ● メール送信テスト

    ローカルからmailコマンドで送信してみます。送信元、送信先は前回書いたように登録したアドレスにします。(プロダクト申請してある場合は送信先は自由に送れます。)

    # mail -s "test" -r XX@XX.XX.jp XX@XX.XX.jp
    test
    EOT
    

    ● メールログ

    Jul 30 07:55:12 XX-XX-XX-XX postfix/smtp[3486]: A8B9B22E07: to=, relay=email-smtp.us-east-1.amazonaws.com[]:25, delay=2.3, delays=0.04/0.05/1.4/0.81, dsn=2.0.0, status=sent (250 Ok 0000014786440a44-26997760-0624-4163-b571-a5b9af3208ab-000000)
    

    問題なくメール送信が出来ました。

    StunnelでSESとPostfixの連携設定

    Stunnelを使ってローカルのポートにアクセスしてトンネル経由で送信したい場合の設定を記載します。

    ● 最初にStunnelをyumでインストールします。

    # yum install stunnel -y
    

    ● /etc/stunnelにPostfix用のstunnel.confを作成します。(SESのエンドポイントは適宜変更して下さい。)

    [smtp-tls-wrapper]
    accept  = 2525
    client  = yes
    connect = email-smtp.us-east-1.amazonaws.com:465
    

    ● /etc/postfix/main.cfをstunnel用に設定します。(inet_interface等は適宜変更して下さい。)

    queue_directory = /var/spool/postfix
    command_directory = /usr/sbin
    daemon_directory = /usr/libexec/postfix
    data_directory = /var/lib/postfix
    mail_owner = postfix
    inet_interfaces = localhost
    inet_protocols = all
    mydestination = $myhostname, localhost.$mydomain, localhost
    unknown_local_recipient_reject_code = 550
    relayhost = 127.0.0.1:2525
    smtp_sasl_auth_enable = yes
    smtp_sasl_security_options = noanonymous
    smtp_tls_security_level = may
    smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
    alias_maps = hash:/etc/aliases
    alias_database = hash:/etc/aliases
    debug_peer_level = 2
    debugger_command =
             PATH=/bin:/usr/bin:/usr/local/bin:/usr/X11R6/bin
             ddd $daemon_directory/$process_name $process_id & sleep 5
    sendmail_path = /usr/sbin/sendmail.postfix
    newaliases_path = /usr/bin/newaliases.postfix
    mailq_path = /usr/bin/mailq.postfix
    setgid_group = postdrop
    html_directory = no
    manpage_directory = /usr/share/man
    sample_directory = /usr/share/doc/postfix-2.6.6/samples
    readme_directory = /usr/share/doc/postfix-2.6.6/README_FILES
    smtp_tls_CAfile = /etc/ssl/certs/ca-bundle.crt
    

    ● 認証用のsasl_passwdを作成します。

    127.0.0.1:2525 smtpユーザ名:smtpパスワード
    

    ● 作成後はファイルを変換します。

    # postmap hash:/etc/postfix/sasl_passwd
    

    ● Stunnelを起動します。

    # stunnel /etc/stunnel/stunnel.conf
    

    これでPostfixを起動するとStunnelを使ってPostfixとSES連携でメール送信出来ます。

    ● メールログ

    Aug  1 05:30:35 ip-XX-XX postfix/smtp[1825]: E9DAD22E0A: to=, relay=127.0.0.1[127.0.0.1]:2525, delay=438, delays=436/0.1/0.84/0.82, dsn=2.0.0, status=sent (250 Ok 00000147900c5f6c-9c0facb7-e8c1-4233-9fd6-40205031693e-000000)
    

    ローカルの2525ポートを使ってメールが送信出来ているのがわかります。