Amazon VPC との間に確立した VPN の状態は、マネジメントコンソールから確認することができるほか、EC2 API Tools からも確認することができます。
ec2-describe-vpn-connections コマンドまたは ec2dvpn コマンド使って、リージョンと VPN ID を指定してやると以下のような出力が得られ、VPN がリンクアップしているかを確認できます。
$ ec2dvpn --region ap-northeast-1 vpn-7axxxxxx VPNCONNECTION vpn-7axxxxxx available ipsec.1 cgw-1984xxxx vgw-d885xxxx false TUNNEL 27.0.1.16 UP Thu Dec 26 09:47:46 JST 2013 1 BGP ROUTES 0 TUNNEL 27.0.1.144 UP Thu Dec 26 09:48:54 JST 2013 1 BGP ROUTES 0
これだけでも VPN の状態を確認するのには十分なのですが、VPN の状態をコマンドの終了コードとして取得するためには以下のようなシェルスクリプトにします。引数でリージョンと VPN ID を指定します。
# !/bin/sh # # Make sure following environment variables are set # EC2_CERT # EC2_PRIVATE_KEY # JAVA_HOME # PATH # # EXIT CODES # 0 At least one of two tunnels is up. # 1 All tunnels are down. # REGION=ap-northeast-1 while [ $# -gt 0 ]; do case "$1" in -h|--help) echo "usage: $0 [-h] [--region REGION] --vpn VPN" exit ;; --region) shift REGION=$1 ;; --vpn) shift VPN_CONN_ID=$1 ;; esac shift done ec2dvpn --region "${REGION}" "${VPN_CONN_ID}" | \ grep ^TUNNEL | awk -F'\t' '{print $3}' | grep -q UP exit $?
下記例のようにして実行します。
$ ./vpn_status.sh --region ap-northeast-1 --vpn vpn-7axxxxxx
VPN トンネルが2本ともダウンしている場合に終了コード1、1本でもアップなら終了コード0となるため、コマンドの戻り値によってシェルのプロンプトの色が変わるように設定していると、このような結果になります。画像は直前のコマンドが失敗するとプロンプトが赤くなるように設定しているため、Amazon VPC との VPN がダウンしている状態を表します。
VPN コネクションの状態がコマンドの終了コードとなるため、下記の様に他のコマンドと組み合わせて応用することができます。これは VPN がダウンしている場合に CD ドライブのトレイが飛び出し、アップしているとトレイが引っ込むという例です。
$ ./vpn_status.sh --region ap-northeast-1 --vpn vpn-7axxxxxx && eject -t || eject あるいは $ ./vpn_status.sh --region ap-northeast-1 --vpn vpn-7axxxxxx; if [ $? -eq 0 ]; then eject -t; else; eject; fi
これを cron で適当な間隔で実行すれば、一定時間ごとに VPN のコネクションを監視しダウンしていれば CD ドライブのトレイが飛び出し、復旧したら引っ込むという仕組みを作ることができます。
しかし、EC2 API Tools は Java で書かれているため、コマンド実行ごとに Java VM を起動するコストが大きく実行に時間がかかるという欠点があります。ec2dvpn コマンドを使って VPN の状態を取得を行ってみると、10回の平均で9.55秒かかっていました。そこで、EC2 API Tools を AWS の Python インターフェイスである boto に置き換えてみます。boto のインストール方法は pip など環境によって様々なので省略します。
前出のシェルスクリプトを Python で置き換えたものがこちらです。実行するには AWS のアクセスキーを取得して AWS_ACCESS_KEY_ID と AWS_SECRET_ACCESS_KEY という環境変数にそれぞれセットしておく必要があります。
#!/usr/bin/env python # -*- coding: utf-8 -*- # # Make sure following environment variables are set # AWS_SECRET_ACCESS_KEY # AWS_ACCESS_KEY_ID # # EXIT CODES # 0 At least one of two tunnels is up. # 1 All tunnels are down. import argparse import os import sys import boto import boto.vpc parser = argparse.ArgumentParser(description='Returns Amazon VPC Hardware VPN status') parser.add_argument('--region', default='ap-northeast-1', help='specify region') parser.add_argument('--vpn', required=True,help='specify VPN connection ID') args = parser.parse_args() UP = 'UP' DOWN = 'DOWN' vpc = boto.vpc.connect_to_region(args.region) vpns = vpc.get_all_vpn_connections(args.vpn) vpn = vpns[0] # the number of vpn connections is always 1 # the number of tunnels is always 2 if vpn.tunnels[0].status == DOWN and vpn.tunnels[1].status == DOWN : sys.exit(1) else : sys.exit(0)
実行方法は前出のシェルスクリプトと同じで、リージョンと VPN ID を引数で与えます。こちらは10回の平均実行時間は0.42秒でした。EC2 API Tools を使う場合と比べて、約22倍高速に実行できています。
$ ./vpn_status.py --region ap-northeast-1 --vpn vpn-7axxxxxx
crontab に AWS のアクセスキーを書いて、毎分チェックを行うようにすれば Amazon VPC VPN の eject 監視ソリューションの完成です。コマンドやコードはいずれも例なので、それぞれの環境に合わせて適切に設定してください。
AWS_ACCESS_KEY_ID=foo AWS_SECRET_ACCESS_KEY=bar PATH=/sbin:/bin:/usr/sbin:/usr/bin * * * * * (/path/to/vpn_status.py --region ap-northeast-1 --vpn vpn-7axxxxxx; if [ $? -eq 0 ]; then eject -t; else; eject; fi)