ようへいの日々精進XP

よかろうもん

今更 VPC で 複数の AZ をまたいだ ELB を試す(3)〜 涙の自腹アカウントでバランシングについて調べてみる 〜

はじめに

前回 ELB を構築した際に「ありゃ?」と思ったのが AZ 間でバランシングが偏っているような現象が見られたので改めて検証してみることにする。ちなみに、涙の自腹アカウントで検証する。*1


とりあえず構築

構成図

以下のような構成。

f:id:inokara:20131231013817p:plain

ELB の構築

ELB の構築は下記のコマンドで一発。

aws elb create-load-balancer \
--load-balancer-name hugahuga \
--listeners Protocol=HTTP,LoadBalancerPort=80,InstanceProtocol=HTTP,InstancePort=8080 \
--subnets "subnet-123456a" "subnet-123456b" \
--security-groups sg-123456

インスタンスの構築

以下のようなシェルスクリプトで一発作成。

#!/bin/bash

SUBNETS=(subnet1 subnet2)
USERDATA="file://path/to/file"
KEY="Your Key"
AMI="AMI id"
SECURITY_GROUP="Your Security Key"

for i in `seq 1 2`
do
  for SUBNET in ${SUBNETS[@]}
  do
    id=`aws ec2 run-instances \
    --image-id ${AMI} \
    --count 1 \
    --instance-type t1.micro \
    --key-name ${KEY} \
    --security-group-ids ${SECURITY_GROUP} \
    --subnet-id ${SUBNET} \
    --associate-public-ip-address \
    --user-data ${USERDATA} | jq '.Instances[]|.InstanceId' | sed 's/"//g'`
    # regist to tag
    aws ec2 create-tags --resources $id --tags Key=Name,Value=param${i}
    echo ${id}
  done
done

このスクリプトVPC 内の AZ にそれぞれ 2 台ずつインスタンスが構築される。

インスタンスを ELB に登録する

aws elb register-instances-with-load-balancer \
--load-balancer-name hugahuga \
--instances i-123456a i-123456b i-123456c i-123456d

とりあえずこれで ELB の環境は構築だん。暫く時間を置くと以下のようにしてアクセスするとインスタンスのホスト名が返ってくるようになる。

curl "http://hugahuga-123456789.ap-northeast-1.elb.amazonaws.com/"

ELB 配下に 4 インスタンスがいるのでランダムに 4 インスタンス分が返ってくるはず...。

f:id:inokara:20140111120244p:plain

なんだかおかしい...。


調査と結果

調査

あらかじめインスタンスのホスト名と AZ を控えておいて、以下のようなスクリプトを書いて、まずは OS X Mavericks 上で実験。

#!/bin/bash

a=`curl -sv "http://hugahuga-209690661.ap-northeast-1.elb.amazonaws.com/"`
case $a in
  ip-10-0-0-38 ) echo "ap-northeast-1a" ;;
  ip-10-0-1-66 ) echo "ap-northeast-1c" ;;
  ip-10-0-0-136 ) echo "ap-northeast-1a" ;;
  ip-10-0-1-114 ) echo "ap-northeast-1c" ;;
esac

実行すると以下のように出力される。

* Adding handle: conn: 0x7f8349004000
* Adding handle: send: 0
* Adding handle: recv: 0
* Curl_addHandleToPipeline: length: 1
* - Conn 0 (0x7f8349004000) send_pipe: 1, recv_pipe: 0
* About to connect() to hugahuga-12345678900.ap-northeast-1.elb.amazonaws.com port 80 (#0)
*   Trying 54.250.131.xxx...
* Connected to hugahuga-12345678900.ap-northeast-1.elb.amazonaws.com (54.250.131.xxx) port 80 (#0)
> GET / HTTP/1.1
> User-Agent: curl/7.30.0
> Host: hugahuga-12345678900.ap-northeast-1.elb.amazonaws.com
> Accept: */*
>
< HTTP/1.1 200 OK
< Accept-Ranges: bytes
< Content-Type: text/html
< Date: Sat, 11 Jan 2014 04:29:23 GMT
< ETag: "52d0ad03-e"
< Last-Modified: Sat, 11 Jan 2014 02:31:31 GMT
* Server nginx/1.4.3 is not blacklisted
< Server: nginx/1.4.3
< Content-Length: 14
< Connection: keep-alive
<
{ [data not shown]
* Connection #0 to host hugahuga-12345678900.ap-northeast-1.elb.amazonaws.com left intact
ap-northeast-1c

何度実行しても ap-northeast-1c が返ってくる。次に AWS 上の ELB 配下ではないインスタンスから同じスクリプトを実行すると...

< 略 >
* About to connect() to hugahuga-12345678900.ap-northeast-1.elb.amazonaws.com port 80 (#0)
*   Trying 54.250.161.yyy...
* Connected to hugahuga-12345678900.ap-northeast-1.elb.amazonaws.com (54.250.161.57) port 80 (#0)
< 略 >
{ [data not shown]
* Connection #0 to host hugahuga-12345678900.ap-northeast-1.elb.amazonaws.com left intact
ap-northeast-1a

< 略 >
* About to connect() to hugahuga-12345678900.ap-northeast-1.elb.amazonaws.com port 80 (#0)
*   Trying 54.250.131.xxx...
* Connected to hugahuga-12345678900.ap-northeast-1.elb.amazonaws.com (54.250.131.173) port 80 (#0)
< 略 >
{ [data not shown]
* Connection #0 to host hugahuga-12345678900.ap-northeast-1.elb.amazonaws.com left intact
ap-northeast-1c

上記のように期待した通りに AZ 間でバランシング出来ているように見える。よく見ると hugahuga-12345678900.ap-northeast-1.elb.amazonaws.comIP が複数返ってきている...ということは ELB を作成した際に生成される DNS NameDNS ラウンドロビンされているようだ。ということは手元の環境(OS X Mavericks)でアクセスが偏ったように見えているのは単に DNS のキャッシュが原因であることが濃厚。


ということで

後始末

以下のように ELB を削除してインスタンスも削除する。

aws elb delete-load-balancer --load-balancer-name hogehuga

インスタンスTerminate する。

aws ec2 describe-instances --filters "Name=tag-value,Values=elb*" | jq '.Reservations[].Instances[]|.InstanceId'

上記のようにインスタンスid を確認して...

aws ec2 terminate-instances --instance-ids ${インスタンス ID}

として Terminate していく。Terminate すると...

{
    "TerminatingInstances": [
        {
            "InstanceId": "i-123456a",
            "CurrentState": {
                "Code": 32,
                "Name": "shutting-down"
            },
            "PreviousState": {
                "Code": 16,
                "Name": "running"
            }
        }
    ]
}

上記のようなレスポンスが返ってくる。

課金の結果...

f:id:inokara:20140111135402p:plain

今月は年始早々から弄りまくったり、インスタンスを落とすの忘れていたりしたけど上のような感じ。*2

*1:特に理由はない

*2:財務省からクレームはまだ来ないレベルかと