Application Load Balancer とは
AWSのロードバランサとしてはElastic Load Balancer(ELB)が従来から存在しますが、これはEC2インスタンスのみを配下に接続可能で、その接続ポートも全インスタンス共通のL4ロードバランサでした。
今回発表のApplication Load Balancerは、EC2の他、ECSによるコンテナインスタンスでポートが異なるサービスを接続したり、URLパスにより接続するインスタンスを変化させる等、L7ロードバランサとして動作します。
もちろんELB同様、ACM(無料のSSL証明書)を用いたSSLターミネートなども利用可能で、基本的にELBの上位互換として動作します。
みんな大好きAWSCLIで使ってみましょう。
elbv2 と呼びます
AWS CLIでの機能名は elbv2 と書かれています。 alb ではありません。
このことからも、AWS内部ではELBバージョン2として作られたことが伺えます。
elbとelbv2の相違点
- elbv2では同一VPCで2以上のAZに2以上のサブネットが必要です。elbは単一サブネットでも構築可能ですがこれができなくなりました。ただし接続するインスタンスは1台でも構いません。
- SSLターミネート処理で、elbv2のみ選択可能な最新ポリシーがある。
前提条件
- ECSでもEC2でも構いませんが2台のインスタンスでWebサービスが2以上稼働していること。
- ここでは2台のインスタンスにポート80でapache、ポート8080でnginxを稼働させています。
- 同一VPCにサブネットが2つ以上存在すること。
- AWSCLI バージョン 1.10.56 以上がインストールされていること。
実行権限
- ELBを操作できること。
AWS CLIのバージョン
elbv2はバージョン1.10.56で追加された機能です。
これより古いバージョンでは動作しませんから必ず確認しましょう。
aws --version
aws-cli/1.10.56 Python/2.6.6 Linux/2.6.32-642.3.1.el6.x86_64 botocore/1.4.46
今回の目的
2台のEC2インスタンスでWebサーバが稼働しており、まずは単純に振り分けることを目的とします。
次に、URLパスによるルーティングを追加する試みとして、/cgi-bin/ 以下のURLへアクセスがあった場合 tcp/8080で動作しているwebサーバへ振り分ける機能を追加します。
- 事前作業
===========
0.1. リージョンの決定
Webサービスが動作しているリージョンで実行します。
ここでは ap-northeast-1 (東京)リージョンにて作業します。
自分の環境に合わせて設定してください。
export AWS_DEFAULT_REGION='ap-northeast-1'
0.2. 変数の確認
プロファイルとリージョンが想定のものになっていることを確認します。
aws configure list
Name Value Type Location
---- ----- ---- --------
profile <not set> None None
access_key ****************M73Q shared-credentials-file
secret_key ****************YWg/ shared-credentials-file
region ap-northeast-1 env AWS_DEFAULT_REGION
- ELBv2の構築
===========
ELBv2では、最初にサブネットを指定してロードバランサの全体環境を構築して、次にターゲットグループと呼ばれる接続先を定義するグループを構築、そして外部からのアクセスを受けるリスナーを構築しこれにターゲットグループを接続してアクセス可能になる流れです。
1.1. サブネットの確認
ELBv2で使用するサブネットを確認してください。ここでは
- subnet-11111111
- subnet-22222222
の2つを使用することにします。自分の環境に合わせて設定してください。
SUBNET_ID1="subnet-11111111"
SUBNET_ID2="subnet-22222222"
(返り値なし)
1.2. VPCIDの確認
上記で使用するサブネットが全て同一のVPCである事を必ず確認してください。
異なるVPCのサブネットは接続出来ません。ここではVPCID
- vpc-33333333
を使用することにします。自分の環境に合わせて設定してください。
VPC_ID="vpc-33333333"
(返り値なし)
1.3. 登録するインスタンスとポート番号
ロードバランサへ登録するインスタンスを確認してください。ここでは
- i-55555555 ポート番号80
- i-66666666 ポート番号80
の2つを使用することにします。自分の環境に合わせて設定してください。
INSTANCE1_ID="i-55555555"
INSTANCE1_PORT="80"
INSTANCE2_ID="i-66666666"
INSTANCE2_PORT="80"
(返り値なし)
1.4. セキュリティグループの作成
セキュリティグループ elbv2-cli-sg を作成します。
SG_NAME="elbv2-cli-sg"
aws ec2 create-security-group --group-name ${SG_NAME} --description ${SG_NAME} --vpc-id ${VPC_ID}
SG_ID=`aws ec2 describe-security-groups --filter Name=group-name,Values=${SG_NAME} \
--query 'SecurityGroups[].GroupId' --output text` && echo ${SG_ID}
{
"GroupId": "sg-99999999"
}
sg-99999999
外部からのHTTP接続をセキュリティグループに追加。
aws ec2 authorize-security-group-ingress --group-id ${SG_ID} --protocol 'tcp' --port 80 --cidr 0.0.0.0/0
(返り値なし)
1.5. アプリケーションロードバランサの作成
それでは作成します。名前を elbv2-cli とします。(任意の名前可)
ELB_NAME="elbv2-cli"
ELB_ARN=`aws elbv2 create-load-balancer --name ${ELB_NAME} \
--subnets ${SUBNET_ID1} ${SUBNET_ID2} --security-groups ${SG_ID} \
--query LoadBalancers[].LoadBalancerArn --output text `
DNSName=`aws elbv2 describe-load-balancers --load-balancer-arns ${ELB_ARN} \
--query LoadBalancers[].DNSName --output text `
aws elbv2 describe-load-balancers --load-balancer-arns ${ELB_ARN}
{
"LoadBalancers": [
{
"VpcId": "vpc-33333333",
"LoadBalancerArn": "arn:aws:elasticloadbalancing:ap-northeast-1:777777777777:loadbalancer/app/elbv2-cli/bd12da1588c83561",
"State": {
"Code": "provisioning"
},
"DNSName": "elbv2-cli-1743316501.ap-northeast-1.elb.amazonaws.com",
"SecurityGroups": [
"sg-99999999"
],
"LoadBalancerName": "elbv2-cli",
"CreatedTime": "2016-08-13T01:21:05.500Z",
"Scheme": "internet-facing",
"Type": "application",
"CanonicalHostedZoneId": "Z14GRHDCWA56QT",
"AvailabilityZones": [
{
"SubnetId": "subnet-11111111",
"ZoneName": "ap-northeast-1a"
},
{
"SubnetId": "subnet-22222222",
"ZoneName": "ap-northeast-1c"
}
]
}
]
}
1.6. ターゲットグループの作成(通常アクセス用)
HTTP(tcp/80)でアクセスを受けるターゲットグループを作成します。
ELB_TG_NAME="elbv2-cli-tg"
ELB_TG=`aws elbv2 create-target-group --name ${ELB_TG_NAME} --protocol HTTP --port 80 --vpc-id ${VPC_ID} \
--query TargetGroups[].TargetGroupArn --output text `
aws elbv2 describe-target-groups --target-group-arns ${ELB_TG}
{
"TargetGroups": [
{
"HealthCheckPath": "/",
"HealthCheckIntervalSeconds": 30,
"VpcId": "vpc-33333333",
"Protocol": "HTTP",
"HealthCheckTimeoutSeconds": 5,
"HealthCheckProtocol": "HTTP",
"UnhealthyThresholdCount": 2,
"HealthyThresholdCount": 5,
"TargetGroupArn": "arn:aws:elasticloadbalancing:ap-northeast-1:777777777777:targetgroup/elbv2-cli-tg/de1a0a8eabbabd2f",
"Matcher": {
"HttpCode": "200"
},
"HealthCheckPort": "traffic-port",
"Port": 80,
"TargetGroupName": "elbv2-cli-tg"
}
]
}
1.7. ターゲットグループへインスタンスを登録
稼働しているWebサービスのインスタンスをターゲットグループへ登録します。
このようにインスタンスIDとポート番号の組み合わせで登録するので、コンテナインスタンスで複数のWebサービスコンテナが稼働していてもそれらを登録することができます。
aws elbv2 register-targets --target-group-arn ${ELB_TG} \
--targets Id=${INSTANCE1_ID},Port=${INSTANCE1_PORT} Id=${INSTANCE2_ID},Port=${INSTANCE2_PORT}
返り値なし
ポート番号をここでは全て指定していますが、ターゲットグループで設定したポート番号をインスタンス側でも使用する場合は省略可能です。(この例ではtcp/80)
何か表示されたらエラーなので確認しましょう。
1.8. リスナの作成
最後に外部からHTTP(tcp/80)でアクセスを受けるリスナを作成して、先に作成したターゲットグループを接続してアクセスできるようにします。
ELB_LISTENER=`aws elbv2 create-listener --load-balancer-arn ${ELB_ARN} --protocol HTTP --port 80 \
--default-actions Type=forward,TargetGroupArn=${ELB_TG} \
--query Listeners[].ListenerArn --output text `
aws elbv2 describe-listeners --listener-arns ${ELB_LISTENER}
{
"Listeners": [
{
"Protocol": "HTTP",
"DefaultActions": [
{
"TargetGroupArn": "arn:aws:elasticloadbalancing:ap-northeast-1:777777777777:targetgroup/elbv2-cli-tg/de1a0a8eabbabd2f",
"Type": "forward"
}
],
"LoadBalancerArn": "arn:aws:elasticloadbalancing:ap-northeast-1:777777777777:loadbalancer/app/elbv2-cli/bd12da1588c83561",
"Port": 80,
"ListenerArn": "arn:aws:elasticloadbalancing:ap-northeast-1:777777777777:listener/app/elbv2-cli/bd12da1588c83561/f1edf2404136e22f"
}
]
}
- アクセスして動作確認
========
実際にDNSNameへアクセスしてWebページが表示されるか確認しましょう。
curl http://${DNSName}
Webページの内容が表示される
普通にWebブラウザでアクセスしてももちろん構いません。
- Pass-Based ルーティングの追加
========
ここまででロードバランサは動作しました。
次に、特定のURLのみ別のサーバへ振り分けるPass-Based Routing の追加を行います。
ここでは /cgi-bin/ へのアクセスをポート8080で受けるインスタンスへ振り分けることにします。
3.1. 登録するインスタンスとポート番号
ここでは
- i-55555555 ポート番号8080
- i-66666666 ポート番号8080
の2つを使用することにします。自分の環境に合わせて設定してください。
INSTANCE3_ID="i-55555555"
INSTANCE3_PORT="8080"
INSTANCE3_ID="i-66666666"
INSTANCE3_PORT="8080"
(返り値なし)
3.1. ターゲットグループの構築(Pass-Based Routing用)
Pass Based Routingはターゲットグループに設定します。
このため、新しくターゲットグループを作成します。
ELB_TG2_NAME="elbv2-cli-tg2"
ELB_TG2=`aws elbv2 create-target-group --name ${ELB_TG2_NAME} --protocol HTTP --port 80 --vpc-id ${VPC_ID} \
--query TargetGroups[].TargetGroupArn --output text `
aws elbv2 describe-target-groups --target-group-arns ${ELB_TG2}
{
"TargetGroups": [
{
"HealthCheckPath": "/",
"HealthCheckIntervalSeconds": 30,
"VpcId": "vpc-33333333",
"Protocol": "HTTP",
"HealthCheckTimeoutSeconds": 5,
"HealthCheckProtocol": "HTTP",
"UnhealthyThresholdCount": 2,
"HealthyThresholdCount": 5,
"TargetGroupArn": "arn:aws:elasticloadbalancing:ap-northeast-1:777777777777:targetgroup/elbv2-cli-tg2/de1a0a8eabbabe8f",
"Matcher": {
"HttpCode": "200"
},
"HealthCheckPort": "traffic-port",
"Port": 80,
"TargetGroupName": "elbv2-cli-tg2"
}
]
}
3.2. ターゲットグループへインスタンスを登録(Pass-Based Routing用)
aws elbv2 register-targets --target-group-arn ${ELB_TG2} \
--targets Id=${INSTANCE3_ID},Port=${INSTANCE3_PORT} Id=${INSTANCE4_ID},Port=${INSTANCE4_PORT}
返り値なし
3.3. リスナへルールを追加
リスナへPass-Based Routingのルールを追加し、/cgi-bin/ へのアクセスを振り分けるターゲットグループを設定します。
aws elbv2 create-rule --listener-arn ${ELB_LISTENER} --priority 10 \
--conditions Field=path-pattern,Values='/cgi-bin/*' \
--actions Type=forward,TargetGroupArn=${ELB_TG2}
{
"Rules": [
{
"Priority": "10",
"Conditions": [
{
"Field": "path-pattern",
"Values": [
"/cgi-bin/*"
]
}
],
"RuleArn": "arn:aws:elasticloadbalancing:ap-northeast-1:777777777777:listener-rule/app/elbv2-cli/51d50a8cdff26750/35560600bd1e51e2/89c54c4e952b753a",
"IsDefault": false,
"Actions": [
{
"TargetGroupArn": "arn:aws:elasticloadbalancing:ap-northeast-1:777777777777:targetgroup/elbv2-cli-tg2/d83dd8bc4d9e2f86",
"Type": "forward"
}
]
}
]
}
- アクセスして動作確認
========
実際にDNSNameへアクセスしてWebページが表示されるか確認しましょう。
curl http://${DNSName}/
curl http://${DNSName}/cgi-bin/
/ へアクセスするとapacheが、
/cgi-bin/ へアクセスするとnginxが応答を返せば成功です。
普通にWebブラウザでアクセスしてももちろん構いません。
セキュリティグループで外部からはポート80しかアクセス許可していないのに、インスタンス上ではポート8080で動作しているnginxが返事をしていることからロードバランサが正しく動作していることがわかるかと思います。
- まとめ
===========
外部からアクセスを受けるリスナでURLなどの条件から振り分け先のターゲットグループを決め、振り分けられたターゲットグループが配下のインスタンスへトラヒックを流す。
という2段階で動作しているのが従来のELBと異なるので最初はアクセス出来ず戸惑いましたが、わかれば簡単に構築できました。
SSL証明書の登録とターミネートについては追って書きたいと思います。