
NLB と ALB のアクセスログは違うんやで、という話
この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
NLB が TLS Termination 対応と同時にアクセスログ出力が可能になったのは記憶にあたらしいかと思います。
このアップデートで、単純に「NLB でもアクセスログが取得できるようになった」と理解していたのですが、取得できる内容はずいぶん違うんやで、ということをきちんと理解しておりませんでした。 というのが、今日の本題になります。
NLB アクセスログ
はじめに、大前提になりますが NLB のアクセスログが取得できるのは、リスナーが TLS の場合のみです。リスナーが TCP の場合は、アクセスログを設定していも出力されません。案外、見落としがちなポイントなのでアクセスログ設定して安心している方はご注意を。
それでは、まず NLB のアクセスログを見てみましょう。(以下、公式ガイドからサンプルを拝借)
tls 1.0 2018-12-20T02:59:40 net/my-network-loadbalancer/c6e77e28c25b2234 g3d4b5e8bb8464cd 72.21.218.154:51341 172.100.100.185:443 5 2 98 246 - arn:aws:acm:us-east-2:671290407336:certificate/2a108f19-aded-46b0-8493-c63eb1ef4a99 - ECDHE-RSA-AES128-SHA tlsv12 - my-network-loadbalancer-c6e77e28c25b2234.elb.us-east-2.amazonaws.com
NLB アクセスログのフィールドは下記のとおりです。
| フィールド | 説明 | サンプルログの値 | 
|---|---|---|
| type | リスナーの種類 | tls | 
| version | ログエントリのバージョン | 1.0 | 
| timestamp | TLS 接続の最後に記録されたタイムスタンプ | 2018-12-20T02:59:40 | 
| elb | ロードバランサーのリソース ID | net/my-network-loadbalancer/c6e77e28c25b2234 | 
| listener | TLS リスナーのリソース ID | g3d4b5e8bb8464cd | 
| client:port | クライアントの IP アドレスとポート | 72.21.218.154:51341 | 
| listener:port | リスナーの IP アドレスとポート | 172.100.100.185:443 | 
| connection_time | 接続が完了するまでの合計時間(ms) | 5 | 
| tls_handshake_time | TLS ハンドシェイクが完了するまでの合計時間(ms) | 2 | 
| received_bytes | ロードバランサーで受信したバイト数 (復号後) | 98 | 
| sent_bytes | クライアントに送信されたバイト数 (復号前) | 246 | 
| incoming_tls_alert | ロードバランサーによって受信された TLS アラートの整数値。存在しない場合 - に設定 | - | 
| chosen_cert_arn | クライアントに提供された証明書の ARN | arn:aws:acm:us-east-2:671290407336:certificate/2a108f19-aded-46b0-8493-c63eb1ef4a99 | 
| chosen_cert_serial | 将来のために予約されています。常に - に設定 | - | 
| tls_cipher | クライアントとネゴシエートされた暗号スイート | ECDHE-RSA-AES128-SHA | 
| tls_protocol_version | クライアントとネゴシエートされた TLS プロトコル | tlsv12 | 
| tls_named_group | 将来のために予約されています。常に - に設定 | - | 
| domain_name | クライアント hello メッセージの server_name 拡張機能の値 | my-network-loadbalancer-c6e77e28c25b2234.elb.us-east-2.amazonaws.com | 
ざっと見ておわかりいただけるかと思いますが、ALB のような HTTP リクエストや user_agent といったフィールドは NLB のアクセスログでは取得できません。 ALB が L7 のコンテントベースのロードバランサであるのに対し、NLB は L4 機能を提供するロードバランサあることを思い出せば、「そりゃそうだ」と納得がいきますね。
ALB アクセスログとの比較
それでは、次に ALB の HTTPS リスナーのログエントリを見てみましょう。(以下、公式ガイドからサンプルを拝借)
https 2018-07-02T22:23:00.186641Z app/my-loadbalancer/50dc6c495c0c9188 192.168.131.39:2817 10.0.0.1:80 0.086 0.048 0.037 200 200 0 57 "GET https://www.example.com:443/ HTTP/1.1" "curl/7.46.0" ECDHE-RSA-AES128-GCM-SHA256 TLSv1.2 arn:aws:elasticloadbalancing:us-east-2:123456789012:targetgroup/my-targets/73e2d6bc24d8a067 "Root=1-58337281-1d84f3d73c47ec4e58577259" "www.example.com" "arn:aws:acm:us-east-2:123456789012:certificate/12345678-1234-1234-1234-123456789012" 1 2018-07-02T22:22:48.364000Z "authenticate,forward" "-" "-"
ALB アクセスログのフィールドと比較表は下記のとおりです。
| ALBのフィールド | 説明 | NLB のフィールド有無 | 
|---|---|---|
| type | リクエストまたは接続のタイプ | ○ | 
| timestamp | クライアントに対してレスポンスを生成した時刻 | ○ | 
| elb | ロードバランサーのリソース ID | ○ | 
| client:port | リクエストを送信したクライアントの IP アドレスとポート | ○ | 
| target:port | このリクエストを処理したターゲットの IP アドレスとポート | ☓ | 
| request_processing_time | リクエストを受け取った時点からターゲットに送信するまでの合計経過時間(ms) | ☓ | 
| target_processing_time | ターゲットにリクエストを送信した時点から、そのターゲットが応答ヘッダーの送信を開始した時点までの合計経過時間(ms) | ☓ | 
| response_processing_time | ターゲットから応答ヘッダーを受け取った時点から、クライアントへの応答の送信を開始した時点までの合計経過時間(ms) | ☓ | 
| elb_status_code | ロードバランサーからの応答のステータスコード | ☓ | 
| target_status_code | ターゲットから応答のステータスコード | ☓ | 
| received_bytes | クライアント (リクエスタ) から受け取ったリクエストのサイズ | ○ | 
| sent_bytes | クライアント (リクエスタ) に返される応答のサイズ | ○ | 
| "request" | HTTP メソッド + プロトコル://ホスト:ポート/uri + HTTP バージョン | ☓ | 
| "user_agent" | リクエスト元のクライアントを特定する User-Agent | ☓ | 
| ssl_cipher | [HTTPS リスナー] SSL 暗号 | ○ (tls_cipher) | 
| ssl_protocol | [HTTPS リスナー] SSL プロトコル | ○ (tls_protocol_version) | 
| target_group_arn | ターゲットグループの ARN | ☓ | 
| "trace_id" | X-Amzn-Trace-Id ヘッダーのコンテンツ | ☓ | 
| "domain_name" | [HTTPS リスナー] TLS ハンドシェイク中にクライアントから提供される SNI ドメイン | ○ | 
| "chosen_cert_arn" | [HTTPS リスナー] クライアントに提示される証明書の ARN | ○ | 
| matched_rule_priority | リクエストに一致したルールの優先度の値 | ☓ | 
| request_creation_time | ロードバランサーがクライアントからリクエストを受け取った時刻 | ☓ | 
| "actions_executed" | リクエストの処理時に実行されるアクション | ☓ | 
| "redirect_url" | HTTP レスポンスのロケーションヘッダーのリダイレクトターゲットの URL | ☓ | 
| "error_reason" | reason コード | ☓ | 
反対に NLB アクセスログのみのフィールドは下記になります。
- listener:port
- connection_time
- tls_handshake_time
- incoming_tls_alert
- chosen_cert_serial
- tls_named_group
ALB ではリクエストを処理したターゲット IP が記録されますが、NLB ではリスナー IP しか記録されません。リスナー IP は、NLB に割り当てられる ENI のプライベート IP アドレスになります。つまり、NLB のアクセスログだけでは最終的にどのノードにリクエストが流れたかを判断できないことになります。
結論
以上のように、NLB と ALB ではアクセスログの内容が異なりますので、従来の ALB アクセスログと同じ内容を期待して設定されている場合は、お気をつけください。
NLB 配下で HTTP リクエストを含めたアクセスログは、Web サーバ上のアクセスログで取得するようにしましょう。また、アクセスログを最終的に S3 で保管したい場合は、Cloudwatch Logs や、Fluentd をあわせて検討されるのが良いかと思います。
さいごに
「NLB のアクセスログ対応」ときいて、すっかり ALB のアクセスログをイメージしておりましたが、よくよく考えると L4、L7 で機能が違うわけですから、その内容も異なって当然ですね。「ELB アクセスログ」という一括りで考えてしまうと、うっかり見落としてしまうポイントかと思いますので、みなさまもお気をつけください!
以上!ひっそり新しい写真に更新した丸毛(@marumo1981)でした!











