ALBログの新機能「CloudWatch Logs統合」でS3配信のコストを確認してみた
はじめに
2026年7月23日、ALBのログ記録がCloudWatch Logsの配信機能(Vended Logs)に統合されるアップデートがありました。
先行記事では、CloudWatch Logsへのログ出力について紹介しています。
本記事では、CloudWatch Logs統合でALBログをS3へ配信した場合のコストへの影響を確認しました。
なお本記事では、ALBの属性(access_logs.s3.* など)で設定する従来のS3出力を「レガシー設定」と呼びます。
検証内容
今回は、ALBのヘルスチェックログを対象にしました。実アクセスの有無に左右されにくく、一定間隔でログが出力されるため、形式ごとのファイルサイズや出力件数を比較しやすいと考えたためです。
同じヘルスチェックログをJSON、plain、Parquetの3形式でS3へ並行配信し、ファイルサイズとCloudWatch Logs統合によるS3配信時のコストへの影響を確認しました。
検証環境
| 項目 | 値 |
|---|---|
| リージョン | ap-northeast-1 |
| ロードバランサー | Application Load Balancer 1台(<ALB_NAME>) |
| 対象ログタイプ | ALB_HEALTH_CHECK_LOGS |
| ログ項目数 | 10項目 |
| ヘルスチェック間隔 | 30秒 |
| ログファイルの出力間隔 | 5分(ALBノードごと) |
| 出力形式 | JSON / plain(スペース区切り) / Parquet |
| 計測期間 | 2026-07-22 〜 2026-07-27(S3への配信設定は07-24に実施) |
今回の比較では、宛先の違いによる影響を避けるため、3形式を同一のS3バケット <LOG_BUCKET> へ配信し、形式ごとにプレフィックスだけを分けました。
以降のサイズ・コストの数値は、すべてヘルスチェックログによるものです。
フォーマット別の比較
ファイルサイズ
同じ時刻・同じALBノードから出力された、10レコードのファイルを1組抽出して比較しました。
| フォーマット | ファイルサイズ | 1レコードあたり換算 | plain比(%) |
|---|---|---|---|
| plain(gz) | 283 B | 28.3 B | 100% |
| JSON(gz) | 393 B | 39.3 B | 139% |
| Parquet(内部GZIP) | 4,042 B | 404.2 B | 1,429% |
「1レコードあたり換算」は、圧縮後のファイルサイズを10レコードで割った参考値です。圧縮効率はレコード数によって変わるため、レコード数を増やしたときに比例するわけではありません。
plain(スペース区切り)
plainはレガシー設定と同じく、値をスペースで区切って並べる形式です。
http 2026-07-27T00:25:02.444270Z 0.022732728 <TARGET_IP>:3000 <TARGET_GROUP> PASS 200 - app/<ALB_NAME>/<ALB_ID> <ALB_NODE_IP>
JSON
JSONは1レコードが1行のオブジェクトとして出力されます。
{"type":"http","time":"2026-07-27T00:25:02.444270Z","latency":"0.022732728","target_addr":"<TARGET_IP>:3000","target_group_id":"<TARGET_GROUP>","status":"PASS","status_code":"200","reason_code":"-","elb":"app/<ALB_NAME>/<ALB_ID>","ip_address":"<ALB_NODE_IP>"}
フィールド数が異なれば比率も変わります(先行記事のアクセスログ計測ではJSONがplainの2.53倍)。
JSONはキーと値が対応するため、plainのように値の位置に依存せず扱えます。フィールド追加に備える場合は、JSONのほうが扱いやすいです。
Parquet
Parquetのファイルをpyarrowで読み取ると、メタデータの比率を確認できました。
- rows=10、row_groups=1、columns=10
- 圧縮方式はGZIP
- row groupのデータ部は1,070 B
- フッタとスキーマのメタデータは約2,972 B(ファイル全体の約73%)
今回のような5分間隔・10レコード規模の出力では、Parquetは適しません。メタデータが全体の約73%を占め、列指向形式による圧縮やスキャン範囲の絞り込みという利点よりも、ファイルサイズの大きさが目立ちました。加えて、公式発表ではParquet変換に別途料金がかかると案内されており、公式ブログで示されているバージニア北部の単価は$0.035/GBです。東京リージョンでも、S3保存用の形式としてこの規模で選ぶ理由は見当たりません。
今回の検証対象外ですが、Parquetで蓄積したい場合は、JSONやplainで配信したログをAthena CTASやGlue ETLでまとめて変換する方法もあります。1ファイルあたりのレコード数を増やせるため、小さなファイルをそのままParquetとして保存する場合より、メタデータの比率を抑えられます。
コストの実測
Cost Explorerで、ap-northeast-1の使用タイプ別使用量を日次で確認しました。設定前の2026-07-22・07-23と、設定翌日の2026-07-25を比較します。
| 日付 | S3記録 | APN1-VendedLog-Bytes 使用量(MB換算) |
|---|---|---|
| 2026-07-22 | なし | 10.57 |
| 2026-07-23 | なし | 10.75 |
| 2026-07-25 | あり | 10.73 |
Cost Explorerの APN1-VendedLog-Bytes をMB単位に換算して比較しました。CloudWatch Logs統合の設定後も、この使用タイプは設定前に観測した10.57〜10.75 MBの範囲内に収まりました。
なお、設定前から計上されている約10 MBは、同一アカウントで稼働しているVPCフローログに起因するものです。フローログのロググループにコスト配分タグを設定し、この使用タイプがフローログのみで発生していることを確認しています。今回のALBログ以外に、Vended Logs対象の配信は設定していません。
公式発表では、ALBログをAmazon S3へ配信する場合、配信は無料と案内されています。CloudWatch LogsおよびAmazon Data Firehose宛の配信はVended Logsとして課金されます。今回の APN1-VendedLog-Bytes の比較結果も、この料金体系と整合します。
設定手順(参考)
ここでは、今回のように同じログを複数形式でS3へ並行配信するための設定をまとめます。
CLIで3形式を並行配信する
Delivery Sourceは1つ作成し、JSON・plain・Parquet用にDelivery DestinationとDeliveryをそれぞれ作成します。
実運用で形式を切り替える場合は、既存ログとの混在を避けるため、可能であれば形式ごとにS3バケットを分けます。同じバケットを使う場合は、少なくともプレフィックスを分けます。
まず、ログの発生元となるDelivery Sourceを作成します。
aws logs put-delivery-source \
--name alb-health-check-logs \
--resource-arn arn:aws:elasticloadbalancing:ap-northeast-1:<ACCOUNT_ID>:loadbalancer/app/<ALB_NAME>/<ALB_ID> \
--log-type ALB_HEALTH_CHECK_LOGS
検証では、同じS3バケットを宛先とするDelivery Destinationを形式ごとに作成しました。--output-format だけを変えます。
aws logs put-delivery-destination \
--name alb-vended-logs-s3-json \
--output-format json \
--delivery-destination-configuration destinationResourceArn=arn:aws:s3:::<LOG_BUCKET>
aws logs put-delivery-destination \
--name alb-vended-logs-s3-plain \
--output-format plain \
--delivery-destination-configuration destinationResourceArn=arn:aws:s3:::<LOG_BUCKET>
aws logs put-delivery-destination \
--name alb-vended-logs-s3-parquet \
--output-format parquet \
--delivery-destination-configuration destinationResourceArn=arn:aws:s3:::<LOG_BUCKET>
最後にDeliveryで紐付けます。形式ごとに宛先ARNと suffixPath を変え、同じバケット内で出力が混ざらないようにします。
aws logs create-delivery \
--delivery-source-name alb-health-check-logs \
--delivery-destination-arn arn:aws:logs:ap-northeast-1:<ACCOUNT_ID>:delivery-destination:alb-vended-logs-s3-json \
--s3-delivery-configuration 'suffixPath=health-check-logs/json/{region}/{yyyy}/{MM}/{dd}/'
plainとParquetも同様に、宛先ARNと suffixPath を変えて create-delivery を実行します。
S3バケットポリシー
S3を宛先にする場合は、delivery.logs.amazonaws.com に次の権限を付与します。
- オブジェクト書き込み(
s3:PutObject) - バケットACL取得(
s3:GetBucketAcl)
{
"Effect": "Allow",
"Principal": {
"Service": "delivery.logs.amazonaws.com"
},
"Action": "s3:PutObject",
"Resource": "arn:aws:s3:::<LOG_BUCKET>/*",
"Condition": {
"StringEquals": {
"aws:SourceAccount": "<ACCOUNT_ID>"
}
}
}
{
"Effect": "Allow",
"Principal": {
"Service": "delivery.logs.amazonaws.com"
},
"Action": "s3:GetBucketAcl",
"Resource": "arn:aws:s3:::<LOG_BUCKET>",
"Condition": {
"StringEquals": {
"aws:SourceAccount": "<ACCOUNT_ID>"
}
}
}
今回は検証を簡略化するため、いずれのステートメントも条件を aws:SourceAccount のみにし、aws:SourceArn は指定していません。実運用では、配信元を限定するために aws:SourceArn も併せて指定することをおすすめします。
レガシー設定からCloudWatch Logs統合へ移行する理由
前述のとおり、CloudWatch Logs統合でALBログをS3へ配信する場合、Vended Logsの配信料金はかかりません。S3の保存料金とリクエスト料金は従来どおり発生します。今回のように複数形式を並行配信すると、PutObject のリクエスト数は形式の数に比例して増える点に注意してください。
ログ配信の定義をALB属性から分離できます。今回の検証でも、ALBのログ関連属性はすべて無効のままでしたが、CloudWatch Logs側で定義したDeliveryを通じてS3へログを配信できました。
コストを優先してログの保存先をS3に絞る構成でも、新方式ならCloudWatch Logsのロググループ宛の配信を必要に応じて追加できます。Logs Insightsによる検索やニアリアルタイムの確認が使えるため、イベント発生時や障害調査に役立ちます。
ロググループへの追加配信にはCloudWatch Logs側の料金が発生します。常時はS3のみに保存し、イベント実施前や障害の再現期間だけロググループへの配信を追加する使い方もできます。必要に応じてご検討ください。
まとめ
S3へALBログを保存する新規構築では、CloudWatch Logs統合を第一候補と考えます。S3への配信ではVended Logsの配信料金がかからず、出力形式を選べるほか、必要になればロググループへの配信を追加してLogs Insightsで調査できます。
形式は、容量を優先するならplain、フィールドの追加やプログラムからの取り扱いを見込むならJSONが扱いやすいです。
既存のレガシー設定を利用している環境も、ログ解析環境をメンテナンスできるタイミングで見直すのがおすすめです。レガシー設定を有効にしたまま、別の出力先に新しいログ配信を設定します。ログ解析やログ処理パイプラインの動作を確認してからレガシー設定を無効化すれば、安全に切り替えられます。







