High Availability for Amazon VPC NAT Instanceを調べてみた。

記事タイトルとURLをコピーする
こんにちは、テクニカルグループの柳瀬です。 Amazonさんのページで紹介されているArticles & Tutorialsは定期的に調べて参考にしているのですが、最近タイトルの記事が紹介されていることに気づいたのでご紹介させて頂きます。

概要

VPC上で環境を構築した場合に考えるポイントの一つとして、NATインスタンスの冗長化があります。 NATインスタンスのダウンがサービスに影響する場合は、きちんと冗長化する必要があります。 今回の元ネタの記事では以下の流れで書かれていました。
  1. Amazon VPCについて
  2. NATインスタンスの使い方と単一障害点になる理由
  3. NATインスタンスの冗長化例と構築方法
ここではAmazon VPCの解説とNATインスタンスの説明は省略させて頂きますが、NATインスタンスの冗長化例を紹介します。

環境構成


1.正常時の構成

以下の図にあるようにパブリック/プライベートサブネットそれぞれで2つのAZを使用しています。 パブリックサブネットにはAZ毎に1台ずつNATインスタンスが配置されていて、プライベートサブネットのEC2インスタンスは自分と同じAZのパブリックサブネットに配置されたNATインスタンスを経由してインターネットに接続します。 この間、NATインスタンスは監視スクリプトでお互いを死活監視している状態になります。

2.障害発生時の構成

NATインスタンスに障害が発生した場合はスクリプトによってルートテーブルが書き換えられ、もう片方のNATインスタンスを経由してインターネットへアクセスします。

3.復旧方法

NATインスタンスに障害が発生した場合は、もう片方のNATインスタンスが障害が発生したNATインスタンスに対してStop/Startを実行します。

4.復旧完了

NATインスタンスが障害から復旧したら、再度ルートテーブルが書き換えられ正常な状態へと戻ります。

環境構築方法


NATインスタンスに割り当てるIAM Roleを作成

2つのNATインスタンスは障害発生時にEC2のAPIを実行します。 とはいえインスタンス内部にアクセスキーIDとシークレットキーの情報を保存したくないので以下のようなIAM Roleを作成します。
{
  "Statement": [
    {
      "Action": [
        "ec2:DescribeInstances",
        "ec2:CreateRoute",
        "ec2:ReplaceRoute",
        "ec2:StartInstances",
        "ec2:StopInstances"
        ],
      "Effect": "Allow",
      "Resource": "*"
    }
  ]
}

VPC環境の作成

構成図のようなVPCネットワークを作成します。 プライベートサブネットのルートテーブルでは、デフォルトルートを同一AZに存在するNATインスタンスに設定します。
  • パブリックサブネットをAZ毎に作成(合計2つ)
  • プライベートサブネットをAZ毎に作成(合計2つ)
  • パブリックサブネットのルートテーブルを作成
  • プライベートサブネットのルートテーブルをサブネット毎に作成(合計2つ)

NAT用インスタンスとしてAmazon Linuxを起動

作成したIAM Roleを割り当て、起動後にSource/Dist CheckをDisableにして下さい。 ※パブリックサブネット内に起動します。

起動したAmazon LinuxをNATインスタンスとしてセットアップ

2台のNATインスタンスに以下のようなコマンドを実行していきます。
$ sudo -s
# cd /root
# yum update aws*
# echo 1 > /proc/sys/net/ipv4/ip_forward
# echo 0 > /proc/sys/net/ipv4/conf/eth0/send_redirects
# /sbin/iptables -t nat -A POSTROUTING -o eth0 -s 0.0.0.0/0 -j MASQUERADE
# /sbin/iptables-save > /etc/sysconfig/iptables
# mkdir -p /etc/sysctl.d/
# cat < /etc/sysctl.d/nat.conf
net.ipv4.ip_forward = 1
net.ipv4.conf.eth0.send_redirects = 0
EOF

スクリプトをダウンロードし、スクリプトの設定を行う

2台のNATインスタンスで以下のようにスクリプトをダウンロードし、実行権限を割り当てます。
# wget http://media.amazonwebservices.com/articles/nat_monitor_files/nat_monitor.sh
# chmod a+x nat_monitor.sh
スクリプト内に以下のようなパラメータの設定をします。
  • NAT_ID=対向側のNATインスタンスID
  • NAT_RT_ID=NAT時に対向のNATインスタンスを経由するルーティングテーブル
  • My_RT_ID=NAT時に自分自身を経由するルーティングテーブル
  • EC2_URL=リージョンを指定(例:https://ec2.us-east-1.amazonaws.com
必要に応じて以下のオプションのパラメータを指定します。
  • Num_Pings
  • Ping_Timeout
  • Wait_Between_Pings
  • Wait_for_Instance_Stop
  • Wait_for_Instance_Start

スクリプトの開始

起動時に実行するようにcron登録する
# echo '@reboot /root/nat_monitor.sh >> /tmp/nat_monitor.log' | crontab
バックグラウンドジョブでスクリプトを実行させる
# ./nat_monitor.sh >> /tmp/nat_monitor.log &

動作確認

インスタンスに障害を発生させて切り替え試験をしてみました。 プライベートサブネットからpingを実行していると、icmp_seq=11〜21が抜けています。 その後icmp_seq=22から通信が復旧している事が分かります。 ルートテーブルが切り戻される部分に関しては特にpingがロスする事はありませんでした。
$ ping google.co.jp
PING google.co.jp (74.125.228.87) 56(84) bytes of data.
64 bytes from iad23s07-in-f23.1e100.net (74.125.228.87): icmp_seq=1 ttl=52 time=3.21 ms
64 bytes from iad23s07-in-f23.1e100.net (74.125.228.87): icmp_seq=2 ttl=52 time=3.11 ms
64 bytes from iad23s07-in-f23.1e100.net (74.125.228.87): icmp_seq=3 ttl=52 time=3.18 ms
64 bytes from iad23s07-in-f23.1e100.net (74.125.228.87): icmp_seq=4 ttl=52 time=3.49 ms
64 bytes from iad23s07-in-f23.1e100.net (74.125.228.87): icmp_seq=5 ttl=52 time=3.16 ms
64 bytes from iad23s07-in-f23.1e100.net (74.125.228.87): icmp_seq=6 ttl=52 time=3.15 ms
64 bytes from iad23s07-in-f23.1e100.net (74.125.228.87): icmp_seq=7 ttl=52 time=3.13 ms
64 bytes from iad23s07-in-f23.1e100.net (74.125.228.87): icmp_seq=8 ttl=52 time=3.36 ms
64 bytes from iad23s07-in-f23.1e100.net (74.125.228.87): icmp_seq=9 ttl=52 time=3.25 ms
64 bytes from iad23s07-in-f23.1e100.net (74.125.228.87): icmp_seq=10 ttl=52 time=3.74 ms
64 bytes from iad23s07-in-f23.1e100.net (74.125.228.87): icmp_seq=22 ttl=54 time=12.3 ms
64 bytes from iad23s07-in-f23.1e100.net (74.125.228.87): icmp_seq=23 ttl=54 time=42.3 ms
64 bytes from iad23s07-in-f23.1e100.net (74.125.228.87): icmp_seq=24 ttl=54 time=4.15 ms
64 bytes from iad23s07-in-f23.1e100.net (74.125.228.87): icmp_seq=25 ttl=54 time=4.14 ms
64 bytes from iad23s07-in-f23.1e100.net (74.125.228.87): icmp_seq=26 ttl=54 time=4.36 ms

==中略==

64 bytes from iad23s07-in-f23.1e100.net (74.125.228.87): icmp_seq=145 ttl=54 time=4.21 ms
64 bytes from iad23s07-in-f23.1e100.net (74.125.228.87): icmp_seq=146 ttl=54 time=4.69 ms
64 bytes from iad23s07-in-f23.1e100.net (74.125.228.87): icmp_seq=147 ttl=54 time=4.23 ms
64 bytes from iad23s07-in-f23.1e100.net (74.125.228.87): icmp_seq=148 ttl=54 time=4.25 ms
64 bytes from iad23s07-in-f23.1e100.net (74.125.228.87): icmp_seq=149 ttl=54 time=4.41 ms
64 bytes from iad23s07-in-f23.1e100.net (74.125.228.87): icmp_seq=150 ttl=54 time=19.5 ms
64 bytes from iad23s07-in-f23.1e100.net (74.125.228.87): icmp_seq=151 ttl=54 time=5.67 ms
64 bytes from iad23s07-in-f23.1e100.net (74.125.228.87): icmp_seq=152 ttl=54 time=4.45 ms
64 bytes from iad23s07-in-f23.1e100.net (74.125.228.87): icmp_seq=153 ttl=54 time=4.36 ms
64 bytes from iad23s07-in-f23.1e100.net (74.125.228.87): icmp_seq=154 ttl=54 time=4.21 ms

まとめ

このような環境を自分で構築すると、NATインスタンスのしくみをきちんと理解出来るし、HA構成を構築する場合のアーキテクチャの参考にもなると思いました。 NATインスタスの監視スクリプトも意図する動作を確認出来ましたし、自分がスクリプトを作るときの参考にもなりそうです。 ちなみにこの環境を構築するのが面倒という方は今回の環境を構築出来るCloudFormationのテンプレートも公開されているようです。

参考