NATインスタンスを冗長構成にしてみた

Wizardによる標準構成のVPCにおいてNATインスタンスはSPOFであり、インスタンス障害や、単一AZの障害、AZ間接続障害によっても両AZのインターネット接続性が損なわれる可能性がある。そこで、NATインスタンスをAZ毎に用意し、障害発生時にfailoverする仕組みを考えてみた。

方針

  • なるべくAWSの1リージョン内で完結し、別リージョンや外部に監視用ホストなどをおかない
  • 瞬間的にフェイルオーバーはおこなわず、毎分ごとにインターネット上のターゲットIPへの疎通を確認し、障害と思われる状態になったらフェイルオーバーを行う
  • 疎通が回復したと思われた場合には、元の状態に戻す

構成

非常にわかりづらい図になっていますが、構成要素としては

  • Subnet x 4 (Public, Private を AZ毎に1つずつ)
  • NATインスタンス x 2 (AZ毎に1つずつ、当然ElasticIPも1つずつ付与)
  • Privateに属するEC2インスタンス
  • RouteTable x 4 (基本的にはSubnet1つに1つ対応、ただし障害発生時にはPrivate側は同じ物を使用する)

のみです。

デモ

まずはデモをご覧ください。

画面が3つに分かれていますが、それぞれ

となっています。

  1. プライベートなEC2インスタンスからpingをwww.yahoo.co.jpへ打っている間に、NAT-1bが落ちたりして疎通ができなくなったとします(ムービーではsrc/dst checkをenableにする事で、NATインスタンスとして動作しないようにしています)。
  2. そしてNAT-1aであるスクリプトが動作すると、NAT-1bが動作していない事を検出し、1bのプライベートsubnetに関連付けされているRouteTableを、1a経由の物にします。
  3. NAT-1bが復旧(src/dst checkをdisable)してからまたスクリプトを動かすと、復旧を確認してRouteTableを元の1bを経由するものに戻します。

しくみ

Public側のRouteTableに仕掛けがあります。1a側は8.8.4.4/32->NAT-1b、1b側は8.8.8.8/32->NAT-1aというたすき掛け状態にしてあります。こうする事により、pingコマンドで簡単に他方のNATインスタンスの稼働状況を確認する事ができます (ただし8.8.8.8,8.8.4.4に到達できない事はないだろうという前提の元に成立しているものですので、完全ではありません)。
この状態で、NATインスタンス上で↓のようなスクリプトを動作させます(cron等で毎分実行など)。

最後に

あらかじめIAM Roleで必要な権限を与えておくと、credentialを渡す必要がなくてグッドです。
また、NATインスタンスのEC2 API Toolsは結構古いので、updateする( sudo yum update aws-apitools-ec2 )のを忘れないようにしましょう。

補足

つまりこういう事です