なぜALBの「クロスゾーン負荷分散」で夜中に叩き起こされるのか?―SREが語るAZ間通信の深淵
クラウドインフラを設計する際、皆さんは「クロスゾーン負荷分散」のスイッチを迷わずONにしていますか?「とりあえず高可用性のためだし、ONが正義でしょ」と考えているなら、一度立ち止まってください。その設定が、実はあなたのサービスのレイテンシと、月末のAWS請求書を密かに蝕んでいるかもしれません。
今日は、ロードバランサー(ALB)の裏側でパケットがどう踊り、AZ(アベイラビリティゾーン)を跨ぐたびに何が起きているのか、現場の泥臭い視点から紐解いていきましょう。
—
1. クロスゾーン負荷分散の「本来の姿」
ALBのデフォルト挙動を理解するために、まずは「クロスゾーン負荷分散(Cross-Zone Load Balancing)」がOFFの状態を想像してください。
通常、ALBは各AZに個別の負荷分散ノードを配置します。OFFの状態では、「ALBノードは、自分が属するAZ内のターゲット(EC2/ECSなど)のみにリクエストを振り分ける」というルールで動きます。
なぜこれが問題になるのか?
もしAZ-AとAZ-Bでターゲットの台数に偏りがあったらどうでしょう。
- AZ-A:ターゲット 10台
- AZ-B:ターゲット 1台
この状態でトラフィックが均等に流入すると、AZ-Bの1台は瞬く間にパンクします。これが「AZ間負荷分散」をONにすべき最大の理由です。これをONにすると、ALBはAZの境界を無視して、全AZのターゲットに対してリクエストを均等にばら撒くようになります。
—
2. パケットはAZを跨ぐたびに「コスト」を支払う
ここからがSREの腕の見せ所です。クロスゾーン負荷分散をONにすると、ALBは「AZ-Aへのリクエストを、あえてAZ-Bのターゲットに転送する」という挙動をします。
ここで発生するのが、「AZ間データ転送コスト」です。
AWSにおいて、AZを跨ぐ通信は「データ転送量」として課金対象になります。トラフィック量が多いWeb APIであれば、このコストは無視できない金額に膨らみます。さらに、パケットがAZを跨ぐことで、物理的な距離(光ファイバーの長さ)によるミリ秒単位のオーバーヘッド、つまりレイテンシの増加も避けられません。
トレードオフの判断基準
- ONにするべき時: AZ間でターゲットの負荷が不均衡になりやすく、可用性を最優先したい場合。
- OFFにするべき時: ターゲットの台数が各AZで完璧に制御されており、レイテンシとコストを極限まで削りたい場合。
—
3. 実践:Terraformでの設定と検証コード
現場でインフラを管理する際、Terraformでこの設定を制御するのは基本中の基本です。
# ALB(Application Load Balancer)のクロスゾーン設定例
resource "aws_lb" "main" {
name = "production-api-lb"
load_balancer_type = "application"
subnets = [aws_subnet.az1.id, aws_subnet.az2.id]
# ここを true にするとコストが増えるが、負荷分散は平準化される
enable_cross_zone_load_balancing = true
}
では、実際にこの設定が正しく効いているか、あるいは各AZに均等にリクエストが飛んでいるかを確認する方法です。Pythonの requests ライブラリで、X-Forwarded-For やターゲットのホスト名を確認するスクリプトを書いてみましょう。
import requests
# ALBのDNS名
url = "http://my-api-load-balancer-12345.ap-northeast-1.elb.amazonaws.com"
# 複数回リクエストを送って、どこのAZ(インスタンス)で処理されたかを確認する
for i in range(10):
response = requests.get(url)
# レスポンスヘッダーやボディに自身のAZ情報を埋め込むようにアプリを設計しておくとデバッグが捗る
print(f"Request {i+1}: Processed by {response.headers.get('X-App-Instance-AZ')}")
—
4. 現場で役立つデバッグのTips
もし「特定のAZだけレスポンスが遅い」という障害に遭遇したら、まずはAWSの TargetGroup のメトリクスを疑ってください。
CloudWatchで以下のメトリクスを監視するのは鉄則です。
1. RequestCountPerTarget: AZ間で値に乖離がないか?
2. ActiveConnectionCount: 特定のAZに接続が滞留していないか?
3. TargetResponseTime: 特定のAZのターゲット群だけが悲鳴を上げていないか?
クロスゾーン負荷分散がONであれば、RequestCountPerTarget はすべてのAZでほぼ均等になるはずです。もしここで乖離があるなら、それはALBの問題ではなく、ターゲットグループの登録数や、ヘルスチェックの失敗が原因である可能性が高いと言えます。
—
最後に:エンジニアとしての心構え
「デフォルト設定だから」という理由でONにしている機能は、実はサービスの寿命を縮める要因かもしれません。
可用性は、ただスイッチをONにすれば手に入る魔法ではありません。「コスト・レイテンシ・可用性」の三つ巴のバランスを、自社のトラフィック特性に合わせて調整し続けること。それが、私たちSREに課せられた責務です。
次のデプロイメントの前には、ぜひ一度この enable_cross_zone_load_balancing の設定と、皆様のサービスのトラフィックパターンを見直してみてください。きっと、より筋肉質なインフラが見えてくるはずです。
コメント