ALB の CloudWatch Logs 統合ログ記録を CloudFormation で設定してみた
はじめに
2026年7月23日、Application Load Balancer(ALB)のログが CloudWatch Logs の統合ログ記録(Vended Logs)に対応しました。対象はアクセスログ・接続ログ・ヘルスチェックログの3種類です。配信先には S3、CloudWatch Logs、Amazon Data Firehose を選べます。
3本目のリンクは前記事で、レガシー方式(ALB 属性による S3 配信)との違いや CLI での設定手順を紹介しています。
本記事では Delivery Source / Delivery Destination / Delivery の3リソースを CloudFormation で記述しました。S3・CloudWatch Logs・Firehose の3配信先を同時に構成し、RecordFields は全フィールドが必須のため、指定時の注意点もあわせて確認しています。
検証内容
検証環境
| 項目 | 値 |
|---|---|
| リージョン | ap-northeast-1 |
| ALB | internet-facing、HTTP:80 と HTTPS:443 の2リスナー |
| オリジン | EC2(Amazon Linux 2023、UserData で nginx を導入) |
| セキュリティグループ | ALB は検証実行元の1アドレスのみ許可 |
| ログタイプ | ALB_ACCESS_LOGS / ALB_CONNECTION_LOGS / ALB_HEALTH_CHECK_LOGS |
HTTPS リスナーは、接続ログに TLS 関連のフィールドを出すために設けました。
ALB 属性によるレガシー方式の S3 配信は、次のとおり3つとも無効のままにしています。本検証のログ出力はすべて統合ログ記録経由です。
access_logs.s3.enabled = false
health_check_logs.s3.enabled = false
connection_logs.s3.enabled = false
リソースは基盤テンプレートと配信テンプレートの2つに分けました。
| リソース | 作成場所 |
|---|---|
| ALB / EC2 / ターゲットグループ / リスナー | 基盤テンプレート(本記事では構成の説明のみ) |
| S3 バケットとバケットポリシー | 配信テンプレート |
| CloudWatch Logs ロググループ | 配信テンプレート |
| Firehose 配信ストリームと実行ロール | 配信テンプレート |
| Delivery Source / Destination / Delivery | 配信テンプレート |
| ACM 証明書(HTTPS リスナー用) | 事前作成。テンプレート外でパラメータとして渡す |
Firehose 配信ストリームは DirectPut 型とし、後段は同一 S3 バケットの別プレフィックスへ書き込みました。バッファは60秒 / 5MB、GZIP 圧縮、レコード変換なしです。
3つの配信先を CloudFormation で設定する
AWS::Logs::DeliverySource はログの出どころ(ALB とログタイプ)、AWS::Logs::DeliveryDestination は配信先(S3 バケット・ロググループ・Firehose ストリーム)を表し、この2つを AWS::Logs::Delivery で紐付けます。
配信テンプレート全文
AWSTemplateFormatVersion: '2010-09-09'
Description: ALB CloudWatch Logs integrated logging - delivery to S3 / CloudWatch Logs / Firehose
Parameters:
LoadBalancerArn:
Type: String
Description: ARN of the target ALB
BucketName:
Type: String
Description: S3 bucket that receives the vended logs
BillingGroupPrefix:
Type: String
Default: kiro-alb-cwl
Description: Prefix of the CmBillingGroup cost allocation tag values
Resources:
# ---------------------------------------------------------------
# Destination 1: S3
# ---------------------------------------------------------------
LogsBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: !Ref BucketName
PublicAccessBlockConfiguration:
BlockPublicAcls: true
BlockPublicPolicy: true
IgnorePublicAcls: true
RestrictPublicBuckets: true
BucketEncryption:
ServerSideEncryptionConfiguration:
- ServerSideEncryptionByDefault:
SSEAlgorithm: AES256
Tags:
- Key: CmBillingGroup
Value: !Sub ${BillingGroupPrefix}-s3-bucket
LogsBucketPolicy:
Type: AWS::S3::BucketPolicy
Properties:
Bucket: !Ref LogsBucket
PolicyDocument:
Version: '2012-10-17'
Statement:
- Sid: AWSLogsDeliveryWrite
Effect: Allow
Principal:
Service: delivery.logs.amazonaws.com
Action: s3:PutObject
Resource: !Sub arn:aws:s3:::${BucketName}/*
Condition:
StringEquals:
aws:SourceAccount: !Ref AWS::AccountId
ArnLike:
aws:SourceArn: !Sub arn:aws:logs:${AWS::Region}:${AWS::AccountId}:*
- Sid: AWSLogsDeliveryAclCheck
Effect: Allow
Principal:
Service: delivery.logs.amazonaws.com
Action: s3:GetBucketAcl
Resource: !Sub arn:aws:s3:::${BucketName}
Condition:
StringEquals:
aws:SourceAccount: !Ref AWS::AccountId
S3Destination:
Type: AWS::Logs::DeliveryDestination
Properties:
Name: alb-logs-s3-destination
DeliveryDestinationType: S3
OutputFormat: json
DestinationResourceArn: !GetAtt LogsBucket.Arn
Tags:
- Key: CmBillingGroup
Value: !Sub ${BillingGroupPrefix}-dest-s3
# ---------------------------------------------------------------
# Destination 2: CloudWatch Logs
# ---------------------------------------------------------------
AccessLogGroup:
Type: AWS::Logs::LogGroup
Properties:
LogGroupName: /aws/vendedlogs/alb-access-logs
RetentionInDays: 1
Tags:
- Key: CmBillingGroup
Value: !Sub ${BillingGroupPrefix}-loggroup
CwlDestination:
Type: AWS::Logs::DeliveryDestination
Properties:
Name: alb-logs-cwl-destination
DeliveryDestinationType: CWL
OutputFormat: json
DestinationResourceArn: !GetAtt AccessLogGroup.Arn
Tags:
- Key: CmBillingGroup
Value: !Sub ${BillingGroupPrefix}-dest-cwl
# ---------------------------------------------------------------
# Destination 3: Data Firehose
# ---------------------------------------------------------------
FirehoseToS3Role:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service: firehose.amazonaws.com
Action: sts:AssumeRole
Policies:
- PolicyName: write-to-logs-bucket
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- s3:AbortMultipartUpload
- s3:GetBucketLocation
- s3:GetObject
- s3:ListBucket
- s3:ListBucketMultipartUploads
- s3:PutObject
Resource:
- !Sub arn:aws:s3:::${BucketName}
- !Sub arn:aws:s3:::${BucketName}/*
Tags:
- Key: CmBillingGroup
Value: !Sub ${BillingGroupPrefix}-iam
FirehoseStream:
Type: AWS::KinesisFirehose::DeliveryStream
Properties:
DeliveryStreamName: alb-logs-firehose
DeliveryStreamType: DirectPut
ExtendedS3DestinationConfiguration:
BucketARN: !Sub arn:aws:s3:::${BucketName}
RoleARN: !GetAtt FirehoseToS3Role.Arn
Prefix: firehose/access-logs/
ErrorOutputPrefix: firehose/errors/
CompressionFormat: GZIP
BufferingHints:
IntervalInSeconds: 60
SizeInMBs: 5
Tags:
- Key: CmBillingGroup
Value: !Sub ${BillingGroupPrefix}-firehose
FirehoseDestination:
Type: AWS::Logs::DeliveryDestination
Properties:
Name: alb-logs-firehose-destination
DeliveryDestinationType: FH
OutputFormat: json
DestinationResourceArn: !GetAtt FirehoseStream.Arn
Tags:
- Key: CmBillingGroup
Value: !Sub ${BillingGroupPrefix}-dest-firehose
# ---------------------------------------------------------------
# Delivery sources (one per log type)
# ---------------------------------------------------------------
AccessLogSource:
Type: AWS::Logs::DeliverySource
Properties:
Name: alb-access-logs
LogType: ALB_ACCESS_LOGS
ResourceArn: !Ref LoadBalancerArn
Tags:
- Key: CmBillingGroup
Value: !Sub ${BillingGroupPrefix}-source
ConnectionLogSource:
Type: AWS::Logs::DeliverySource
Properties:
Name: alb-connection-logs
LogType: ALB_CONNECTION_LOGS
ResourceArn: !Ref LoadBalancerArn
Tags:
- Key: CmBillingGroup
Value: !Sub ${BillingGroupPrefix}-source
HealthCheckLogSource:
Type: AWS::Logs::DeliverySource
Properties:
Name: alb-health-check-logs
LogType: ALB_HEALTH_CHECK_LOGS
ResourceArn: !Ref LoadBalancerArn
Tags:
- Key: CmBillingGroup
Value: !Sub ${BillingGroupPrefix}-source
# ---------------------------------------------------------------
# Deliveries (source x destination)
# RecordFields is omitted, so the service default field set and
# order are used.
# ---------------------------------------------------------------
AccessLogToS3:
Type: AWS::Logs::Delivery
Properties:
DeliverySourceName: !Ref AccessLogSource
DeliveryDestinationArn: !GetAtt S3Destination.Arn
S3SuffixPath: access-logs/{account-id}/{region}/{yyyy}/{MM}/{dd}/
S3EnableHiveCompatiblePath: false
Tags:
- Key: CmBillingGroup
Value: !Sub ${BillingGroupPrefix}-dlv-s3-access
ConnectionLogToS3:
Type: AWS::Logs::Delivery
Properties:
DeliverySourceName: !Ref ConnectionLogSource
DeliveryDestinationArn: !GetAtt S3Destination.Arn
S3SuffixPath: connection-logs/{account-id}/{region}/{yyyy}/{MM}/{dd}/
S3EnableHiveCompatiblePath: false
Tags:
- Key: CmBillingGroup
Value: !Sub ${BillingGroupPrefix}-dlv-s3-connection
HealthCheckLogToS3:
Type: AWS::Logs::Delivery
Properties:
DeliverySourceName: !Ref HealthCheckLogSource
DeliveryDestinationArn: !GetAtt S3Destination.Arn
S3SuffixPath: health-check-logs/{account-id}/{region}/{yyyy}/{MM}/{dd}/
S3EnableHiveCompatiblePath: false
Tags:
- Key: CmBillingGroup
Value: !Sub ${BillingGroupPrefix}-dlv-s3-healthcheck
AccessLogToCwl:
Type: AWS::Logs::Delivery
Properties:
DeliverySourceName: !Ref AccessLogSource
DeliveryDestinationArn: !GetAtt CwlDestination.Arn
Tags:
- Key: CmBillingGroup
Value: !Sub ${BillingGroupPrefix}-dlv-cwl-access
AccessLogToFirehose:
Type: AWS::Logs::Delivery
Properties:
DeliverySourceName: !Ref AccessLogSource
DeliveryDestinationArn: !GetAtt FirehoseDestination.Arn
Tags:
- Key: CmBillingGroup
Value: !Sub ${BillingGroupPrefix}-dlv-fh-access
Outputs:
BucketName:
Value: !Ref LogsBucket
LogGroupName:
Value: !Ref AccessLogGroup
FirehoseStreamName:
Value: !Ref FirehoseStream
配信先が3種類あっても、AWS::Logs::DeliveryDestination 自体の書き方はほぼ共通です。今回のテンプレートで配信先ごとに書き分ける主なプロパティは DeliveryDestinationType と DestinationResourceArn です。また、S3・CloudWatch Logs・Firehose では周辺リソースの設定も異なります。
まず DeliveryDestinationType です。指定する値は、S3 では S3、CloudWatch Logs では CWL、Firehose では FH です。CloudWatchLogs や Firehose のような表記は指定しません。
S3Destination:
Properties:
DeliveryDestinationType: S3
CwlDestination:
Properties:
DeliveryDestinationType: CWL
FirehoseDestination:
Properties:
DeliveryDestinationType: FH
次に DestinationResourceArn です。S3 はバケット、CloudWatch Logs はロググループ、Firehose は配信ストリームの ARN を渡します。いずれも同一テンプレート内で作成したリソースを !GetAtt で参照できるため、ARN を文字列で組み立てる必要はありません。
S3Destination:
Properties:
DestinationResourceArn: !GetAtt LogsBucket.Arn
CwlDestination:
Properties:
DestinationResourceArn: !GetAtt AccessLogGroup.Arn
FirehoseDestination:
Properties:
DestinationResourceArn: !GetAtt FirehoseStream.Arn
S3 宛では、バケットポリシーで delivery.logs.amazonaws.com に s3:PutObject と s3:GetBucketAcl を許可します。呼び出し元は aws:SourceAccount と aws:SourceArn で絞ります。
- Sid: AWSLogsDeliveryWrite
Effect: Allow
Principal:
Service: delivery.logs.amazonaws.com
Action: s3:PutObject
Resource: !Sub arn:aws:s3:::${BucketName}/*
Condition:
StringEquals:
aws:SourceAccount: !Ref AWS::AccountId
ArnLike:
aws:SourceArn: !Sub arn:aws:logs:${AWS::Region}:${AWS::AccountId}:*
CloudWatch Logs 宛では、ロググループに delivery.logs.amazonaws.com の logs:CreateLogStream と logs:PutLogEvents を許可するリソースポリシーが必要です。今回のテンプレートでは AWS::Logs::ResourcePolicy を明示的に定義していません。設定者に必要な権限があれば、Delivery 作成時に AWS がこのポリシーを自動設定します(Logs sent to CloudWatch Logs)。
なお、Firehose 配信ストリーム自身が後段の S3 へ書き込むための実行ロールは必要で、テンプレートの FirehoseToS3Role として定義しています。
一方で、Firehose 宛に delivery.logs.amazonaws.com を信頼する自作ロールは不要でした。当初テンプレートに用意していたそのロールを削除してスタックを更新した後も、3配信先への配信は継続していました。CloudWatch Logs は Firehose への直接書き込みにサービスリンクロール AWSServiceRoleForLogDelivery を使用します(Using service-linked roles for CloudWatch Logs)。
権限の話とは別に、Delivery Source、Delivery Destination、Delivery の3リソースにはいずれもコスト配分タグを設定できます。CloudWatch Logs 統合のコストを把握する意図で、今回はテンプレート内の全リソースに CmBillingGroup を付与しました。
デプロイ後に aws logs describe-deliveries で確認した配信の一覧が次のとおりです。
| Delivery ID | Delivery Source | Delivery Destination | 種別 | recordFields |
|---|---|---|---|---|
| aaaa1111bbbb2222 | alb-access-logs | alb-logs-s3-destination | S3 | 未指定 |
| cccc3333dddd4444 | alb-connection-logs | alb-logs-s3-destination | S3 | 未指定 |
| eeee5555ffff6666 | alb-health-check-logs | alb-logs-s3-destination | S3 | 未指定 |
| gggg7777hhhh8888 | alb-access-logs | alb-logs-cwl-destination | CWL | 未指定 |
| iiii9999jjjj0000 | alb-access-logs | alb-logs-firehose-destination | FH | 未指定 |
アクセスログの Delivery Source alb-access-logs は S3・CWL・FH の3宛先に紐付いています。1つの Delivery Source を複数の配信先に紐付け、並行して配信できます。
3つの配信先に届いたログを確認する
ALB に HTTP と HTTPS でリクエストを送り、3つの配信先それぞれに届いたログを確認しました。OutputFormat はすべて json を指定しています。
S3 には次のキーでオブジェクトが作成されました。
AWSLogs/123456789012/elasticloadbalancing/access-logs/123456789012/ap-northeast-1/2026/07/27/
123456789012_elasticloadbalancing_ap-northeast-1_app.example-alb.0123456789abcdef_20260727T1450Z_198.51.100.10_0a1b2c3d.log.gz
先頭の AWSLogs/<アカウント ID>/elasticloadbalancing/ はサービス側が付与する部分です。S3SuffixPath に {account-id} を含めたため、1つのキーにアカウント ID が2回現れました。重複を避けるなら S3SuffixPath から {account-id} を外すとよいです。
S3 に届いたアクセスログ(HTTPS リクエスト)
{"request_line":"GET https://example-alb-1234567890.ap-northeast-1.elb.amazonaws.com:443/secure-1 HTTP/2.0","user_agent":"curl/8.18.0","trace_id":"Root=1-68a1b2c3-4d5e6f708192a3b4c5d6e7f8","domain_name":"example-alb-1234567890.ap-northeast-1.elb.amazonaws.com","chosen_cert_arn":"arn:aws:acm:ap-northeast-1:123456789012:certificate/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee","actions_executed":"forward","redirect_url":"-","error_reason":"-","target_port_list":"10.0.0.100:80","target_status_code_list":"404","classification":"-","classification_reason":"-","transformed_host":"-","transformed_uri":"-","request_transform_status":"-","type":"h2","time":"2026-07-27T14:51:41.522397Z","elb":"app/example-alb/0123456789abcdef","client_port":"203.0.113.10:4985","target_port":"10.0.0.100:80","request_processing_time":"0.002","target_processing_time":"0.002","response_processing_time":"0.000","elb_status_code":"404","target_status_code":"404","received_bytes":"79","sent_bytes":"3565","ssl_cipher":"ECDHE-RSA-AES128-GCM-SHA256","ssl_protocol":"TLSv1.2","target_group_arn":"arn:aws:elasticloadbalancing:ap-northeast-1:123456789012:targetgroup/example-tg/fedcba9876543210","matched_rule_priority":"0","request_creation_time":"2026-07-27T14:51:41.518000Z","conn_trace_id":"TID_a1b2c3d4e5f60718293a4b5c6d7e8f90","ip_address":"198.51.100.10"}
CloudWatch Logs では、テンプレートで作成したロググループ /aws/vendedlogs/alb-access-logs にレコードが届いていました。1レコードが1イベントとして格納されます。
CloudWatch Logs に届いたアクセスログ(HTTP リクエスト)
{"request_line":"GET http://example-alb-1234567890.ap-northeast-1.elb.amazonaws.com:80/ HTTP/1.1","user_agent":"curl/8.18.0","trace_id":"Root=1-68a1b2c3-4d5e6f708192a3b4c5d6e7f8","domain_name":"-","chosen_cert_arn":"-","actions_executed":"forward","redirect_url":"-","error_reason":"-","target_port_list":"10.0.0.100:80","target_status_code_list":"200","classification":"-","classification_reason":"-","transformed_host":"-","transformed_uri":"-","request_transform_status":"-","type":"http","time":"2026-07-27T14:47:06.948295Z","elb":"app/example-alb/0123456789abcdef","client_port":"203.0.113.10:4988","target_port":"10.0.0.100:80","request_processing_time":"0.002","target_processing_time":"0.003","response_processing_time":"0.000","elb_status_code":"200","target_status_code":"200","received_bytes":"133","sent_bytes":"296","ssl_cipher":"-","ssl_protocol":"-","target_group_arn":"arn:aws:elasticloadbalancing:ap-northeast-1:123456789012:targetgroup/example-tg/fedcba9876543210","matched_rule_priority":"0","request_creation_time":"2026-07-27T14:47:06.943000Z","conn_trace_id":"TID_a1b2c3d4e5f60718293a4b5c6d7e8f90","ip_address":"198.51.100.11"}
Firehose 配信は、ストリームの後段に指定した S3 のオブジェクト(firehose/access-logs/2026/07/27/14/ 配下)で確認しました。レコードのフィールド構成は他の配信先と同じです。
Firehose 経由で S3 に届いたアクセスログ(HTTPS リクエスト)
{"request_line":"GET https://example-alb-1234567890.ap-northeast-1.elb.amazonaws.com:443/secure-13 HTTP/2.0","user_agent":"curl/8.18.0","trace_id":"Root=1-68a1b2c3-4d5e6f708192a3b4c5d6e7f8","domain_name":"example-alb-1234567890.ap-northeast-1.elb.amazonaws.com","chosen_cert_arn":"arn:aws:acm:ap-northeast-1:123456789012:certificate/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee","actions_executed":"forward","redirect_url":"-","error_reason":"-","target_port_list":"10.0.0.100:80","target_status_code_list":"404","classification":"-","classification_reason":"-","transformed_host":"-","transformed_uri":"-","request_transform_status":"-","type":"h2","time":"2026-07-27T14:51:42.746886Z","elb":"app/example-alb/0123456789abcdef","client_port":"203.0.113.10:4985","target_port":"10.0.0.100:80","request_processing_time":"0.000","target_processing_time":"0.000","response_processing_time":"0.000","elb_status_code":"404","target_status_code":"404","received_bytes":"79","sent_bytes":"3565","ssl_cipher":"ECDHE-RSA-AES128-GCM-SHA256","ssl_protocol":"TLSv1.2","target_group_arn":"arn:aws:elasticloadbalancing:ap-northeast-1:123456789012:targetgroup/example-tg/fedcba9876543210","matched_rule_priority":"0","request_creation_time":"2026-07-27T14:51:42.746000Z","conn_trace_id":"TID_a1b2c3d4e5f60718293a4b5c6d7e8f90","ip_address":"198.51.100.10"}
S3 に届いた接続ログでは、HTTPS リスナー宛(listener_port が 443)のレコードで tls_protocol や tls_cipher に値が入っていました。
{"leaf_client_cert_subject":"-","time":"2026-07-27T14:47:07.123363Z","client_ip":"203.0.113.10","client_port":"4985","listener_port":"443","tls_protocol":"TLSv1.2","tls_cipher":"ECDHE-RSA-AES128-GCM-SHA256","tls_handshake_latency":"0.015","leaf_client_cert_validity":"-","leaf_client_cert_serial_number":"-","tls_verify_status":"Success","conn_trace_id":"TID_a1b2c3d4e5f60718293a4b5c6d7e8f90","tls_keyexchange":"secp256r1","elb":"app/example-alb/0123456789abcdef","ip_address":"198.51.100.10"}
今回、ALB の対象ログタイプについて describe-configuration-templates で確認したところ、配信先タイプごとの OutputFormat に指定できる値は次のとおりでした。
| 配信先 | 選択可能なフォーマット |
|---|---|
| S3 | plain / json / w3c / parquet |
| CloudWatch Logs | plain / json |
| Firehose | plain / json / raw |
この検証では ALB と EC2、Firehose 配信ストリーム、CloudWatch Logs と Firehose 宛の Vended Logs 配信、S3 と CloudWatch Logs の保管に対して課金が発生し得ます。ALB の統合ログ記録から S3 への配信自体は無料です。確認後はスタックを削除しました。
RecordFields を指定するときの注意点
AWS::Logs::Delivery の RecordFields では出力するフィールドを指定できます。今回 ap-northeast-1 で確認した ALB の3ログタイプでは、全フィールドが必須でした。そのため、この時点の構成では RecordFields は実質的に出力順の制御にしか使えません。ALB の3ログタイプについて aws logs describe-configuration-templates で確認したフィールド定義は次のとおりです。
| ログタイプ | フィールド数 | うち mandatory |
|---|---|---|
| ALB_ACCESS_LOGS | 34 | 34 |
| ALB_CONNECTION_LOGS | 15 | 15 |
| ALB_HEALTH_CHECK_LOGS | 10 | 10 |
いずれのログタイプも全フィールドが mandatory: true でした。この時点で確認した構成では、フィールドの取捨選択はできません。
実際に ALB_HEALTH_CHECK_LOGS の10フィールドのうち time と status_code の2つだけを指定してデプロイしたところ、スタックイベントの ResourceStatusReason は次のエラーになりました。
Resource handler returned message: "Mandatory record fields are missing
(Service: CloudWatchLogs, Status Code: 400, Request ID: aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee)"
(HandlerErrorCode: InvalidRequest)
同じ指定を aws logs create-delivery で実行した場合も同様に失敗しました。
An error occurred (ValidationException) when calling the CreateDelivery operation:
Mandatory record fields are missing
RecordFields を書かなければ、サービス既定のフィールドセットと順序で出力されます。今回確認した構成ではフィールドの取捨選択はできないため、テンプレート上の選択肢は「全フィールドを列挙して順序を制御する」か「RecordFields プロパティ自体を書かない」の2つです。
残る用途は出力順の制御です。掲載したテンプレートとは別に、OutputFormat が plain の Destination と RecordFields を列挙した Delivery を追加し、ALB_HEALTH_CHECK_LOGS の10フィールドを公式の既定順と入替順でそれぞれ配信しました。
| Delivery ID | 配信先ロググループ | フォーマット | RecordFields |
|---|---|---|---|
| kkkk1111llll2222 | /aws/vendedlogs/alb-hc-plain-default | plain | 10項目・デフォルト順 |
| mmmm3333nnnn4444 | /aws/vendedlogs/alb-hc-plain-reordered | plain | 10項目・入替順 |
| oooo5555pppp6666 | /aws/vendedlogs/alb-hc-json-reordered | json | 10項目・入替順 |
指定した順序は次のとおりです。
デフォルト順: type, time, latency, target_addr, target_group_id, status, status_code, reason_code, elb, ip_address
入替順: status_code, reason_code, status, time, type, latency, target_addr, target_group_id, elb, ip_address
以下は time が一致する同一レコードです。
plain / デフォルト順
http 2026-07-27T14:45:17.556303Z 0.00587012 10.0.0.100:80 example-tg PASS 200 - app/example-alb/0123456789abcdef 198.51.100.11
plain / 入替順
200 - PASS 2026-07-27T14:45:17.556303Z http 0.00587012 10.0.0.100:80 example-tg app/example-alb/0123456789abcdef 198.51.100.11
json / 入替順
{"status_code":"200","reason_code":"-","status":"PASS","time":"2026-07-27T14:45:17.556303Z","type":"http","latency":"0.00587012","target_addr":"10.0.0.100:80","target_group_id":"example-tg","elb":"app/example-alb/0123456789abcdef","ip_address":"198.51.100.11"}
plain では指定した順序どおりに列が並び替わり、1列目が http(type)から 200(status_code)に変わりました。plain は列名を持たないため、列番号で読むパーサーがあると値の対応が崩れます。公式の既定順を前提に列番号で読む既存のパーサーがある場合は、RecordFields の順序を公式ドキュメントや describe-configuration-templates の記述に揃える必要があります。
今回確認した JSON 出力でも、キーは指定順に出現しました。ただし、利用側ではキーの出現順に依存せず、キー名で参照します。json の既定順の出力は掲載を省略しています。
まとめ
ALB の CloudWatch Logs 統合ログ記録は、CloudFormation の3リソースを組み合わせて IaC 管理できました。S3 への保管を維持しつつ、監視や後段処理の用途で配信先を広げたい場面で選択肢に入ります。ALB の CloudWatch Logs 統合のログ設定を別スタックで管理する方法や、クロスアカウントで管理する方法についても、別途検証する予定です。







