NATインスタンスをAutoScalingで動かしてみた

以前に NATインスタンスを冗長構成にしてみた - log4moto という記事を書いたが、これはRouteTableの書き換えは行うが、インスタンスのリプレースまでは行わないものだった。
今回は "障害発生時に自動的にインスタンスを入れ替える" ために、AutoScalingを利用してみた。

構成図

下準備

  • VPC内のNATインスタンスへの経路が必要なRouteTableにNATタグを作成、Valueには所属するAvailabilityZoneを指定しておく
  • EC2の modify-instance-attribute describe-route-tables delete-route create-route が行えるIAM Roleを作成する

ヘルスチェック用のELBを作成する

今回はELBを利用してヘルスチェックを行いたいと思います。
名前はnatwatcherで作成しました。外部からのアクセスは不要なので、internal ELBにしました。
ヘルスチェック用にCGIを用意するので、ヘルスチェックは下記のように指定しておきます。

  • Ping Target: HTTP:80/cgi-bin/healthcheck/8.8.8.8/8.8.4.4 (疎通監視先のIPアドレスを / 区切りで記述します)
  • Timeout: 59sec
  • Interval: 60sec
  • Unhealthy Threshold: 2
  • Healthy Threshold: 2

ヘルスチェックは、すべてのIPアドレスへの疎通がNGであった時に初めて失敗します。

LaunchConfigを作成する

ユーザデータファイル init.sh はこちらにありますので、手元にダウンロードしてください。
また上記スクリプト中に含まれるヘルスチェック用のCGIこちらです。

$ curl -so init.sh https://gist.github.com/j3tm0t0/8980236/raw/1d4396f213bb4764b80597da30ee359f3d123fb2/init.sh
$ aws autoscaling create-launch-configuration --launch-configuration-name autonat_rev1 --image-id ami-0d13700c --instance-type t1.micro --associate-public-ip-address --iam-instance-profile NAT --key-name keypair --security-groups sg-3fffe65d --user-data file://init.sh

AMIは通常のAmazon Linux AMI。起動時に自動的にPublic IPアドレスを割り振るようにしてあります。

AutoScalingGroup作成

$ aws autoscaling create-auto-scaling-group --auto-scaling-group-name autonat --launch-configuration-name autonat_rev1 --max-size 3 --min-size 0 --desired-capacity 3 --load-balancer-names natwatcher --health-check-type ELB --health-check-grace-period 300 --vpc-zone-identifier subnet-34dd8272,subnet-6fa0f706,subnet-00cee369

先ほど作成したLaunchConfigurationを指定。AZ毎に1台ずつ起動する設定になっています。

動作チェック

プライベートsubnetのインスタンスからpingをうちながら、NATインスタンスにログインして、わざとインターフェースを落としてみます。

$ ssh ec2-54-199-200-244.ap-northeast-1.compute.amazonaws.com
Warning: Permanently added 'ec2-54-199-200-244.ap-northeast-1.compute.amazonaws.com,54.199.200.244' (RSA) to the list of known hosts.

       __|  __|_  )
       _|  (     /   Amazon Linux AMI
      ___|\___|___|

https://aws.amazon.com/amazon-linux-ami/2013.09-release-notes/
9 package(s) needed for security, out of 30 available
Run "sudo yum update" to apply all updates.
[ec2-user@ip-10-0-1-109 ~]$ sudo ifconfig eth0 down
Write failed: Broken pipe

5分ほど待つと、疎通が回復します。

[ec2-user@ip-10-0-251-138 ~]$ ping 8.8.8.8
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=1 ttl=49 time=34.1 ms
64 bytes from 8.8.8.8: icmp_seq=2 ttl=49 time=34.3 ms

64 bytes from 8.8.8.8: icmp_seq=307 ttl=49 time=35.3 ms
64 bytes from 8.8.8.8: icmp_seq=308 ttl=49 time=35.4 ms
 :

ヘルスチェックの間隔を調整する事で、気持ち早く回復させる事も可能です。

TODO

NATインスタンスの仕組み上トラフィックが増えた時にスケールアウトするのは難しいので、インスタンスタイプ毎にAutoScalingGroupを作成して、トラフィックが多くなったらスケールアップとか出来たらよいかも?
もし一日の利用パターンがある程度予想可能なのであれば、scheduled update group actionで行ってもよいかもしれません。

(追記)

EIP自動付与バージョン。ただし、事前にEIPを取得して、AZ毎に使用するEIPを書いておく必要があります。