AWS中級 #6 ALB / NLB と ACM (HTTPS)

読了 8分

#5 Route 53 のドメインが指す場 — そこにはほぼ常に ロードバランサー があります。AWS のマネージドロードバランサーをまとめて ELB (Elastic Load Balancing) と呼び、その中に ALB / NLB / GWLB の 3 種類があります。

この記事では 3 つの LB の違い → ALB の Listener / Target Group / Health Check の流れ → ACM で証明書を取得して HTTPS を貼る場を 1 本の線で通していきます。

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

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

99% の一般的な 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)
                     └── default /     ────▶ Target Group C (web)
                                          ├── EC2 #1 (AZ a)
                                          ├── EC2 #2 (AZ b)
                                          └── EC2 #3 (AZ a)

中心となる 3 つの要素:

1) 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>

2) 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 パターン

3) 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 有効化
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 のような長寿命接続 — 自動 stickiness

運用では セッションを外部 (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 が単一 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

検証方式:

  • DNS 検証 (推奨) — Route 53 の CNAME で自動検証、自動更新
  • Email 検証 (旧式) — admin@example.com 等にメール送信、毎年手動

ほぼ常に DNS 検証。Route 53 と一緒に使えばコンソールが「Create record in Route 53」ボタンで自動。

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

ACM 証明書はリージョン単位。ALB がソウルなら証明書もソウルで発行。ただし CloudFront は常に us-east-1 (#7)。

リージョンマッピング
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 リダイレクト
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 #

#2 で見た 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 つだけ (新オプション)。なので EC2 SG は NLB の IP ではなく クライアント IP をそのまま見ます。運用では NLB クライアント IP を絞るために NACL や VPC レベルの場を追加することも。

よくハマる罠 #

1) ACM 証明書が ISSUED にならない #

原因はほぼ 99%:

  • 検証 CNAME が Route 53 に入っていない
  • CNAME が誤った zone に入っている (example.com ではなく api.example.com の zone)
  • TTL が長すぎて伝搬しない → 5 分ほど待つ

2) CloudFront 証明書をソウルで発行 #

CloudFront は us-east-1 のみ。コンソールで取得時、右上を N. Virginia に。

3) HTTP 80 Listener を作らず HTTPS のみ #

ユーザーが http://example.com で来ると timeout。80 Listener の redirect to HTTPS が標準。

4) Health check path が / #

/ が重い場 (DB 呼び出し等) なら ALB health check が DB を 30 秒ごとに爆撃。/health のような軽いパス を別途用意。

5) Target Group のポート vs Listener のポート #

ALB Listener は 443 だが Target Group の EC2 は 8080 ということがあります。両者は別物。Target Group のポートは EC2 が listen 中の場。

6) 502 Bad Gateway #

ALB → EC2 応答が崩れるとき。よくある原因:

  • EC2 の keep-alive timeout < ALB idle timeout (60s 既定)
  • EC2 が応答する前に切れる
  • EC2 SG が ALB SG を inbound で受けていない
  • EC2 が 8080 で listen していない

7) Sticky session で負荷偏り #

特定インスタンスにだけリクエストが溜まり、1 台だけ CPU 100% — Stickiness をオフして stateless に。

8) Cross-Zone オフ #

旧 ALB の cross-zone オプションがオフだと AZ 単位均等分配 — ある AZ のインスタンスは少ないのにトラフィックは同量 → 負荷偏り。Cross-zone load balancing を有効化 (ALB は既定オン、NLB は費用ゆえ既定オフ)。

9) Idle timeout の罠 #

ALB の idle timeout (既定 60s) がバックエンド / クライアントの keep-alive より短いと 502。通常はバックエンド keep-alive > ALB idle。

まとめ #

今回押さえたこと:

  • ELB = ALB / NLB / GWLB。99% の一般的 web は ALB
  • ALB: L7、path / host / header ルーティング、WAF 連動、Lambda target、Cognito 認証
  • NLB: L4、固定 IP、数百万 RPS、PrivateLink
  • ALB の場 = Listener (受けるポート) → Listener Rule (path/host) → Target Group (送る場) → Health Check
  • Target Group の target-type = instance / ip / lambda
  • Listener Rule の action = forward / redirect / fixed-response / authenticate
  • HTTP → HTTPS redirect が運用標準 (80 Listener の default action)
  • Health check は軽い /health、deep は別途 /health/deep
  • ACM = 無料 SSL 証明書 + 自動更新。DNS 検証 推奨
  • リージョンマッピング — ALB は同リージョン、CloudFront は常に us-east-1
  • HTTPS を貼る 6 ステップ — 証明書リクエスト → CNAME 検証 → ISSUED → Listener attach → 80 redirect → Route 53 Alias
  • Security Policy で許可 TLS バージョンを制限
  • 罠 — 証明書検証失敗、CloudFront リージョン、80 抜け、health check 重い、ポート混乱、502、sticky 偏り、cross-zone、idle timeout

次回 — CloudFront #

ALB までの場は片付きました。最後に、ユーザーに近くキャッシュ を置く場 — CloudFront です。

#7 CloudFront で静的サイトを配信 では、Origin / Behavior / Cache Policy の流れ、S3 + CloudFront 静的ホスティングパターン、OAC で S3 を安全に隠す方法、そして無効化 (invalidation) まで整理します。

X