目次
13 章

ALB / NLB と ACM (HTTPS)

AWS のマネージドロードバランサー ALB / NLB / GWLB の役割の違い、Listener / Target Group / Health Check の流れ、そして ACM で証明書を発行して HTTPS を一気に付ける運用の流れまで整理します。

第12章 Route 53 のドメインが指す先には、ほぼ常にロードバランサーがあります。AWS のマネージドロードバランサーを総称して ELB (Elastic Load Balancing) と呼び、その中に ALB / NLB / GWLB の3種類があります。

本章では3つの LB の違いから始め、ALB の Listener / Target Group / Health Check の流れ、そして ACM で証明書を受け取って HTTPS を付ける過程まで一本に整理します。ここで扱う SG パターンは 第9章 EC2 運用 の延長であり、ALB を Origin として置くパターンと ACM のリージョンルールは 第14章 CloudFront へつながり、Target Group の ip タイプは 第15章 ECS と Fargate で自動登録として再び現れます。

ロードバランサーが解く問題 #

EC2 1台の後ろにドメインを直接挿すと、次が崩れます。

問題LB が解く機能
EC2 が死ぬとサイトがダウンHealth check で死んだインスタンスを外し、生きている側へ
トラフィックが増えて1台では足りない複数のインスタンスに負荷分散
AZ 障害時に全面ダウンMulti-AZ 分散
HTTPS 証明書をインスタンスごとに管理LB で一度終端 (TLS termination)
カナリア / Blue-Green デプロイListener Rule で比率分散

運用ではほぼ常に Internet → ALB / NLB → EC2 / ECS / Lambda パターンです。

ALB / NLB / GWLB — 3つの比較 #

ALB (Application LB)NLB (Network LB)GWLB (Gateway LB)
OSI レイヤーL7 (HTTP / HTTPS)L4 (TCP / UDP / TLS)L3/L4 (IP)
ルーティング方式path / host / header / メソッドport のみパケットそのまま
処理量良い非常に速い (数百万 RPS)適した場合に速い
WebSocketサポートサポート-
HTTP/2サポートサポート (TLS)-
固定 IPなし (DNS)あり (AZ ごとに EIP)-
WAF 連携サポート不可-
Cognito 認証サポート不可-
Lambda targetサポート不可-
用途Web / APIゲーム / IoT / TCP / gRPCセキュリティアプライアンス (Firewall)

決定ガイド #

LB 決定木
HTTP(S) ?
├── YES → ALB
│   └── 非常に高い RPS (数十万+)? → ALB → 限界時に NLB
└── NO →
    TCP/UDP ?
    ├── YES → NLB
    └── 外部セキュリティアプライアンスを通す → GWLB

一般的な Web ワークロードはほぼ ALB です。NLB はゲーム / IoT / 非常に高い処理量 / 固定 IP が必要な場合に使います。

ALB の構造 #

ALB の構造
                    Route 53
                   ┌────────┐
                   │  ALB   │
                   │        │
                   └─┬──┬───┘
                     │  │
                Listener (port 443)
                     │  │
                     ▼  ▼
                Listener Rules
                  (path / host)
                     ├── /api/*  ────▶ Target Group A (api EC2 たち)
                     ├── /admin/* ────▶ Target Group B (admin)
                     └── 基本 /     ────▶ Target Group C (web)
                                          ├── EC2 #1 (AZ a)
                                          ├── EC2 #2 (AZ b)
                                          └── EC2 #3 (AZ a)

核心となる構成要素は次のとおりです。

Listener — 受けるポート #

ALB がどのポートでトラフィックを受けるかを決めます。通常は 80(HTTP)、443(HTTPS)です。

ALB + Listener を作る
aws elbv2 create-load-balancer \
  --name my-alb \
  --subnets subnet-pubA subnet-pubB \
  --security-groups sg-alb \
  --scheme internet-facing \
  --type application

aws elbv2 create-listener \
  --load-balancer-arn <alb-arn> \
  --protocol HTTPS \
  --port 443 \
  --certificates CertificateArn=<acm-arn> \
  --default-actions Type=forward,TargetGroupArn=<tg-arn>

Target Group — 送る対象 #

Listener がトラフィックを送るインスタンス / IP / Lambda の束です。ポートとプロトコルを持つグループです。

Target Group を作る
aws elbv2 create-target-group \
  --name my-app-tg \
  --protocol HTTP \
  --port 8080 \
  --vpc-id vpc-... \
  --target-type instance \
  --health-check-protocol HTTP \
  --health-check-path /health \
  --health-check-interval-seconds 30 \
  --healthy-threshold-count 2 \
  --unhealthy-threshold-count 3

target-type の意味は次のとおりです。

タイプ役割
instanceEC2 インスタンス ID。SG 指定に滑らか
ip任意の IP (VPC 内)。ECS / Fargate の自動登録
lambdaLambda 関数。ALB → Lambda パターン

Listener Rule — ルーティングルール #

同じ Listener の中で path / host / header で別の Target Group へ送ります。

Listener Rules の形
Priority  Condition                      Action
10        host = api.example.com         forward → tg-api
20        path = /admin/*                forward → tg-admin
30        path = /static/*               redirect → cloudfront.example.com
default   *                              forward → tg-web

ルールは priority 順(小さいものが先)で評価され、マッチすると止まります。

Listener Rule のアクションは次のとおりです。

  • forward — Target Group へ送ります(重みで複数の場所に分散も可能)。
  • redirect — 別の URL へ送ります(HTTP → HTTPS 永久リダイレクトの定石)。
  • fixed-response — 固定応答を返します(メンテナンスページ)。
  • authenticate-cognito / -oidc — ユーザー認証の後に通過させます。
HTTP → HTTPS リダイレクトの定石
Listener (port 80)
  default action: redirect → HTTPS://#{host}#{path}#{query} (301)

Listener (port 443)
  default action: forward → tg-web

このパターンが運用の標準です。すべての 80 トラフィックを 443 へ永久に送ります。

Health Check — 生きている対象だけ #

Target Group の Health Check が死んだインスタンスを自動で外し、生き返ると再び入れてくれます。

Health Check の流れ
ALB ─ HTTP GET /health ──▶ EC2:8080
                       応答 200 ──▶ healthy (3回連続)
                       応答 5xx ──▶ unhealthy (3回連続) → ルーティングから除外

よく使うオプションは次のとおりです。

オプション役割
HealthCheckPath/health/healthz のような軽い経路
HealthCheckProtocolHTTP / HTTPS
HealthCheckIntervalSeconds30 (通常)
HealthyThresholdCount2~3 回連続 200 → healthy
UnhealthyThresholdCount2~3 回連続失敗 → unhealthy
Matcher.HttpCode200 または 200-299

Health Check 経路の設計 #

良い /health 応答は軽いです。

軽い health endpoint の例 (FastAPI)
@app.get("/health")
def health():
    return {"status": "ok"}

DB チェックまで行う deep health は別の経路に置きます。

deep health
@app.get("/health/deep")
def deep_health(db: Session = Depends(get_db)):
    db.execute("SELECT 1")
    return {"status": "ok", "db": "ok"}

/health は常に軽く、/health/deep はモニタリングやデバッグでだけ使います。ALB が deep health をポーリングすると DB の負担が大きいです。

Sticky Session — 同じ対象へ #

特定のユーザーのリクエストを常に同じインスタンスへ送るオプションです。

Stickiness を ON にする
aws elbv2 modify-target-group-attributes \
  --target-group-arn <tg-arn> \
  --attributes \
    Key=stickiness.enabled,Value=true \
    Key=stickiness.type,Value=lb_cookie \
    Key=stickiness.lb_cookie.duration_seconds,Value=86400

使う場合は、セッションをメモリに置く昔のアプリ(ほぼ作るべきではないが、マイグレーション中の一時的なもの)や WebSocket のような長寿命の接続です。

運用ではセッションを外部(Redis / DB)へ出して stateless に置くのが定石です。Stickiness は例外的な場合にだけ使います。

NLB の用途 #

ALB が解けない仕事に NLB を使います。

NLB の強み #

  • 固定 IP (AZ ごとに EIP) — ファイアウォールのホワイトリストに有用です。
  • 数百万 RPS の処理。
  • TLS termination も可能 — NLB が TLS を終端し、平文で backend へ送ります。
  • PrivateLink の役割 — サービスを別の VPC に公開します。

NLB の弱み #

  • L4 のみ — path / host / header のルーティングができません。
  • WAF 連携が直接できません。
  • 単一の Listener が1つの Target Group です。
NLB + TLS Listener
aws elbv2 create-load-balancer \
  --name my-nlb --type network \
  --subnets subnet-pubA subnet-pubB

aws elbv2 create-listener \
  --load-balancer-arn <nlb-arn> \
  --protocol TLS --port 443 \
  --certificates CertificateArn=<acm-arn> \
  --default-actions Type=forward,TargetGroupArn=<tg-arn>

ACM — 証明書発行 #

ACM (AWS Certificate Manager) は AWS 内の ALB / NLB / CloudFront / API Gateway で使う公開 SSL 証明書を無料で発行し、自動更新します。

証明書のリクエスト #

ACM 証明書をリクエスト
aws acm request-certificate \
  --domain-name example.com \
  --subject-alternative-names "*.example.com" "api.example.com" \
  --validation-method DNS \
  --region ap-northeast-2

検証方式は2つです。

  • DNS 検証 (推奨) — Route 53 の CNAME で自動検証し、自動更新されます。
  • Email 検証 (旧方式) — admin@example.com などへメールを送信し、毎年手動です。

ほぼ常に DNS 検証を使います。Route 53 を一緒に使うと、コンソールが「Create record in Route 53」ボタンで自動処理します。

証明書のリージョン一致ルール #

ACM 証明書はリージョン単位です。ALB がソウルにあれば証明書もソウルで発行します。ただし CloudFront は常に us-east-1 です(第14章)。

リージョンのマッピング
ALB (ソウル)         → ACM 証明書 (ap-northeast-2)
NLB (東京)         → ACM 証明書 (ap-northeast-1)
CloudFront         → ACM 証明書 (us-east-1) ← 常に
API Gateway (REST) → ACM 証明書 (該当リージョン)
API Gateway (Edge) → ACM 証明書 (us-east-1)

自動更新 #

ACM 証明書はデフォルト13か月有効で、満了60日前から自動更新されます。

  • DNS 検証で作った証明書は完全に自動です。
  • Email 検証は手動なので DNS を推奨します。

自動更新が失敗する場合は、DNS 検証の CNAME が消えるか、ALB が証明書を使用中だがドメインが別の場所へ移動して検証が失敗する場合です。ACM コンソールで満了通知が自動で出て、CloudWatch アラームもかけられます。

HTTPS を付ける一行の手順 #

ドメインがあり ALB があると仮定します。

HTTPS を付ける手順
1. ACM で証明書をリクエスト (DNS 検証)
2. Route 53 に検証 CNAME を追加 (コンソールで1回クリック)
3. 証明書 ISSUED を待つ (数分)
4. ALB Listener 443 に証明書を attach
5. Listener 80 → HTTPS redirect
6. Route 53 のドメイン → ALB Alias

この6段階が運用の標準パターンです。証明書を毎年更新する必要もありません。

Security Policy — TLS バージョン #

Listener の Security Policy が、許可する TLS バージョンと暗号スイートを定義します。

よく使うポリシー
ELBSecurityPolicy-TLS13-1-2-2021-06   ← 推奨 (TLS 1.3, 1.2)
ELBSecurityPolicy-TLS-1-2-2017-01     ← 互換性が良い
ELBSecurityPolicy-FS-2018-06          ← Forward Secrecy 強制

古いクライアント(TLS 1.0、1.1)を切りたいなら TLS13-1-2-2021-06 を使います。毎年新しいポリシーが出るので定期的に点検します。

Connection Draining — 優雅な終了 #

インスタンスを手動で外したり ASG が減らしたりするときに、進行中のリクエストが切れないように待つ役割です。

Connection Draining
ALB ─ 新しいリクエストは送らない ─▶ EC2  (deregistration_delay = 300s)
        進行中のリクエストは最後まで処理

デフォルト300秒です。通常は30 ~ 60秒に減らしても十分です。短すぎると進行中のリクエストが切れ、長すぎるとデプロイが遅くなります。

LB の SG と EC2 の SG #

第9章 EC2 運用 で見た SG パターンです。

ALB ↔ EC2 の SG
ALB SG (sg-alb)
  Inbound:  443 ← 0.0.0.0/0
  Outbound: all

EC2 SG (sg-app)
  Inbound:  8080 ← sg-alb           ← ALB SG 自体
  Outbound: all

NLB は異なります。NLB 自体は SG がない(旧 NLB)か、1つの SG だけを持ちます(新オプション)。そのため EC2 SG が NLB の IP ではなくクライアント IP をそのまま見ることになります。運用では NLB のクライアント IP を狭めるために NACL や VPC レベルの制御を追加することもあります。

よく出会う落とし穴 #

  • ACM 証明書が ISSUED にならない — ほぼ99%が検証 CNAME が Route 53 に入っていないか、誤った zone に入ったか(example.com ではなく api.example.com の zone)、TTL が長すぎて伝播していない場合です。5分ほど待ってみます。
  • CloudFront 証明書をソウルで発行 — CloudFront は us-east-1 だけを使います。コンソールで受け取るときに右上を N. Virginia に変えます。
  • HTTP 80 Listener を作らず HTTPS だけ — ユーザーが http://example.com で入ってくると timeout します。80 Listener の redirect to HTTPS が標準です。
  • Health check path が // が重い作業(DB 呼び出しなど)だと、ALB health check が DB を30秒ごとに爆撃します。/health のような軽い経路を別途置きます。
  • Target Group のポート vs Listener のポートの混同 — ALB Listener は 443 なのに Target Group の EC2 は 8080 のことがあります。2つのポートは別物です。Target Group のポートが EC2 が listen 中のポートです。
  • 502 Bad Gateway — ALB → EC2 の応答が壊れるときです。よくある原因は、EC2 の keep-alive timeout が ALB idle timeout(60s デフォルト)より短いか、EC2 が応答する前に切れるか、EC2 SG が ALB SG を inbound に受けていないか、EC2 が 8080 で listen していないことです。
  • Sticky session で負荷の偏り — 特定のインスタンスにだけリクエストが溜まって1台だけ CPU 100% になります。Stickiness を OFF にして stateless に置きます。
  • Cross-Zone を OFF にする — 旧 ALB の cross-zone オプションが OFF だと AZ 単位の均等分配になり、片方の AZ のインスタンスが少ないのにトラフィックは同じ量なので負荷が偏ります。Cross-zone load balancing を ON にします(ALB はデフォルト ON、NLB は費用のためデフォルト OFF)。

練習問題 #

  1. §「HTTPS を付ける一行の手順」の6段階を見ずに書いてみてください。そのうち 第12章 Route 53 の作業(検証 CNAME 追加、ドメイン Alias)はどの段階かを表示し、ACM 作業と ALB 作業を区別してみてください。
  2. ALB と NLB の比較表を見て、次の3つのワークロードにそれぞれ何を選ぶべきかを §「決定ガイド」を根拠に答えてください。(a) 一般的な REST API、(b) ファイアウォールのホワイトリストのために固定 IP が必要な TCP ゲームサーバー、(c) WAF を付けなければならない Web サイト。
  3. CloudFront 用の証明書をソウルで発行して ISSUED にならない状況を仮定し、§「証明書のリージョン一致ルール」を根拠に原因と解決を書いてみてください。このルールは 第14章 CloudFront で再び確認することになります。

一行まとめ: ELB は ALB / NLB / GWLB に分かれ、一般的な Web はほぼ ALB。ALB の流れは Listener(受けるポート) → Listener Rule(path/host) → Target Group(送る対象) → Health Check で、HTTP 80 の default action を HTTPS redirect に置くのが標準。ACM は無料の SSL 証明書を DNS 検証で自動更新し、ALB は同じリージョンだが CloudFront は常に us-east-1。

次の章 #

ALB までの役割はつかめました。次の 第14章 CloudFront では、最後にユーザーに近くキャッシュを置く CloudFront へつながります。Origin / Behavior / Cache Policy の流れ、S3 + CloudFront 静的ホスティングパターン、OAC で S3 を安全に隠す方法、そして無効化(invalidation)まで整理します。

X