ALB のアクセスログを出力する S3バケットは ALB と同じリージョンに存在する必要がある
お久しぶりです。岩城です。
皆さん、マルチリージョンで動くワークロードのログを 1 つの S3 バケットに集約したいと思うことはありませんか。
私はありまして、大阪リージョンで動いている ALB のアクセスログを大阪リージョンの S3 バケットに集約しようとして失敗しました。
ALB の仕様が関係していたので、原因と回避策を紹介したいと思います。
まとめ
- ALB のアクセスログの出力先バケットは、同じリージョンに存在しなければなりません
- ALB の公式ドキュメントに記載を見つけられなかったのですが、API リファレンスには記載があります
The S3 bucket must exist in the same Region as the load balancer and must have a bucket policy that grants Elastic Load Balancing permissions to write to the bucket.
(機械翻訳)
S3 バケットはロードバランサーと同じリージョンに存在し、Elastic Load Balancing によるバケットへの書き込みを許可するバケットポリシーが設定されている必要があります。
- 考えられる対応
| 対応案 | 構成 | 料金 | 難易度 | 備考 |
|---|---|---|---|---|
| リージョンごとに集約バケットを用意 | 各リージョンの ALB が、それぞれ同一リージョンのバケットにログを保持する(1 つには集約しない) | 各リージョンのストレージ料のみ。クロスリージョン転送は発生しない | 低 | 構成がシンプルで安価。ただし集約されないため、横断的に見るには各バケットを個別に参照する必要がある |
| S3 クロスリージョンレプリケーション(CRR) | ALB が東京の S3 バケットへログを配信し、CRR が大阪の S3 バケットへレプリケーションする | 各リージョンのストレージ料、CRR の前提となるバージョニングによる追加のストレージ料、クロスリージョン転送料が掛かる | 低〜中 | マネージドで運用しやすい。送信元と送信先の両方でバージョニングが必須 |
| S3 イベント通知と Lambda | ALB が東京の S3バケットへログを配信し、ObjectCreated で Lambda を起動して大阪の S3 バケットへコピーする |
クロスリージョン転送料、Lambda 実行料、両バケットのストレージ料が掛かる | 中 | コピー時にプレフィックス変換や絞り込みができる。ログ数が多いと呼び出しと転送のコストが増え、Lambda の運用と監視も必要になる |
それでは、検証してみましょう。
ALB と別リージョンの S3 バケットに出力できないことを確認する
下図のような検証環境を作りました。

東京リージョンの ALB のアクセスログを、大阪リージョンの S3 バケットに出力するように設定してみます。
同じリージョンに存在する S3 バケットを指定していないためエラーになりました。
~ $ aws elbv2 modify-load-balancer-attributes \
> --region ap-northeast-1 \
> --load-balancer-arn arn:aws:elasticloadbalancing:ap-northeast-1:xxxxxxxxxxxx:loadbalancer/app/devio-iwaki-alb/5449dd9807b7d76c \
> --attributes \
> Key=access_logs.s3.enabled,Value=true \
> Key=access_logs.s3.bucket,Value=devio-iwaki-s3-osaka-xxxxxxxxxxxx
aws: [ERROR]: An error occurred (InvalidConfigurationRequest) when calling the ModifyLoadBalancerAttributes operation: S3Bucket: devio-iwaki-s3-osaka-xxxxxxxxxxxx is not located in the same region with ELB: app/devio-iwaki-alb/5449dd9807b7d76c
当然、同じリージョンに存在する S3 バケットを指定すれば、問題なく設定できます。
~ $ aws elbv2 modify-load-balancer-attributes \
> --region ap-northeast-1 \
> --load-balancer-arn arn:aws:elasticloadbalancing:ap-northeast-1:xxxxxxxxxxxx:loadbalancer/app/devio-iwaki-alb/5449dd9807b7d76c \
> --attributes \
> Key=access_logs.s3.enabled,Value=true \
> Key=access_logs.s3.bucket,Value=devio-iwaki-s3-tokyo-xxxxxxxxxxxx
{
"Attributes": [
{
"Key": "access_logs.s3.enabled",
"Value": "true"
},
{
"Key": "access_logs.s3.bucket",
"Value": "devio-iwaki-s3-tokyo-992031286038"
},
{
"Key": "access_logs.s3.prefix",
"Value": ""
},
(~省略~)
]
}
(END)
ALB が存在するリージョンごとに S3 バケットを用意するのでも良いですが、ログは 1 箇所に集約したいじゃないですか。
なので、東京リージョンの S3 バケットから大阪リージョンの S3 バケットにクロスリージョンレプリケーションして、1 箇所に集約する構成にします。
S3 バケットのクロスリージョンレプリケーションを使って 1 箇所にログを集約する
以下のような構成で東京リージョンから大阪リージョンの S3 バケットにアクセスログをコピーする構成を試してみました。

レプリケーション元と先の S3 バケットの設定が気になる方は CFn テンプレートを確認してください。
レプリケーション元(東京)の CFn テンプレート
AWSTemplateFormatVersion: "2010-09-09"
Description: >
CRR verification - Tokyo (ap-northeast-1) SOURCE bucket.
Receives ALB access logs (same-region requirement satisfied) and replicates
ALL objects to the Osaka destination bucket via S3 Cross-Region Replication.
Source objects are expired quickly by a lifecycle rule to minimize cost.
Parameters:
DestinationBucketArn:
Type: String
Description: ARN of the Osaka destination bucket (from the crr-osaka-dest stack output).
SourceExpireDays:
Type: Number
Default: 7
Description: Days after which current-version objects in the Tokyo source bucket expire.
Resources:
SourceBucket:
Type: AWS::S3::Bucket
DeletionPolicy: Delete
UpdateReplacePolicy: Delete
Properties:
BucketName: !Sub "devio-iwaki-s3-tokyo-${AWS::AccountId}"
VersioningConfiguration:
Status: Enabled
PublicAccessBlockConfiguration:
BlockPublicAcls: true
BlockPublicPolicy: true
IgnorePublicAcls: true
RestrictPublicBuckets: true
OwnershipControls:
Rules:
- ObjectOwnership: BucketOwnerEnforced
LifecycleConfiguration:
Rules:
# Keep the source lean: expire current objects quickly (they are already
# replicated to Osaka), and clean up old versions and stale uploads.
- Id: expire-current-objects
Status: Enabled
ExpirationInDays: !Ref SourceExpireDays
- Id: expire-noncurrent-versions
Status: Enabled
NoncurrentVersionExpiration:
NoncurrentDays: 3
- Id: abort-incomplete-multipart
Status: Enabled
AbortIncompleteMultipartUpload:
DaysAfterInitiation: 3
ReplicationConfiguration:
Role: !GetAtt ReplicationRole.Arn
Rules:
- Id: replicate-all-to-osaka
Status: Enabled
Priority: 0
Filter: {} # empty filter = ALL objects
DeleteMarkerReplication:
Status: Disabled # keep objects on destination even if deleted at source
Destination:
Bucket: !Ref DestinationBucketArn
# Bucket policy for ALB access log delivery (same as the same-region setup).
SourceBucketPolicy:
Type: AWS::S3::BucketPolicy
Properties:
Bucket: !Ref SourceBucket
PolicyDocument:
Version: "2012-10-17"
Statement:
- Sid: AllowELBLogDelivery
Effect: Allow
Principal:
Service: logdelivery.elasticloadbalancing.amazonaws.com
Action: s3:PutObject
Resource: !Sub "arn:aws:s3:::${SourceBucket}/AWSLogs/${AWS::AccountId}/*"
# IAM role assumed by S3 to perform replication.
ReplicationRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Sub "devio-iwaki-role-crr-${AWS::AccountId}"
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
Service: s3.amazonaws.com
Action: sts:AssumeRole
Policies:
- PolicyName: devio-iwaki-crr-policy
PolicyDocument:
Version: "2012-10-17"
Statement:
# Read source objects + replication metadata
- Effect: Allow
Action:
- s3:GetReplicationConfiguration
- s3:ListBucket
Resource: !Sub "arn:aws:s3:::devio-iwaki-s3-tokyo-${AWS::AccountId}"
- Effect: Allow
Action:
- s3:GetObjectVersionForReplication
- s3:GetObjectVersionAcl
- s3:GetObjectVersionTagging
Resource: !Sub "arn:aws:s3:::devio-iwaki-s3-tokyo-${AWS::AccountId}/*"
# Write replicas to the destination bucket
- Effect: Allow
Action:
- s3:ReplicateObject
- s3:ReplicateDelete
- s3:ReplicateTags
Resource: !Sub "${DestinationBucketArn}/*"
Outputs:
SourceBucketName:
Description: Name of the Tokyo source bucket (set this as the ALB access log bucket)
Value: !Ref SourceBucket
ReplicationRoleArn:
Description: ARN of the replication IAM role
Value: !GetAtt ReplicationRole.Arn
レプリケーション先(大阪)の CFn テンプレート
AWSTemplateFormatVersion: "2010-09-09"
Description: >
CRR verification - Osaka (ap-northeast-3) DESTINATION bucket.
Receives replicated objects from the Tokyo source bucket via S3 Cross-Region
Replication. Versioning enabled (required for replication target).
Resources:
DestinationBucket:
Type: AWS::S3::Bucket
DeletionPolicy: Delete
UpdateReplacePolicy: Delete
Properties:
BucketName: !Sub "devio-iwaki-s3-osaka-repl-${AWS::AccountId}"
VersioningConfiguration:
Status: Enabled
PublicAccessBlockConfiguration:
BlockPublicAcls: true
BlockPublicPolicy: true
IgnorePublicAcls: true
RestrictPublicBuckets: true
OwnershipControls:
Rules:
- ObjectOwnership: BucketOwnerEnforced
LifecycleConfiguration:
Rules:
# Keep costs low: expire noncurrent versions quickly on the destination.
- Id: expire-noncurrent-versions
Status: Enabled
NoncurrentVersionExpiration:
NoncurrentDays: 7
- Id: abort-incomplete-multipart
Status: Enabled
AbortIncompleteMultipartUpload:
DaysAfterInitiation: 3
Outputs:
DestinationBucketName:
Description: Name of the Osaka destination bucket
Value: !Ref DestinationBucket
DestinationBucketArn:
Description: ARN of the Osaka destination bucket (use as ReplicationDestinationArn in the Tokyo stack)
Value: !GetAtt DestinationBucket.Arn
レプリケーション元の S3 バケットに作成されたアクセスログ(TestFile)が大阪リージョンにレプリケーションされましたね。


ログのタイムスタンプを見ると同時刻なのでリアルタイムでレプリケーションされていると思いがちですが、ここには注意が必要です。
メタデータを保持してレプリケーションされるので、ログのタイムスタンプは同一になります。しかし、レプリケーションはリアルタイムではありません。
ほとんどのレプリケーションは 15 分以内に完了しますが、場合によってはレプリケーションに最大 48 時間かかることがあります。
どうしても 15 分以内にログをレプリケーションさせたい場合は、S3 レプリケーションタイムコントロール (S3 RTC) の利用を検討してください。
S3 Replication Time Control (S3 RTC)を使用してコンプライアンス要件を満たす - Amazon Simple Storage Service
わざわざ S3 イベント通知 + Lambda など別の仕組みを使ってコピーしなくても、マネージドな機能で実現できるのが良いですね。
さいごに
ALB のアクセスログは同一リージョンの S3 バケットにしか出力できない、というのは意外と見落としがちなポイントでした。
今回は東京リージョンにもログ集約バケットを作り、リージョンごとに集約先を分けました。どうしても 1 つのバケットに集約したい場合は CRR が手軽ですが、クロスリージョンの転送料が乗るので、ログの保持期間やライフサイクル設定とあわせて検討するのが良さそうです。
どなたかのお役に立てれば幸いです。






