ALBのヘルスチェックを制する者は、クラウドの夜更かしを制する:実務で差がつく設計の要諦
SREとして現場に立っていると、「ALBのヘルスチェックが通らない」という深夜の緊急通知ほど心臓に悪いものはありません。ロードバランサーは、単なるトラフィックの振り分け機ではありません。それは「生きているサービス」と「死んでいるサービス」の境界線を引き、ユーザーに「503 Service Unavailable」を見せないための最後の砦です。
今回は、ALB(Application Load Balancer)のターゲットグループにおけるヘルスチェックを、教科書的な説明ではなく、パケットが現場でどう動いているのかという観点から深掘りします。
—
1. ヘルスチェックの裏側:パケットの「往復」を想像する
ALBのヘルスチェックは、AWSの管理コンソールでポチポチと設定して終わりではありません。実体は、ALBの各AZ(アベイラビリティゾーン)に配置されたノードが、ターゲットに対して定期的に送る「問いかけ」です。
通信フローのシーケンス
1. ALB → ターゲット: HTTP GET リクエスト(または gRPC)を送信。
2. ターゲット → ALB: アプリケーションプロセスがリクエストを処理し、レスポンスを返す。
3. ALBの判定: レスポンスコードが「成功(デフォルト200)」であれば「Healthy」、そうでなければ「Unhealthy」とみなす。
このとき重要なのが、ALBから来るリクエストの「送信元IP」です。VPC内のセキュリティグループを絞り込む際、0.0.0.0/0 を許可して満足していませんか? 実際には、そのターゲットグループが所属するVPCのCIDRから、ALBノードが通信を行っています。ここを理解していないと、セキュリティグループのルール一つでヘルスチェックが永遠に失敗し続けるという泥沼にハマります。
—
2. パラメーター設計の「黄金比」
ヘルスチェックの設定項目には、実は開発者が無意識に設定しがちな「罠」が潜んでいます。
| 項目 | 推奨の考え方 | 現場の教訓 |
| :— | :— | :— |
| Health check interval | 30秒が基本 | 短すぎると高負荷時に自らDDosを仕掛けることに。 |
| Healthy threshold | 2〜3回 | ネットワークの瞬断で即落ちさせない猶予。 |
| Unhealthy threshold | 2回 | 「死」は速やかに検知し、切り離すべき。 |
| Timeout | 2〜5秒 | 処理時間がこれを超えると、たとえ後で成功しても「失敗」扱いです。 |
特に Timeout は要注意です。アプリケーションが重い処理を行っている最中にヘルスチェックが来ると、ALBは「あ、これ死んでるな」と誤判定します。ヘルスチェック用のエンドポイントは、ビジネスロジックから切り離された、極めて軽量なものにすべきです。
—
3. 実践:ヘルスチェックを「正しく」実装するコード例
Web APIを開発する際、単に 200 OK を返すだけのエンドポイントを作っていませんか?
実務では、データベースへの接続確認まで含めるか、あるいはあえて「静的なヘルスチェック用ファイル」を置くか、戦略的な判断が求められます。
Python (FastAPI) での記述例
from fastapi import FastAPI, Response, status
app = FastAPI()
# 外部監視用の軽量エンドポイント
@app.get("/healthz")
async def health_check():
# データベースの疎通確認などをここで行うと
# DB障害時に即座にターゲットから外すことができる
try:
# DB接続確認などのロジック
return Response(status_code=status.HTTP_200_OK)
except Exception:
# DBが死んでいれば503を返し、ALBから切り離す
return Response(status_code=status.HTTP_503_SERVICE_UNAVAILABLE)
疎通確認用ワンライナー(デバッグ用)
ALBの設定が正しいか確認したいとき、curl でターゲットに対して直接叩いてみるのが鉄則です。
# ヘッダーを確認し、期待通りのステータスコードが返るかチェック
curl -v -H "User-Agent: ELB-HealthChecker/2.0" http://<ターゲットのIP>:8080/healthz
—
4. gRPCヘルスチェックの落とし穴
最近のマイクロサービスでは gRPC の利用が増えています。gRPCのヘルスチェックは、標準の gRPC Health Checking Protocol を利用します。
これは単なるHTTPの GET ではなく、grpc.health.v1.Health サービスを呼び出す仕組みです。ALBでこれを設定する場合、プロトコルを gRPC に指定し、パスを /grpc.health.v1.Health/Check とします。
ここで注意!
アプリケーションコード側で、必ずこの Health サービスを実装しておかなければなりません。ライブラリ(Pythonなら grpcio-health-checking など)を使わずに手動で実装しようとして、仕様を満たせずハマるケースが後を絶ちません。
—
5. まとめ:SREとしての心得
最後に、トラブルシューティングの現場から一つだけ。
ヘルスチェックが失敗したとき、真っ先に疑うべきは以下の3点です。
1. セキュリティグループ: ALBのサブネットからターゲットへの通信が許可されているか?
2. パスの不一致: /health なのか /healthz なのか?(意外と多いミスです)
3. アプリケーションの応答時間: Timeout 設定値より処理が長くなっていないか?
ヘルスチェックの設定は、サービスの安定性を担保するための「契約」のようなものです。曖昧な設定は、深夜の呼び出しという形で必ず自分に返ってきます。今日から、エンドポイント一つ一つの定義に、「なぜこの値なのか?」という理由を添えて設計してみてください。
それが、クラウドエンジニアとして一歩先へ行くための近道です。
コメント