はじめに
EC2 上の nginx なら、ログを見たければサーバーに入って access.log を開けばいい。
$ tail -f /var/log/nginx/access.log
では ALB は? SSH できるサーバーが存在しない。
- そもそも ALB にログってあるのか
- あるなら、どこに出せるのか
が気になって調べたので整理する。
ALBにログってあるの?
ある。ただしデフォルトでは出ていない。
ALB のログ出力はオプション機能で、明示的に有効化しない限り 1 行も記録されない。
❌ 「マネージドだから AWS がどこかに勝手にログを残してくれている」は誤解。有効化する前のリクエストのログは、後からは絶対に取り出せない。
👉 「障害が起きてから有効化しても、障害時のログはない」ということ。使う予定がなくても先に有効化しておく価値がある。
どんなログがある?
ALB が出力できるログは 2 種類ある。
| 種類 | 単位 | 主な内容 |
|---|---|---|
| アクセスログ | リクエスト単位 | 時刻、クライアント IP、パス、ステータスコード、処理時間 |
| 接続ログ | 接続単位 | TLS プロトコル / 暗号スイート、ハンドシェイク遅延、クライアント証明書情報 |
-
アクセスログ:nginx の
access.logに相当する、いわゆる「ログ」。ターゲットに届かなかったリクエスト(不正なリクエスト、healthy なターゲットがない場合など)も記録される - 接続ログ:2023 年に追加された新しいログ。1 つの持続的接続に複数のリクエストが乗る場合、アクセスログには複数行、接続ログには 1 行になる。mTLS(クライアント証明書認証)の失敗調査などで使う
👉 CloudWatch に出ている RequestCount や HTTPCode_ELB_5XX_Count はメトリクス(数値の集計)であってログではない。「5XX が増えた」ことは分かっても「どのリクエストが 5XX だったか」はメトリクスでは追えない。
どこに出せる?
S3 のみ。
アクセスログも接続ログも、出力先に指定できるのは S3 バケットだけだ。
❌ 「CloudWatch Logs に出せるはず」は誤解。ALB にはアプリケーションログを CloudWatch Logs へ直接送る機能はない。CloudWatch Logs で見たければ、S3 に置かれたログを Lambda などで自分で転送する必要がある。
S3 に置かれるログはこんな形をしている:
s3://alb-access-logs-example/AWSLogs/123456789012/elasticloadbalancing/ap-northeast-1/2026/07/17/
123456789012_elasticloadbalancing_ap-northeast-1_app.my-alb.1234567890abcdef_20260717T0140Z_10.0.1.23_5cw8xj2p.log.gz
- gzip 圧縮されたテキストファイル
-
AWSLogs/<アカウントID>/elasticloadbalancing/<リージョン>/<年>/<月>/<日>/という決まったパス構造 - ALB のノードごと・約 5 分ごとに 1 ファイル
なぜS3なの?
nginx のログとの一番の違いはここだ。
- nginx:ログは自分のサーバーのディスクに書かれる。自分で取りに行く
- ALB:実体のサーバーには触れない。AWS 側のサービスに届けてもらう
ALB のログ配送は、Elastic Load Balancing のログ配送サービスがユーザーのバケットにオブジェクトを書き込むという形で実現されている。
[ALB ノード群] → [ELB のログ配送サービス] → PutObject → [あなたの S3 バケット]
👉 つまり「AWS のサービスが、あなたのバケットに書き込む」構図。だから**バケット側で書き込みを許可(バケットポリシー)**しないと、ログは 1 バイトも届かない。有効化手順でバケットポリシーが必要になるのはこのためだ。
👉 出力先が S3 なのは、この「サービスからの大量・定期配送」に向いているから。ALB は 5 分ごとにノード単位でファイルをまとめて置いていく。リアルタイムのストリームではなく、バッチ配送だ。
有効化の流れ(概要)
手順は 3 ステップ。詳細な画面操作は省き、流れとキモだけ押さえる。
1. S3 バケットを作る(ALB と同一リージョン)
2. バケットポリシーで ELB のログ配送サービスに書き込みを許可する ← キモ
3. ALB の属性でアクセスログを有効化し、バケットを指定する
キモになるバケットポリシーはこれだけ:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "logdelivery.elasticloadbalancing.amazonaws.com"
},
"Action": "s3:PutObject",
"Resource": "arn:aws:s3:::alb-access-logs-example/AWSLogs/123456789012/*"
}
]
}
-
Principalが ELB のログ配送サービス。「AWS のサービスに書き込ませる」ことがポリシーにそのまま表れている -
Resourceにはアカウント ID まで含めたパスを書く。ワイルドカードで済ませると、他人のアカウントの ALB から自分のバケットにログを書き込まれ得る
👉 有効化した瞬間、ELB がバケットに ELBAccessLogTestFile というテストファイルを書き込む。これが置かれていれば権限設定は成功。逆に有効化時に Access Denied が出たら、ほぼバケットポリシーの問題(バケット名・アカウント ID・プレフィックスの不一致)だ。
ハマりどころ
調べていて「これは知らないと引っかかる」と思った点:
-
SSE-KMS のバケットには出せない
- サーバーサイド暗号化は SSE-S3(S3 マネージドキー)のみ対応。「セキュリティ要件で KMS 必須」なバケットに相乗りしようとすると詰む
-
バケットは ALB と同一リージョン必須
- 「ログは全部 us-east-1 の集約バケットに」という構成は直接はできない(レプリケーションで集める)
-
配送は約 5 分間隔・ベストエフォート
- リアルタイムではない。さらに公式ドキュメント自身が「完全な記録としてではなく、傾向の把握に使え」と明言している
-
トラフィックがないとログファイルも出ない
- 「有効化したのにファイルがない」のは、単にリクエストが来ていないだけのことがある
-
古いリージョンには旧方式のポリシーもある
- 2022 年 8 月以前からあるリージョンでは、サービスプリンシパルではなくリージョンごとの ELB アカウント ID(東京なら
582318560864)を Principal に書く旧方式も使われている。古い記事や既存のポリシーでこの形を見ても壊れているわけではない
- 2022 年 8 月以前からあるリージョンでは、サービスプリンシパルではなくリージョンごとの ELB アカウント ID(東京なら
まとめ
- ALB にログはある。ただしデフォルトでは出ていないので、有効化する前のログは存在しない
- 種類は**アクセスログ(リクエスト単位)と接続ログ(接続単位)**の 2 つ。CloudWatch メトリクスはログではない
- 出力先は S3 のみ。CloudWatch Logs には直接出せない
- マネージドサービスのログは「取りに行く」のではなく「届けてもらう」。だからバケットポリシーでログ配送サービスに書き込み許可を与えるのが設定のキモ
- ハマりどころ:SSE-KMS 非対応 / 同一リージョン必須 / 約 5 分間隔のベストエフォート配送
👉 料金は S3 の保存料だけ(配送自体は無料)。「いつか要るかも」なら先に有効化しておこう。障害が起きてからでは遅い。