Amazon EC2で「Elastic Load Balancing」オプションを使って負荷分散/冗長化を実現する詳細手順

先日、Amazon Web Servicesより、以下、Amazon EC2関連の新サービスが3つ発表されましたね。

  • Amazon CloudWatch
    • Amazon EC2のインスタンスのリソースをモニタリングすることが可能
  • Auto Scaling
    • Amazon EC2のインスタンスの負荷状況を判断し、自動でインスタンス数を増減させ、スケーリングを実施することが可能
  • Elastic Load Balancing
    • ロードバランサとして、各インスタンスのフロントエンドでトラフィックを分散させることが可能


これら3つは連携させて使うと、なかなか強力な可能性を秘めています。

例えば、「Amazon CloudWatch」にて、バックエンドのAmazon EC2のインスタンスの負荷状況を監視し、負荷量がある一定の閾値を超えた段階で、「Auto Scaling」にて、Amazon EC2のインスタンス数を増加させ、「Elastic Load Balancing」を利用して、新しく起動したAmazon EC2のインスタンスにトラフィックを振り分けることも可能です。

これらのサービスを使うことで、自動的なスケールアウト(負荷分散)、かつシステムの冗長化を簡単に構築することが可能となります。

以下、AWSブログからの引用図ですが、全体のフロー図として参考になると思います。


https://farm4.static.flickr.com/3628/3562521311_02c3ca49ef_o.png
New Features for Amazon EC2: Elastic Load Balancing, Auto Scaling, and Amazon CloudWatch | AWS News Blog より引用


今日は、3つのうちAmazon EC2のインスタンス(仮想サーバ)のフロントエンドで、ロードバランサとして振舞うことの出来る「Elastic Load Balancing」の使い方を紹介したいと思います。


尚、Amazon CloudWatchやAuto Scalingとの連携については、長くなりそうなので、また後日に別エントリで書きたいと思います。

前提・セットアップ

さて、この「Elastic Load Balancing」ですが、ロードバランサの起動時間、およびデータ転送量に応じた従量課金制となっており、起動時は1時間当たり0.025ドル、データ転送量1Gバイト当たり0.008ドルとなっています。
手軽に試せる金額といえますね。


あと、このエントリの前提として、既に、Amazon EC2の操作に関するセットアップは終了しているものとします。
# 基本操作やセットアップについては Amazon EC2/S3を使ってみた - まとめ (Amazon Web Services関連エントリ目次) - 元RX-7乗りの適当な日々 から辿るリンク先を参考にしてください。


では、セットアップに移りましょう。
まず、「Elastic Load Balancing」のAPIを実行するべく、コマンドラインツールのセットアップを行います。
ツールは、以下リンク先からダウンロード可能です。


以下の手順な感じで、ダウンロード〜展開〜設置しましょう。

$ wget http://ec2-downloads.s3.amazonaws.com/ElasticLoadBalancing-2009-05-15.zip
$ unzip ElasticLoadBalancing-2009-05-15.zip
$ sudo mv ElasticLoadBalancing-1.0-1/ /usr/local/ElasticLoadBalancing


次に、環境変数を追加します。

export AWS_ELB_HOME=/usr/local/ElasticLoadBalancing
export PATH=$PATH:${AWS_ELB_HOME}/bin

# 既に、EC2 Command-Line Tools等のセットアップで、${JAVA_HOME}なども設定済の前提です。


以上で、セットアップは完了です。

$ elb-version
Amazon Elastic Load Balancing CLI version 1.0-1 (API 2009-05-15)

を実行して、バージョン情報が表示されればOKです。

早速、ロードバランサを作ってみる

例えば、既に以下のようにEC2のインスタンスが2つ起動しているものとします。
このフロントエンドにロードバランサを配置し、リクエストを振り分けるように設定してみたいと思います。

$ ec2-describe-instances
RESERVATION     r-f70c949e      xxxxxxxxxxxx    default
INSTANCE        i-bb793cd2      ami-a3fb1dca    ec2-174-129-104-205.compute-1.amazonaws.com     domU-12-31-38-00-28-15.compute-1.internalrunning  rx7_key    0               m1.small        2009-05-22T03:10:09+0000        us-east-1c      aki-a71cf9ce    ari-a51cf9cc     monitoring-disabled
RESERVATION     r-fd33ab94      xxxxxxxxxxxx    default
INSTANCE        i-f99fda90      ami-5647a33f    ec2-174-129-164-79.compute-1.amazonaws.com      domU-12-31-38-02-6D-A1.compute-1.internalrunning  rx7_key    0               m1.small        2009-05-22T06:11:13+0000        us-east-1c      aki-a71cf9ce    ari-a51cf9cc     monitoring-disabled

この通り、2台のインスタンスが起動している状態です。
早速ですが、次のコマンドで、ロードバランサをcreateします。

$ elb-create-lb example-lb --availability-zones us-east-1c --listener "protocol=HTTP, lb-port=80, instance-port=80"
DNS-NAME  example-lb-391217788.us-east-1.elb.amazonaws.com

上記コマンドは、第1引数の"example-lb"は任意で付けられるロードバランサ名です。作ったロードバランサがわかるような名前をつけておくと良いでしょう。

"--availability-zones"オプションは、どのゾーンに振り分けるかを指定。インスタンスの稼動しているロケーションを確認の上設定してください。複数指定する場合は、カンマ(,)区切りです。

"--listener"オプションは、上記例を参考にプロトコル、フロントのロードバランサで待ち受けるポート番号、バックエンドの振り分け先(インスタンスで稼動しているサービス)のポート番号を指定します。上記例では、ロードバランサの80番ポートに到達したリクエストを、バックエンドのインスタンスの80番ポートへ振り分ける設定としています。
HTTPと同時にHTTPSも待ち受けたい、など複数のリスナの設定をする場合は、"--listener"オプションを複数記述することも可能です。


ロードバランサのcreateが完了すると、上記例のように標準出力として"DNS-NAME"が表示されます。
このFQDN(URL)にアクセスすると、バックエンドのサービスに振り分けてくれるというわけです。


このFQDNから、自前のDNSサーバ等で好きなドメインネームをCNAMEレコードとして追加してやれば、独自ドメインで使用することも可能になります。

ロードバランサの状況を確認する

以下のコマンドで、、、

$ elb-describe-lbs
LOAD-BALANCER  example-lb  example-lb-391217788.us-east-1.elb.amazonaws.com  2009-05-22T06:36:14.310Z

現在「Elastic Load Balancing」で使用しているロードバランサが確認できます。

ロードバランサにぶらさげるインスタンスを設定する


ロードバランサのバックエンドに配置するインスタンスは、以下のような感じでコマンドを実行します。

$ elb-register-instances-with-lb example-lb --instances i-bb793cd2,i-f99fda90
INSTANCE-ID  i-bb793cd2
INSTANCE-ID  i-f99fda90

コマンドに続けて、ロードバランサ名(create時に指定したもの)と、"--instance"オプションで、Amazon EC2のインスタンスのID("i-xxxxxxxx"形式のもの)を指定するのみです。複数ある場合は、カンマ(,)区切りで指定します。


この状態で、フロントのロードバランサのFQDN(URL)へリクエストを投げてみると、既にバックエンドからレスポンスが返って来るかと思います。まぁ簡単!
(バックエンドの挙動は、ログなどから確認してみましょう。)

バックエンドのヘルスチェック状況を確認する

振り分け設定後は、以下コマンドにてバックエンドのインスタンスの状態を確認することが出来ます。

$ elb-describe-instance-health example-lb
INSTANCE-ID  i-bb793cd2  InService
INSTANCE-ID  i-f99fda90  InService

通常、先ほど設定したバックエンドの2インスタンスが正常に稼動していれば、上記例のように2つとも、"InService"と表示されているはずです。

$ elb-describe-instance-health example-lb
INSTANCE-ID  i-bb793cd2  InService
INSTANCE-ID  i-f99fda90  OutOfService

ちなみに、片方のサービスを停止させて、少し間をあけてから実行すると、上記例のように"OutService"と表示されます。

ロードバランサを削除する

作成したロードバランサが不要となった場合は、以下コマンドにて削除できます。

$ elb-delete-lb example-lb

    Warning: Deleting a LoadBalancer can lead to service disruption to any
    customers connected to the LoadBalancer. Are you sure you want to delete
    this LoadBalancer? [Ny]y
OK-Deleting LoadBalancer

上記例のようにコマンドに続けて、ロードバランサ名を指定します。
さすがに削除時は上記のように本当に削除してよいか確認を求められますので、問題なければ"y"を入力しましょう。

バックエンドのヘルスチェックの設定について

マニュアルを眺めていると、バックエンドのインスタンスのヘルスチェックについても、そこそこ細かく制御できるようです。

elb-configure-healthcheck LoadBalancerName \
--target value \
--healthy-threshold value \
--unhealthy-threshold value \
--interval value \
--timeout value

上記のような感じで実行できるみたいです。
各オプションの詳細は、API仕様を眺めていると、以下のようですね。

  • LoadBalancerName
    • ロードバランサ名
  • target
    • チェック方法、"TCP:80"とか"HTTP:80/status.html"のような感じで記述
  • healthy-threshold
    • チェックOKになるまでの回数、2回〜10回で設定可能、デフォルト3回
  • unhealthy-threshold
    • チェックNGになるまでの回数、2回〜10回で設定可能、デフォルト5回
  • interval
    • チェック間隔、5秒〜600秒で設定可能、デフォルト30秒
  • timeout
    • チェックNGを判断するタイムアウト時間、2秒〜60秒で設定可能、デフォルト5秒、intervalの値以下で設定すること

# 英訳が間違っていたら教えてください(^^;

その他コマンド

上記で紹介しきれなかったコマンドたちをマニュアルレベルwで紹介します。

ここまで紹介してきた手順やオプションの説明から、もう何となく使えちゃうレベルになっているかと思うので、勝手に省略します。(力切れとも言う...)

ロードバランサにぶらさげているインスタンスを外す

elb-deregister-instances-from-lb
Deregisters instances from a LoadBalancer.

elb-deregister-instances-from-lb LoadBalancerName --instances value [, value...]

振り分け先ゾーンの追加

elb-enable-zones-for-lb
Add Availability Zones to an existing LoadBalancer.

elb-enable-availability-zones-for-lb LoadBalancerName --availability-zones value [, value...]

振り分け先ゾーンの削除

elb-disable-zones-for-lb
Remove Availability Zones from a LoadBalancer.

elb-disable-availability-zones-for-lb LoadBalancerName --availability-zones value [, value...]

おわりに

このエントリ、「Elastic Load Balancing」の説明書のようになってしまいましたね。

相変わらず、AWSらしく、コマンド数発でロードバランサが簡単に使えるようになるあたりが、さすがというか。


このロードバランサはL4レベルで動作しているように見えます。
ちなみに、振り分けのアルゴリズムは、チラチラ見ている感じは、なんとなくラウンドロビンで動いているような感じはしますが、詳しく調べていないのでわかりません。何か分かれば追記します。


このオプションは、今回のエントリの流れのように、単体で使用する分にも、冗長化や負荷分散目的で十分に便利化とは思いますが、(冒頭でも書きましたが)モニタリングサービスやオートスケーリングのオプションを組み合わせることで大きな可能性を秘めていると思います。

後日改めて、それらの方法を紹介できれば、と思います。今日はここまで。(十分、長いエントリになってしまった。。。)