2012年12月14日金曜日

HAProxyをDNS名で指定したバックエンドのIPアドレスが変わったらリロードする

スズキです。

以前、下記のような記事を書いたのですが、
(ELBとからめて)Hostヘッダでの振り分けをHAProxyでやってみる

次のような指摘をいただきました。


よくよく考えてみれば、その通りで、HAProxyはバックエンドサーバをDNS名で
指定すると、最初に名前解決したIPアドレスをキャッシュし、ずっと使ってしまいます。

そして、ELBは(internalも)をIPスケールアウト/インなどでIPアドレスが変わってしまう
可能性があるので、このままでは、いつか問題が発生してしまいます。

ということで、ELBのDNS名に対するIPアドレスが変更されたら、HAProxyをリロード
(無停止で設定を入れ替える)仕組みをMonitで実現してみました。
(HAProxyのリロードに関する話は下記が大変参考になります)
HAProxy で graceful restart する方法

DNS名に対するIPアドレスの変更をチェックするNagiosプラグイン


Monitの話ですが、表記のチェックに関してはNagiosの監視でも使いそうなので、
Nagiosのプラグインとして作成してみました。

check_dns_ip
#!/bin/sh

. `dirname $0`/utils.sh

set -e
trap 'echo "UNKNOWN: $?"; exit $STATE_UNKNOWN' ERR

WARN=1
CRIT=1

while getopts c:w:n: OPTNAME; do
    case "$OPTNAME" in
    w)
        WARN="$OPTARG"
        ;;
    c)
        CRIT="$OPTARG"
        ;;
    n)
        DNS_NAME="$OPTARG"
        ;;
    *)
        echo "UNKNOWN: Usage"
        exit $STATE_UNKNOWN
        ;;
    esac
done

IP_FILE=`dirname $0`/../../var/run/check_dns_ip-$DNS_NAME.txt
IP_LIST=`dig +noall +answer $DNS_NAME | awk '{print $5}' | sort`

if [ ! -f $IP_FILE ]; then
    echo $IP_LIST > $IP_FILE
    echo "OK : Initial Setup"
    exit $STATE_OK
fi

COUNT=`echo $IP_LIST | diff - $IP_FILE | wc -l`

if   [ $COUNT -ge $CRIT ]; then
    echo "CRITICAL: IP Address Chenged"
    echo $IP_LIST > $IP_FILE
    exit $STATE_CRITICAL
elif [ $COUNT -ge $WARN ]; then
    echo "WARNING: IP Address Chenged"
    echo $IP_LIST > $IP_FILE
    exit $STATE_WARNING
elif [ $COUNT -eq 0 ]; then
    echo "OK: IP Address Not Chenge"
    exit $STATE_OK
fi

echo "UNKNOWN: End"; exit $STATE_UNKNOWN

注意点は下記となります。
  • 同じディレクトリに"utils.sh"が必要
    • "/usr/lib64/nagios/plugins/utils.sh"とかにあったらシンボリックリンクで
  • "../../var/run/"にIPアドレスの状態を保持するファイルが作成できるように
    • ファイルの中身は"10.0.64.53 10.0.65.164"といった感じ
下記のように実行できます。

最初に実行した場合
# ./check_dns_ip -n internal-web-xxx.ap-northeast-1.elb.amazonaws.com
OK : Initial Setup
IPアドレスが変わっていない場合
# ./check_dns_ip -n internal-web-xxx.ap-northeast-1.elb.amazonaws.com
OK: IP Address Not Chenge
IPアドレスが変わった場合
# ./check_dns_ip -n internal-web-xxx.ap-northeast-1.elb.amazonaws.com
CRITICAL: IP Address Chenged
※ステータスファイルもアップデートされるので、このアラートは一回きりです。

Monitの設定ファイルとチェックプログラムの作成


Monitの設定ファイルは次のようにしました。

check_dns_ip_elb.conf
check program check_dns_ip_elb with path "/opt/suz-lab/etc/monit/check_dns_ip_elb.sh"
    if status != 0 then exec "/etc/init.d/haproxy reload"

チェック用のプログラムを実行し、終了ステータスコードが0以外の場合は、
HAProxyをリロードするようにしています。

本当はチェックプログラムは直接、上記で作成したスクリプトを利用したかったのですが、
引数が使えないという制約で、改めて下記のような専用のスクリプトを用意しています。

check_dns_ip_elb.sh
#!/bin/sh
DNS_NAME=internal-web-xxx.ap-northeast-1.elb.amazonaws.com
set -e
trap 'echo "NG: $?"' ERR
/opt/suz-lab/lib/nagios/check_dns_ip -n $DNS_NAME
exit $?
これで、Monitが定期的にELBのアドレスをチェックし、変更があったらHAProxyを
再起動してくれるようになります。

"SUZ-LAB CentOS AMI"で具体的に設定して確認


次のようにGitHubから取ってくるのが早いかもしれません。
# cd /opt/
# git clone https://github.com/suz-lab/suz-lab-centos-ami.git suz-lab
# chmod 755 /opt/suz-lab/lib/nagios/check_dns_ip
# ln -s /usr/lib64/nagios/plugins/utils.sh /opt/suz-lab/lib/nagios/utils.sh
# ls /opt/suz-lab/etc/monit/
README.md  check_dns_ip_elb.conf  check_dns_ip_elb.sh
# cat /etc/monit.conf
...
include /opt/suz-lab/etc/monit/*.conf
# /etc/init.d/monit restart

ELBのIPアドレスが変更されると、次のようにHAProxyがリロードされます。
# cat /var/log/messages
...
Dec 13 23:20:13 ip-10-0-1-52 monit[19484]: 'check_dns_ip_elb' status failed (2) for /opt/suz-lab/etc/monit/check_dns_ip_elb.sh. Error: no output to stderr..
Dec 13 23:20:13 ip-10-0-1-52 monit[19484]: 'check_dns_ip_elb' exec: /etc/init.d/haproxy
Dec 13 23:20:14 localhost haproxy[19612]: Proxy web started.
Dec 13 23:20:14 localhost haproxy[13041]: Pausing frontend proxy.
Dec 13 23:20:14 localhost haproxy[19612]: Proxy proxy started.
Dec 13 23:20:14 localhost haproxy[13041]: Stopping frontend proxy in 0 ms.
Dec 13 23:20:14 localhost haproxy[13041]: Stopping backend web in 0 ms.
Dec 13 23:20:14 localhost haproxy[13041]: Proxy proxy stopped (FE: 0 conns, BE: 0 conns).
Dec 13 23:20:14 localhost haproxy[13041]: Proxy web stopped (FE: 0 conns, BE: 0 conns).
Dec 13 23:21:13 ip-10-0-1-52 monit[19484]: 'check_dns_ip_elb' status succeeded
...

ELBのIPアドレスが変わる挙動も書かないと...
--------
http://www.suz-lab.com

0 コメント: