【実務・中級編】 ALBの高度なルーティングアルゴリズム(重み付けおよびパスベース・ホストベースルーティング) – クラウド&コンテナネットワーク実践ガイド

ALBの「賢いルーティング」を極める:重み付けとL7制御で実現する現場のゼロダウンタイム戦略

こんにちは。数え切れないほどの深夜の障害対応と、その後のポストモーテム(事後検証)で白髪が増えたシニアSREです。

皆さんはAWSのALB(Application Load Balancer)を単なる「リクエストを振り分ける箱」だと思っていませんか?もしそうなら、非常にもったいない。ALBは、実はインフラエンジニアにとって最も強力な「トラフィック・オーケストレーター」です。

今日は、教科書には載っていない「現場の泥臭い知見」を交えながら、ALBのL7ルーティングと重み付け制御を深掘りします。

—

1. なぜ「L7ルーティング」がビジネスを救うのか

一般的なLBはL4(TCP/UDP)で動きますが、ALBはHTTP/HTTPSのヘッダーを解釈します。ここが重要です。リクエストの Host ヘッダーや Path を見て、バックエンドのターゲットグループ(TG)へ振り分ける。この「賢さ」が、マイクロサービスアーキテクチャの心臓部となります。

パスベース・ホストベースの仕組み

ALBは、リスナーに対して「ルール」を優先度順に並べます。

  • ホストベース: api.example.com と web.example.com を別々のサーバー群に飛ばす。
  • パスベース: /api/v1/user は認証基盤へ、/api/v1/products はカタログ基盤へ飛ばす。

これらを組み合わせることで、モノリスなアプリを少しずつマイクロサービスへ切り出す「ストラングラー・フィグ・パターン(Strangler Fig Pattern)」が現実的なものになります。

—

2. 現場で重宝する「重み付け分散」の真実

ブルー/グリーンデプロイメントや、Canaryリリース(カナリアリリース)を行う際、最もお世話になるのが「ターゲットグループの重み付け」です。

例えば、新しいAPIサーバー(TG-New)を本番に投入する際、いきなり全トラフィックを向けるのは自殺行為です。まずは10%だけ流して、エラーレートとレイテンシを監視する。これがSREの鉄則です。

構成例:重み付け設定(Terraform記述)

Terraformで記述する場合、リスナーアクションの forward ブロック内で定義します。

resource "aws_lb_listener_rule" "canary_rule" {
  listener_arn = aws_lb_listener.front_end.arn
  priority     = 100

  action {
    type = "forward"
    forward {
      # 旧バージョンに90%
      target_group {
        arn    = aws_lb_target_group.old_version.arn
        weight = 90
      }
      # 新バージョンに10%
      target_group {
        arn    = aws_lb_target_group.new_version.arn
        weight = 10
      }
      stickiness {
        enabled  = true
        duration = 3600 # 1時間は同じTGに振り分ける
      }
    }
  }

  condition {
    path_pattern {
      values = ["/api/v1/*"]
    }
  }
}

SREの現場Tips:
stickiness(スティッキーセッション)の設定には注意してください。重み付けを行っている場合、クライアントのCookieベースでセッションを固定すると、比率が正確に反映されなくなります。カナリアリリースの初期段階では、あえてスティッキーセッションを無効にし、確率的な分散を優先するのがコツです。

—

3. 実践:デバッグと挙動確認

構築したルールが正しく動いているか、本番環境で試すのは勇気がいりますよね。まずはローカルから curl を叩いて、レスポンスヘッダーを確認するのが定石です。

# -v でHTTPヘッダーを表示し、リクエストがどのターゲットに到達したか検証する
# ALBが追加する 'X-Amzn-Trace-Id' を確認するのも有効です
curl -v -H "Host: api.example.com" https://your-alb-dns.com/api/v1/user

Pythonで簡易的な分散確認ツールを書くなら、以下のようなスクリプトを回して、数秒間の分布を見るのが一番手っ取り早いです。

import requests
from collections import Counter

# 100回リクエストを投げて、レスポンス内の特定の識別子(サーバーID等)を集計する
results = []
for _ in range(100):
    res = requests.get("https://your-alb-dns.com/api/v1/user")
    # レスポンスヘッダーからインスタンスID等を抽出(アプリ側で仕込んでおくこと)
    server_id = res.headers.get("X-Server-ID")
    results.append(server_id)

print(Counter(results))

—

4. トラブルシューティングの勘所

最後に、現場で必ずぶつかる壁を共有します。

1. 正規表現の罠:
path_pattern で正規表現を使う際、複雑すぎると評価順序のデバッグが困難になります。ルール数は最大100個まで。優先度(Priority)が若い順に評価されることを常に意識してください。

2. 503 Service Unavailable:
これが出たら、まずターゲットグループの「ヘルスチェック」を確認してください。ALBのルーティングが正しくても、ターゲットの HealthCheck が失敗していればリクエストは通りません。

3. HTTP 404:
ALBのルールで一致するものがない場合、デフォルトアクション(デフォルトターゲットグループ)に転送されます。もしデフォルトターゲットが存在しない、あるいは設定ミスがあると、ALBは迷わず 404 を返します。「意図しないリクエスト」を拾うための「キャッチオール用ターゲット」を常に用意しておくのが、ベテランのインフラ構成です。

—

まとめ

ALBのルーティング制御は、単なる設定作業ではありません。それは「トラフィックの交通整理」という名の、サービスを守るための防波堤構築です。

  • 重み付けを使って安全にデプロイする。
  • パスベースでサービスを疎結合にする。
  • ヘッダーを駆使してリクエストを適切にハンドリングする。

これらを使いこなせば、皆さんのインフラはより堅牢に、そしてリリースが恐ろしくないものになるはずです。もし設定で詰まったら、まずは curl でヘッダーを追いかけるところから始めてみてください。パケットの行方を想像する力が、SREとしての最大の武器になります。

それでは、また次回の障害対応(ではなく、平和な運用)でお会いしましょう!

コメント

タイトルとURLをコピーしました