- AWS
ALBをAWS CLIで作成|ターゲットグループ・リスナー・ルール設定
ALB(Application Load Balancer)を AWS CLI で作るときは、aws elbv2 の 5 つのコマンドを「ロードバランサー → ターゲットグループ → ターゲット登録 → リスナー → ルール」の順に実行します。 後ろのコマンドは前のコマンドが返す ARN を必要とするので、--query で ARN を変数に受け取りながら進めるのがコツです。
この記事では、5 つのコマンドを 1 本のスクリプトにまとめて実行した出力を載せ、ヘルスチェックのオプション、ルールの条件とアクションの JSON、作成時に出やすいエラー文、そして依存関係に沿った削除の順番までを扱います。
確認環境:Ubuntu 24.04、AWS CLI 1.46.1、Python 3.11。AWS の API をローカルで再現するツール(moto 5.2.3)で実行しました。掲載するコマンドは、ローカル向けの接続先指定を外して AWS でそのまま使える形にしています。アカウント ID は例示用の 123456789012 です。
ALB 作成コマンドの早見表
作る順番と、それぞれが何を必要とするかを先に押さえます。
| 順 | 作るもの | コマンド | 必要なもの | 受け取る値 |
|---|---|---|---|---|
| 1 | ロードバランサー | aws elbv2 create-load-balancer |
2 つ以上の AZ のサブネット、セキュリティグループ | ロードバランサーの ARN |
| 2 | ターゲットグループ | aws elbv2 create-target-group |
VPC ID、プロトコル、ポート | ターゲットグループの ARN |
| 3 | ターゲット登録 | aws elbv2 register-targets |
2 の ARN、インスタンス ID | (出力なし) |
| 4 | リスナー | aws elbv2 create-listener |
1 と 2 の ARN | リスナーの ARN |
| 5 | ルール | aws elbv2 create-rule |
4 の ARN、転送先の ARN、優先度 | ルールの ARN |
確認・変更・削除でよく使うコマンドも並べておきます。
| やりたいこと | コマンド |
|---|---|
| ターゲットの状態を見る | aws elbv2 describe-target-health --target-group-arn ARN |
| ルールを一覧する | aws elbv2 describe-rules --listener-arn ARN |
| ヘルスチェックを変える | aws elbv2 modify-target-group --target-group-arn ARN --health-check-path /healthz |
| ルールの条件を変える | aws elbv2 modify-rule --rule-arn ARN --conditions … |
| ルールの優先度を変える | aws elbv2 set-rule-priorities --rule-priorities RuleArn=ARN,Priority=5 |
| ターゲットを外す | aws elbv2 deregister-targets --target-group-arn ARN --targets Id=i-xxxx |
| 削除する(この順で) | delete-rule → delete-listener → delete-load-balancer → delete-target-group |
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「ALBをAWS CLIで作成|ターゲットグループ・リスナー・ルール設定」
ALB を構成する 4 つの部品
ALB は「ロードバランサー本体」「リスナー」「ルール」「ターゲットグループ」の 4 つでできています。 リクエストは次の流れで振り分けられます。
flowchart LR
C[クライアント] --> L[リスナー HTTP:80]
L --> R1{ルール 優先度10<br>パスが /api/ で始まる}
R1 -- 一致 --> T2[ターゲットグループ api-tg]
R1 -- 不一致 --> D[デフォルトルール]
D --> T1[ターゲットグループ web-tg]
T1 --> I1[EC2 インスタンス 1]
T1 --> I2[EC2 インスタンス 2]
T2 --> I1
| 部品 | 役割 |
|---|---|
| ロードバランサー | 入口。サブネットとセキュリティグループに置かれ、DNS 名を持つ |
| リスナー | 待ち受けるプロトコルとポート。どのルールにも合わないときのデフォルトアクションを持つ |
| ルール | 条件(パス・ホストなど)とアクション(転送・リダイレクト・固定レスポンス)の組。優先度の数字が小さい順に評価される |
| ターゲットグループ | 転送先の集まり。ヘルスチェックの設定もここに持つ |
5 つのコマンドを通しで実行するスクリプト
前のコマンドの出力から --query '…Arn' --output text で ARN を取り出し、変数に入れて次へ渡します。 VPC・サブネット・セキュリティグループ・EC2 インスタンスは作成済みとし、冒頭の変数に自分の環境の値を入れます。
#!/bin/bash
# ALB 一式を作成する(VPC・サブネット・セキュリティグループ・EC2 は作成済みの前提)
set -euo pipefail
# ---- 自分の環境の値に置き換える ----
VPC_ID=vpc-xxxxxxxx
SUBNET_A=subnet-aaaaaaaa # ap-northeast-1a
SUBNET_C=subnet-cccccccc # ap-northeast-1c
SG_ID=sg-xxxxxxxx # 80 番を許可したセキュリティグループ
INSTANCE_1=i-xxxxxxxxxxxxxxxxx
INSTANCE_2=i-yyyyyyyyyyyyyyyyy
# ------------------------------------
# vars.sh に同じ変数を書いておくと、そちらの値を使う
[ -f ./vars.sh ] && . ./vars.sh
# 1. ロードバランサー
ALB_ARN=$(aws elbv2 create-load-balancer \
--name web-alb --type application --scheme internet-facing \
--subnets "$SUBNET_A" "$SUBNET_C" --security-groups "$SG_ID" \
--query 'LoadBalancers[0].LoadBalancerArn' --output text)
echo "ALB_ARN=$ALB_ARN"
# 2. ターゲットグループ(Web 用と API 用)
TG_ARN=$(aws elbv2 create-target-group \
--name web-tg --protocol HTTP --port 80 --vpc-id "$VPC_ID" \
--target-type instance \
--health-check-path /health \
--health-check-interval-seconds 15 --health-check-timeout-seconds 5 \
--healthy-threshold-count 3 --unhealthy-threshold-count 2 \
--matcher HttpCode=200-299 \
--query 'TargetGroups[0].TargetGroupArn' --output text)
echo "TG_ARN=$TG_ARN"
API_TG_ARN=$(aws elbv2 create-target-group \
--name api-tg --protocol HTTP --port 8080 --vpc-id "$VPC_ID" \
--query 'TargetGroups[0].TargetGroupArn' --output text)
echo "API_TG_ARN=$API_TG_ARN"
# 3. ターゲット登録
aws elbv2 register-targets --target-group-arn "$TG_ARN" \
--targets Id="$INSTANCE_1" Id="$INSTANCE_2"
aws elbv2 register-targets --target-group-arn "$API_TG_ARN" \
--targets Id="$INSTANCE_1",Port=8080
# 4. リスナー(既定の転送先は web-tg)
LISTENER_ARN=$(aws elbv2 create-listener \
--load-balancer-arn "$ALB_ARN" --protocol HTTP --port 80 \
--default-actions Type=forward,TargetGroupArn="$TG_ARN" \
--query 'Listeners[0].ListenerArn' --output text)
echo "LISTENER_ARN=$LISTENER_ARN"
# 5. ルール(/api/* は api-tg へ)
RULE_ARN=$(aws elbv2 create-rule \
--listener-arn "$LISTENER_ARN" --priority 10 \
--conditions Field=path-pattern,Values='/api/*' \
--actions Type=forward,TargetGroupArn="$API_TG_ARN" \
--query 'Rules[0].RuleArn' --output text)
echo "RULE_ARN=$RULE_ARN"
# 6. 確認
aws elbv2 describe-load-balancers --load-balancer-arns "$ALB_ARN" \
--query 'LoadBalancers[0].[LoadBalancerName,Scheme,Type,State.Code]' --output text
aws elbv2 describe-rules --listener-arn "$LISTENER_ARN" \
--query 'Rules[].[Priority,Conditions[0].Values[0],Actions[0].Type]' --output text
create-alb.sh として保存して実行した出力です。
bash create-alb.sh
ALB_ARN=arn:aws:elasticloadbalancing:ap-northeast-1:123456789012:loadbalancer/app/web-alb/b697ed833a1f4371
TG_ARN=arn:aws:elasticloadbalancing:ap-northeast-1:123456789012:targetgroup/web-tg/21804fae0e99e108
API_TG_ARN=arn:aws:elasticloadbalancing:ap-northeast-1:123456789012:targetgroup/api-tg/881bde866f9d157d
LISTENER_ARN=arn:aws:elasticloadbalancing:ap-northeast-1:123456789012:listener/app/web-alb/b697ed833a1f4371/69d2e7a15c787a23
RULE_ARN=arn:aws:elasticloadbalancing:ap-northeast-1:123456789012:listener-rule/app/web-alb/b697ed833a1f4371/69d2e7a15c787a23/45569358fab49318
web-alb internet-facing application active
10 /api/* forward
default None forward
ARN の形を見ると親子関係がわかります。 リスナーの ARN はロードバランサーの ID(b697ed833a1f4371)を含み、ルールの ARN はさらにリスナーの ID(69d2e7a15c787a23)を含みます。一方、ターゲットグループの ARN はロードバランサーの ID を含まず、独立した部品です。この違いが、あとで説明する削除の順番に関わります。
あとから ARN を取り直したいときは、名前から引けます。
ALB_ARN=$(aws elbv2 describe-load-balancers --names web-alb \
--query 'LoadBalancers[0].LoadBalancerArn' --output text)
TG_ARN=$(aws elbv2 describe-target-groups --names web-tg \
--query 'TargetGroups[0].TargetGroupArn' --output text)
LISTENER_ARN=$(aws elbv2 describe-listeners --load-balancer-arn $ALB_ARN \
--query 'Listeners[0].ListenerArn' --output text)
各コマンドの出力を読む
スクリプトでは ARN だけを取り出しましたが、--query を外すと各コマンドは作成したものの全体を JSON で返します。順に見ていきます。ID は実行のたびに変わるため、このあとの出力例には ARN の末尾が異なるものがあります。
create-load-balancer の出力
aws elbv2 create-load-balancer \
--name web-alb --type application --scheme internet-facing \
--subnets $SUBNET_A $SUBNET_C --security-groups $SG_ID
{
"LoadBalancers": [
{
"LoadBalancerArn": "arn:aws:elasticloadbalancing:ap-northeast-1:123456789012:loadbalancer/app/web-alb/9b51716b97e33a95",
…(省略)…
"LoadBalancerName": "web-alb",
"Scheme": "internet-facing",
"VpcId": "vpc-7b70ce50cc026ce8e",
"State": {
"Code": "provisioning"
},
"Type": "application",
"AvailabilityZones": [
{
"ZoneName": "ap-northeast-1a",
"SubnetId": "subnet-38887ef06a72f5ac0"
},
{
"ZoneName": "ap-northeast-1c",
"SubnetId": "subnet-fbc82fd9c64a99153"
}
],
"SecurityGroups": [
"sg-b270fa51c2e3af047"
],
"IpAddressType": "ipv4"
}
]
}
作成直後の State.Code は provisioning で、準備が整うと active になります。 省略した部分には、アクセスに使う DNSName と、Route 53 のエイリアスレコードで使う CanonicalHostedZoneId も含まれます。
API リファレンス(CreateLoadBalancer)に書かれている主なオプションの決まりは次のとおりです。
| オプション | 既定値 | 決まり |
|---|---|---|
--name |
(必須) | 32 文字まで。英数字とハイフン。先頭・末尾のハイフンと、先頭の internal- は使えない |
--type |
application |
application / network / gateway |
--scheme |
internet-facing |
外向けは internet-facing、VPC 内向けは internal |
--subnets |
(必須) | ALB は 2 つ以上のアベイラビリティーゾーンから、AZ ごとに 1 つずつ指定する |
--ip-address-type |
ipv4 |
ALB は ipv4 / dualstack / dualstack-without-public-ipv4 |
スクリプトで作成完了を待ちたいときは、ウェイターを挟みます。
aws elbv2 wait load-balancer-available --load-balancer-arns $ALB_ARN
create-target-group の出力
aws elbv2 create-target-group \
--name web-tg --protocol HTTP --port 80 --vpc-id $VPC_ID \
--target-type instance \
--health-check-path /health \
--health-check-interval-seconds 15 --health-check-timeout-seconds 5 \
--healthy-threshold-count 3 --unhealthy-threshold-count 2 \
--matcher HttpCode=200-299
{
"TargetGroups": [
{
"TargetGroupArn": "arn:aws:elasticloadbalancing:ap-northeast-1:123456789012:targetgroup/web-tg/a1354c422c67a6cd",
"TargetGroupName": "web-tg",
"Protocol": "HTTP",
"Port": 80,
"VpcId": "vpc-7b70ce50cc026ce8e",
"HealthCheckProtocol": "HTTP",
"HealthCheckPort": "traffic-port",
"HealthCheckEnabled": true,
"HealthCheckIntervalSeconds": 15,
"HealthCheckTimeoutSeconds": 5,
"HealthyThresholdCount": 3,
"UnhealthyThresholdCount": 2,
"HealthCheckPath": "/health",
"Matcher": {
"HttpCode": "200-299"
},
"TargetType": "instance",
"ProtocolVersion": "HTTP1",
"IpAddressType": "ipv4"
}
]
}
ヘルスチェックのオプションを何も付けずに作った api-tg は、次の値になりました。
aws elbv2 create-target-group --name api-tg --protocol HTTP --port 8080 --vpc-id $VPC_ID \
--query 'TargetGroups[0].{Arn:TargetGroupArn,Interval:HealthCheckIntervalSeconds,Timeout:HealthCheckTimeoutSeconds,Healthy:HealthyThresholdCount,Unhealthy:UnhealthyThresholdCount,Path:HealthCheckPath,Port:HealthCheckPort,Protocol:HealthCheckProtocol,Matcher:Matcher.HttpCode,TargetType:TargetType}'
{
"Arn": "arn:aws:elasticloadbalancing:ap-northeast-1:123456789012:targetgroup/api-tg/d9c7f31344e3e354",
"Interval": 30,
"Timeout": 5,
"Healthy": 5,
"Unhealthy": 2,
"Path": "/",
"Port": "traffic-port",
"Protocol": "HTTP",
"Matcher": "200",
"TargetType": "instance"
}
ヘルスチェックのオプション早見表
ヘルスチェックは「何秒おきに、どのパスへ、何回続けて成功・不成功なら状態を切り替えるか」を決める設定です。 ALB のユーザーガイド(ターゲットグループのヘルスチェック)に載っている既定値と範囲です。ターゲットタイプが instance または ip の場合の値を示します。
| オプション | 意味 | 既定値 | 範囲 |
|---|---|---|---|
--health-check-protocol |
チェックに使うプロトコル | HTTP |
HTTP / HTTPS |
--health-check-port |
チェック先のポート | traffic-port(転送と同じポート) |
1〜65535 |
--health-check-path |
チェック先のパス | / |
有効な URI |
--health-check-interval-seconds |
チェックの間隔 | 30 秒 | 5〜300 秒 |
--health-check-timeout-seconds |
応答を待つ時間 | 5 秒 | 2〜120 秒 |
--healthy-threshold-count |
正常と判定するまでの連続成功回数 | 5 | 2〜10 |
--unhealthy-threshold-count |
異常と判定するまでの連続不成功回数 | 2 | 2〜10 |
--matcher HttpCode=… |
成功とみなす HTTP ステータス | 200 |
200〜499。200-299 のように範囲でも書ける |
既定値のままだと、新しいターゲットが正常と判定されるまでに「30 秒 × 5 回」ほどかかります。切り替えを早めたいときは、間隔としきい値を小さくします。 上のスクリプトでは 15 秒 × 3 回にしています。アプリケーションに /health のような軽い応答を返すパスを用意し、それをチェック先にすると判定が安定します。
register-targets と describe-target-health
register-targets は成功しても何も出力しません。登録できたかは describe-target-health で確認します。ポートを省くとターゲットグループのポートが使われ、Id=…,Port=8080 と書くとターゲットごとに変えられます。
aws elbv2 register-targets --target-group-arn $TG_ARN \
--targets Id=$INSTANCE_1 Id=$INSTANCE_2
aws elbv2 describe-target-health --target-group-arn $TG_ARN \
--query 'TargetHealthDescriptions[].[Target.Id,Target.Port,TargetHealth.State]' \
--output table
ヘルスチェックを通ったあとの表示は次のとおりです。
------------------------------------------
| DescribeTargetHealth |
+----------------------+-----+-----------+
| i-aeaa250e75ee61017 | 80 | healthy |
| i-99063769549952cd2 | 80 | healthy |
+----------------------+-----+-----------+
State に出る値の意味は、ユーザーガイドで次のように説明されています。
| State | 意味 |
|---|---|
initial |
登録の処理中、または最初のヘルスチェックの途中 |
healthy |
ヘルスチェックに通っている |
unhealthy |
ヘルスチェックに応答しない、または通っていない |
unused |
ターゲットグループがどのリスナーからも使われていない、AZ が有効でない、インスタンスが停止している、など |
draining |
登録解除の途中で、処理中の接続が終わるのを待っている |
unavailable |
ターゲットグループのヘルスチェックが無効になっている |
unused のままなら、リスナーやルールからそのターゲットグループがまだ参照されていない可能性があります。リスナーを作ってからもう一度確認します。
create-listener の出力
aws elbv2 create-listener \
--load-balancer-arn $ALB_ARN --protocol HTTP --port 80 \
--default-actions Type=forward,TargetGroupArn=$TG_ARN
{
"Listeners": [
{
"ListenerArn": "arn:aws:elasticloadbalancing:ap-northeast-1:123456789012:listener/app/web-alb/9b51716b97e33a95/5f4e8e254e1df153",
"LoadBalancerArn": "arn:aws:elasticloadbalancing:ap-northeast-1:123456789012:loadbalancer/app/web-alb/9b51716b97e33a95",
"Port": 80,
"Protocol": "HTTP",
…(省略)…
"DefaultActions": [
{
"Type": "forward",
"TargetGroupArn": "arn:aws:elasticloadbalancing:ap-northeast-1:123456789012:targetgroup/web-tg/a1354c422c67a6cd"
}
]
}
]
}
--default-actions が、どのルールにも合わなかったリクエストの行き先です。リスナーを作ると、このデフォルトアクションを持つ「デフォルトルール」が 1 つ自動でできます。
HTTPS で待ち受けるリスナーは、AWS CLI リファレンス(create-listener)の例にあるとおり、証明書の ARN とセキュリティポリシーを加えます。
aws elbv2 create-listener \
--load-balancer-arn $ALB_ARN \
--protocol HTTPS --port 443 \
--certificates CertificateArn=arn:aws:acm:ap-northeast-1:123456789012:certificate/3dcb0a41-bd72-4774-9ad9-756919c40557 \
--ssl-policy ELBSecurityPolicy-2016-08 \
--default-actions Type=forward,TargetGroupArn=$TG_ARN
--certificates には証明書を 1 つだけ指定します。
create-rule で条件とアクションを書く
ルールは「条件(Conditions)に合ったら、アクション(Actions)を行う」という 1 行です。 優先度(--priority)は 1〜50000 の数字で、小さい順に評価され、最初に合ったルールのアクションが行われます。どれにも合わなければデフォルトルールが使われます。
短い書き方(パス条件で転送)
aws elbv2 create-rule \
--listener-arn $LISTENER_ARN --priority 10 \
--conditions Field=path-pattern,Values='/api/*' \
--actions Type=forward,TargetGroupArn=$API_TG_ARN
{
"Rules": [
{
"RuleArn": "arn:aws:elasticloadbalancing:ap-northeast-1:123456789012:listener-rule/app/web-alb/9b51716b97e33a95/5f4e8e254e1df153/8d724ff699559cce",
"Priority": "10",
"Conditions": [
{
"Field": "path-pattern",
"Values": [
"/api/*"
]
}
],
"Actions": [
{
"Type": "forward",
"TargetGroupArn": "arn:aws:elasticloadbalancing:ap-northeast-1:123456789012:targetgroup/api-tg/d9c7f31344e3e354"
}
],
"IsDefault": false
}
]
}
Values の * をシェルに展開させないよう、値は引用符で囲みます。
リダイレクトのルール(JSON ファイル)
アクションが複雑になったら JSON ファイルに書き、file:// で渡します。old.example.com へのアクセスを https://www.example.com の同じパスへ 301 で移す例です(rule-redirect.json)。
[
{
"Type": "redirect",
"RedirectConfig": {
"Protocol": "HTTPS",
"Port": "443",
"Host": "www.example.com",
"Path": "/#{path}",
"Query": "#{query}",
"StatusCode": "HTTP_301"
}
}
]
aws elbv2 create-rule \
--listener-arn $LISTENER_ARN --priority 20 \
--conditions Field=host-header,Values='old.example.com' \
--actions file://rule-redirect.json
{
"Rules": [
{
"RuleArn": "arn:aws:elasticloadbalancing:ap-northeast-1:123456789012:listener-rule/app/web-alb/b697ed833a1f4371/69d2e7a15c787a23/2353be5818b7155b",
"Priority": "20",
"Conditions": [
{
"Field": "host-header",
"Values": [
"old.example.com"
]
}
],
"Actions": [
{
"Type": "redirect",
"RedirectConfig": {
"Protocol": "HTTPS",
"Port": "443",
"Host": "www.example.com",
"Path": "/#{path}",
"Query": "#{query}",
"StatusCode": "HTTP_301"
}
}
],
"IsDefault": false
}
]
}
#{path} や #{query} は、元のリクエストの値をそのまま引き継ぐための書き方です。ほかに #{protocol} #{host} #{port} があります。StatusCode は HTTP_301(恒久的)か HTTP_302(一時的)です。
固定レスポンスのルール
ターゲットに転送せず、ALB 自身が決まった応答を返します。メンテナンス中の案内などに使えます(rule-fixed.json)。
[
{
"Type": "fixed-response",
"FixedResponseConfig": {
"StatusCode": "503",
"ContentType": "text/plain",
"MessageBody": "Maintenance"
}
}
]
aws elbv2 create-rule \
--listener-arn $LISTENER_ARN --priority 30 \
--conditions Field=path-pattern,Values='/maintenance*' \
--actions file://rule-fixed.json --query 'Rules[0].Actions'
[
{
"Type": "fixed-response",
"FixedResponseConfig": {
"MessageBody": "Maintenance",
"StatusCode": "503",
"ContentType": "text/plain"
}
}
]
複数の条件を組み合わせる
1 つのルールには条件を複数並べられます。API リファレンス(CreateRule)では「ルールの条件が満たされたときに、そのアクションが行われる」と説明されています。また、1 つの条件の中に値を複数書いた場合は、どれか 1 つに合えばその条件は満たされます(ユーザーガイドの条件タイプの説明より)。ホスト・パス・HTTP メソッドを組み合わせた例です(cond-multi.json)。
[
{ "Field": "host-header", "HostHeaderConfig": { "Values": ["admin.example.com"] } },
{ "Field": "path-pattern", "PathPatternConfig": { "Values": ["/reports/*", "/export/*"] } },
{ "Field": "http-request-method", "HttpRequestMethodConfig": { "Values": ["GET", "HEAD"] } }
]
aws elbv2 create-rule \
--listener-arn $LISTENER_ARN --priority 40 \
--conditions file://cond-multi.json \
--actions Type=forward,TargetGroupArn=$API_TG_ARN \
--query 'Rules[0].[Priority,length(Conditions)]' --output text
40 3
HTTP ヘッダー・クエリ文字列・送信元 IP の条件も同じ形で書けます(cond-extra.json)。
[
{ "Field": "http-header", "HttpHeaderConfig": { "HttpHeaderName": "X-Client", "Values": ["mobile*"] } },
{ "Field": "query-string", "QueryStringConfig": { "Values": [ { "Key": "version", "Value": "v2" } ] } },
{ "Field": "source-ip", "SourceIpConfig": { "Values": ["203.0.113.0/24"] } }
]
aws elbv2 create-rule \
--listener-arn $LISTENER_ARN --priority 50 \
--conditions file://cond-extra.json \
--actions Type=forward,TargetGroupArn=$API_TG_ARN \
--query 'Rules[0].Conditions[].Field'
[
"http-header",
"query-string",
"source-ip"
]
重みをつけて 2 つのターゲットグループへ転送する
ForwardConfig を使うと、リクエストを割合で分けられます。新しい版を少しずつ試すときに使えます(fwd-weighted.json。ARN は自分のものに置き換えます)。
[
{
"Type": "forward",
"ForwardConfig": {
"TargetGroups": [
{ "TargetGroupArn": "arn:aws:elasticloadbalancing:ap-northeast-1:123456789012:targetgroup/web-tg/21804fae0e99e108", "Weight": 90 },
{ "TargetGroupArn": "arn:aws:elasticloadbalancing:ap-northeast-1:123456789012:targetgroup/api-tg/881bde866f9d157d", "Weight": 10 }
]
}
}
]
aws elbv2 create-rule \
--listener-arn $LISTENER_ARN --priority 60 \
--conditions Field=path-pattern,Values='/beta/*' \
--actions file://fwd-weighted.json \
--query 'Rules[0].Actions[0].ForwardConfig.TargetGroups[].Weight'
[
90,
10
]
Weight は 0〜999 の範囲で指定します。
条件とアクションの早見表
ALB のユーザーガイド(ルールの条件タイプ、アクションタイプ)の記載をまとめます。
条件の Field |
何を見るか | 大文字・小文字 | ワイルドカード |
|---|---|---|---|
path-pattern |
URL のパス(クエリ文字列は含まない) | 区別する | *(0 文字以上)と ?(1 文字) |
host-header |
Host ヘッダー | 区別しない | * と ? |
http-header |
任意の HTTP ヘッダー | 名前・値とも区別しない | 値にだけ使える |
http-request-method |
HTTP メソッド | 区別する | 使えない(完全一致) |
query-string |
クエリ文字列のキーと値 | 区別しない | * と ? |
source-ip |
送信元 IP アドレス | ― | 使えない(CIDR 形式で書く) |
| 上限 | 値 |
|---|---|
| 1 つのルールに書ける条件 | 5 つまで |
| 1 つの条件に書ける値 | 3 つまで |
| 1 つのルールで使えるワイルドカード | 5 個まで |
同じ Field を複数書けるもの |
http-header と query-string |
アクションの Type |
動作 | 設定を書く場所 |
|---|---|---|
forward |
ターゲットグループへ転送する | TargetGroupArn または ForwardConfig |
redirect |
別の URL へリダイレクトする | RedirectConfig |
fixed-response |
決まった応答を返す(ステータスは 2XX・4XX・5XX) | FixedResponseConfig |
authenticate-oidc |
OIDC 準拠の ID プロバイダーで認証する(HTTPS リスナー) | ― |
authenticate-cognito |
Amazon Cognito で認証する(HTTPS リスナー) | ― |
ルールを一覧・変更する
ここまでに作ったルールを優先度順に一覧します。
aws elbv2 describe-rules --listener-arn $LISTENER_ARN \
--query 'Rules[].[Priority,Conditions[0].Field,Actions[0].Type,IsDefault]' --output table
--------------------------------------------------------
| DescribeRules |
+---------+----------------+------------------+--------+
| 10 | path-pattern | forward | False |
| 20 | host-header | redirect | False |
| 30 | path-pattern | fixed-response | False |
| 40 | host-header | forward | False |
| 50 | http-header | forward | False |
| 60 | path-pattern | forward | False |
| default| None | forward | True |
+---------+----------------+------------------+--------+
優先度の変更は set-rule-priorities、条件やアクションの変更は modify-rule です。
RULE_ARN=$(aws elbv2 describe-rules --listener-arn $LISTENER_ARN \
--query "Rules[?Priority=='10'].RuleArn" --output text)
aws elbv2 set-rule-priorities --rule-priorities RuleArn=$RULE_ARN,Priority=5 \
--query 'Rules[].Priority' --output text
aws elbv2 modify-rule --rule-arn $RULE_ARN \
--conditions Field=path-pattern,Values='/api/v1/*' \
--query 'Rules[0].Conditions[0].Values'
5
[
"/api/v1/*"
]
Priority は文字列で返るので、--query の比較は '10' と引用符つきで書きます。
ヘルスチェックの設定は modify-target-group であとから変えられます。
aws elbv2 modify-target-group --target-group-arn $TG_ARN \
--health-check-path /healthz --health-check-interval-seconds 10 \
--query 'TargetGroups[0].[HealthCheckPath,HealthCheckIntervalSeconds]' --output text
/healthz 10
作成時に出やすいエラーと直し方
エラー文のかっこ内(エラーコード)を見ると、どの部品の指定が合っていないかがわかります。 今回の確認環境で実際に出たものを並べます。
| 操作 | エラー文 | 直し方 |
|---|---|---|
使用中の優先度で create-rule |
(PriorityInUse) … The specified priority is in use. |
空いている番号にする。または set-rule-priorities で既存をずらす |
| 同じ名前で設定の違うターゲットグループを作成 | (DuplicateTargetGroupName) … A target group with the specified name already exists. |
名前を変える。既存を使うなら describe-target-groups --names で ARN を取る |
| タイムアウトを間隔以上にした | (ValidationError) … Health check timeout '10' must be smaller than the interval '5' |
タイムアウトを間隔より短くする |
| しきい値を 1 にした | Parameter validation failed: Invalid value for parameter HealthyThresholdCount, value: 1, valid min value: 2 |
2〜10 の範囲にする |
| 間隔を 3 秒にした | Parameter validation failed: Invalid value for parameter HealthCheckIntervalSeconds, value: 3, valid min value: 5 |
5〜300 の範囲にする |
| 名前にアンダースコアを使った | (ValidationError) … Target group name 'bad_tg' can only contain characters that are alphanumeric characters or hyphens(-) |
英数字とハイフンだけにする |
条件の Field を path と書いた |
(ValidationError) … Condition field 'path' must be one of '[path-pattern,host-header,http-header,http-request-method,query-string,source-ip]' |
path-pattern と書く |
--priority を付け忘れた |
aws: error: the following arguments are required: --priority |
優先度を指定する |
無い名前で describe-load-balancers |
(LoadBalancerNotFound) … The specified load balancer does not exist. |
名前とリージョンを確認する |
| ターゲットグループの ARN が違う | (TargetGroupNotFound) … Target group '…' not found |
変数の中身を echo で確認する |
| リスナーの ARN が違う | (ListenerNotFound) … The specified listener does not exist. |
describe-listeners で取り直す |
「Parameter validation failed」で始まるものは、AWS へ送る前に CLI が範囲を確かめて止めたものです。API リファレンスには、このほかに DuplicateLoadBalancerName(同じ名前のロードバランサーがある)、SubnetNotFound、InvalidSecurityGroup、TooManyRules(ルール数の上限)などが挙げられています。
削除の順番と ResourceInUse
ターゲットグループは、リスナーやルールから参照されている間は削除できません。 作った直後の状態で delete-target-group を実行すると、次のエラーで止まります。
aws elbv2 delete-target-group --target-group-arn $TG_ARN
An error occurred (ResourceInUse) when calling the DeleteTargetGroup operation: The target group 'arn:aws:elasticloadbalancing:ap-northeast-1:123456789012:targetgroup/web-tg/21804fae0e99e108' is currently in use by a listener or a rule
ルールからだけ参照されている api-tg も同じです。
An error occurred (ResourceInUse) when calling the DeleteTargetGroup operation: The target group 'arn:aws:elasticloadbalancing:ap-northeast-1:123456789012:targetgroup/api-tg/881bde866f9d157d' is currently in use by a listener or a rule
参照している側(ルール・リスナー)を先に消し、参照されている側(ターゲットグループ)を最後に消すのが正しい順番です。
| 順 | 削除するもの | コマンド | 理由 |
|---|---|---|---|
| 1 | ルール | aws elbv2 delete-rule --rule-arn ARN |
ターゲットグループを参照している。デフォルトルールは対象外 |
| 2 | リスナー | aws elbv2 delete-listener --listener-arn ARN |
デフォルトアクションがターゲットグループを参照している |
| 3 | ロードバランサー | aws elbv2 delete-load-balancer --load-balancer-arn ARN |
リスナーが無くなった本体を消す |
| 4 | ターゲットグループ | aws elbv2 delete-target-group --target-group-arn ARN |
どこからも参照されなくなってから消す |
ALB のユーザーガイドによると、ターゲットグループを削除しても、登録されていた EC2 インスタンスには影響しません。インスタンスが不要なら別に停止・終了します。
一式を削除するスクリプト
create-alb.sh で作ったものを、上の順番で削除するスクリプトです。
#!/bin/bash
# create-alb.sh で作った一式を、依存の少ない順に削除する
set -euo pipefail
ALB_ARN=$(aws elbv2 describe-load-balancers --names web-alb \
--query 'LoadBalancers[0].LoadBalancerArn' --output text)
# 1. ルール → 2. リスナー
for LISTENER_ARN in $(aws elbv2 describe-listeners --load-balancer-arn "$ALB_ARN" \
--query 'Listeners[].ListenerArn' --output text); do
for RULE_ARN in $(aws elbv2 describe-rules --listener-arn "$LISTENER_ARN" \
--query 'Rules[?!IsDefault].RuleArn' --output text); do
aws elbv2 delete-rule --rule-arn "$RULE_ARN"
echo "deleted rule: ${RULE_ARN##*/}"
done
aws elbv2 delete-listener --listener-arn "$LISTENER_ARN"
echo "deleted listener: ${LISTENER_ARN##*/}"
done
# 3. ロードバランサー(削除完了まで待つ)
aws elbv2 delete-load-balancer --load-balancer-arn "$ALB_ARN"
aws elbv2 wait load-balancers-deleted --load-balancer-arns "$ALB_ARN"
echo "deleted load balancer: web-alb"
# 4. ターゲットグループ
for NAME in web-tg api-tg; do
TG_ARN=$(aws elbv2 describe-target-groups --names "$NAME" \
--query 'TargetGroups[0].TargetGroupArn' --output text)
aws elbv2 delete-target-group --target-group-arn "$TG_ARN"
echo "deleted target group: $NAME"
done
bash delete-alb.sh
deleted rule: 45569358fab49318
deleted rule: 2353be5818b7155b
deleted rule: a7268d6f871914c0
deleted rule: 44e2a1159e9d33ce
deleted rule: 5402f6acceb19978
deleted rule: de55bb87524f71f7
deleted listener: 69d2e7a15c787a23
deleted load balancer: web-alb
deleted target group: web-tg
deleted target group: api-tg
Rules[?!IsDefault] でデフォルトルール以外だけを選んでいます。デフォルトルールはリスナーと一緒に消えます。最後にロードバランサーが残っていないことを確認します。
aws elbv2 describe-load-balancers --query 'LoadBalancers[].LoadBalancerName'
[]
ターゲットだけを外す
ALB は残したまま、特定のインスタンスだけを振り分け先から外すときは deregister-targets を使います。
aws elbv2 deregister-targets --target-group-arn $TG_ARN --targets Id=$INSTANCE_2
aws elbv2 describe-target-health --target-group-arn $TG_ARN \
--query 'TargetHealthDescriptions[].[Target.Id,TargetHealth.State]' --output text
i-aeaa250e75ee61017 healthy
登録解除の待ち時間は、ターゲットグループの属性 deregistration_delay.timeout_seconds で決まります。確認すると 300 秒でした。
aws elbv2 describe-target-group-attributes --target-group-arn $TG_ARN \
--query "Attributes[?Key=='deregistration_delay.timeout_seconds']"
[
{
"Key": "deregistration_delay.timeout_seconds",
"Value": "300"
}
]
よくある質問
Q. ターゲットグループとロードバランサーは、どちらを先に作ればよいですか? A. どちらが先でも作れます。2 つを結びつけるのはリスナー(とルール)なので、リスナーを作る時点で両方の ARN がそろっていれば大丈夫です。この記事では、エラーが出たときに原因を追いやすいよう、入口から順に作っています。
Q. describe-target-health が unused のままです。
A. そのターゲットグループが、まだどのリスナーやルールからも参照されていないときに出る状態です。create-listener か create-rule で転送先に指定してから、もう一度確認します。
Q. ルールの優先度はどう決めればよいですか? A. 数字が小さいほど先に評価されます。あとから間に差し込めるよう、10・20・30 のように間隔をあけて振ると扱いやすくなります。条件が狭いルール(特定のホストとパスの組み合わせなど)を小さい数字にし、広い条件を大きい数字にするのが基本です。
Q. HTTP を HTTPS に移すルールはどう書きますか?
A. HTTP:80 のリスナーのデフォルトアクションを redirect にします。RedirectConfig の Protocol を HTTPS、Port を 443、StatusCode を HTTP_301 にし、Host・Path・Query は #{host}・/#{path}・#{query} で元の値を引き継ぎます。
まとめ
- 作る順番は「ロードバランサー → ターゲットグループ → ターゲット登録 → リスナー → ルール」
- 前の出力の ARN を
--query '…Arn' --output textで変数に受け取ると、通しで実行できる - ヘルスチェックは既定で 30 秒間隔・5 回成功で正常。切り替えを早めるなら間隔としきい値を小さくする
- ルールは優先度の小さい順に評価され、条件は 1 ルール 5 つまで。1 つの条件に書いた複数の値は、どれか 1 つに合えばよい
- アクションは forward・redirect・fixed-response が基本で、複雑なものは JSON ファイルで渡す
ResourceInUseはターゲットグループがまだ参照されている合図。ルール → リスナー → ロードバランサー → ターゲットグループの順に消すPriorityInUseやDuplicateTargetGroupNameは名前・番号の重なり。エラーコードを見て対象を直す
参考・出典
- Elastic Load Balancing API リファレンス:CreateLoadBalancer、CreateTargetGroup、CreateRule
- Application Load Balancer ユーザーガイド:ターゲットグループのヘルスチェック、ルールの条件タイプ、ルールのアクションタイプ、ターゲットグループの削除
- AWS CLI コマンドリファレンス:elbv2 create-listener
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「ALBをAWS CLIで作成|ターゲットグループ・リスナー・ルール設定」
株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。
WE ARE HIRING
RJCで一緒に開発しながら、
成長を楽しみませんか?
RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!
- 127日年間休日
- 12時間平均残業時間
- 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!
ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。