S3ライフサイクルルールの動きを理解してみた

2022.12.23

S3ライフサイクルルールでオブジェクトがいつ消えるのか度々わからなくなるのでブログに残しました。

ライフサイクルルールとは

S3に入っているオブジェクトを違うストレージクラスに移動したり、設定した期間で削除したりするときに使用する設定になります。
ライフサイクルルールの公式ドキュメントは以下になります。
ストレージのライフサイクルの管理

オブジェクトが消えるタイミング

今回のテーマはライフサイクルルールでオブジェクトが消えるタイミングについてです。
以下の公式ドキュメントではこのように記載されています。
ライフサイクルルール: オブジェクトの存在時間に基づく

  • アクションが実行される、オブジェクト作成からの日数です。
  • Amazon S3 は、ルールに指定された日数をオブジェクトの作成時間に加算し、得られた日時を翌日の午前 00:00 UTC (協定世界時) に丸めることで、時間を算出します。たとえば、あるオブジェクトが 2014 年 1 月 15 日午前 10 時 30 分 (UTC) に作成され、移行ルールに 3 日と指定した場合、オブジェクトの移行日は 2014 年 1 月 19 日 0 時 0 分 (UTC) となります。

理解しにくい文章ですが、日本時間で考えると午前9時が対象の時間になるようです。
ただし以下のドキュメントにも記載されている通り、丁度午前9時に削除されるわけではなくキューに追加されて非同期で削除されるのでオブジェクトが消えるまでに遅延があります。
オブジェクトの有効期限

消えるタイミングを見てみた

ライフサイクルルールでのオブジェクトの失効アクションはアクセスログで確認できるので、アクセスログ、ライフサイクルルールを設定したS3バケットを作成しました。
ライフサイクルとログ記録

S3バケットの作成は以下のCloudFormationテンプレートを使用しています。

AWSTemplateFormatVersion: "2010-09-09"

Description: S3 Stack

Resources:
# ------------------------------------------------------------#
# S3
# ------------------------------------------------------------# 
  AccessLogS3:
    Type: AWS::S3::Bucket
    Properties: 
      BucketEncryption: 
        ServerSideEncryptionConfiguration: 
          - ServerSideEncryptionByDefault:
              SSEAlgorithm: AES256
      BucketName: !Sub ${AWS::StackName}-${AWS::AccountId}-accesslog
      PublicAccessBlockConfiguration:
        BlockPublicAcls: True
        BlockPublicPolicy: True
        IgnorePublicAcls: True
        RestrictPublicBuckets: True

  S3:
    DependsOn: AccessLogS3
    Type: AWS::S3::Bucket
    Properties: 
      BucketEncryption: 
        ServerSideEncryptionConfiguration: 
          - ServerSideEncryptionByDefault:
              SSEAlgorithm: AES256
      BucketName: !Sub ${AWS::StackName}-${AWS::AccountId}
      LifecycleConfiguration: 
        Rules:
          - ExpirationInDays: 1
            Id: Delete-Rule
            Status: Enabled
      LoggingConfiguration: 
        DestinationBucketName: !Ref AccessLogS3
      PublicAccessBlockConfiguration:
        BlockPublicAcls: True
        BlockPublicPolicy: True
        IgnorePublicAcls: True
        RestrictPublicBuckets: True

  BucketPolicy:
    Type: AWS::S3::BucketPolicy
    Properties: 
      Bucket: !Ref AccessLogS3
      PolicyDocument: 
        Version: "2012-10-17"
        Statement: 
          - Sid: "S3ServerAccessLogsPolicy"
            Effect: "Allow"
            Principal: 
              Service: "logging.s3.amazonaws.com"
            Action: 
              - "s3:PutObject"
            Resource: !Join 
              - ''
              - - 'arn:aws:s3:::'
                - !Ref AccessLogS3
                - /*
            Condition: 
              ArnLike: 
                'aws:SourceArn': !GetAtt S3.Arn
              StringEquals: 
                'aws:SourceAccount': !Sub ${AWS::AccountId}

上記のテンプレートはS3バケットを2つ作成するものになります。
9行目から21行目までの定義でS3のアクセスログを格納する用のS3バケットを作成します。
23行目から43行目までの定義でライフサイクルルールを使用したS3バケットを作成しています。
またライフサイクルルールの設定は32行目から36行目で行っていて、ExpirationInDays (削除する日数)は1日にしています。
45行目から67行目でアクセスログ格納用S3のバケットポリシーを作成しています。

バケットポリシーは以下のドキュメントを参考にしています。
ログ配信許可

CloudFormationの実行はAWS CLIで行いました。
以下のコマンドを実行してください。

aws cloudformation create-stack --stack-name スタック名 --template-body file://CloudFormationテンプレートファイル名

S3バケットの作成が完了したらS3バケットにテキストファイルなどを格納します。
S3バケットへのファイル格納は以下のコマンドで行います。

aws s3 cp 格納するファイル名 s3://S3バケット名

ファイルを格納してしばらくすると、アクセスログ格納用S3バケットにログが出力されます。

今回はテスト用ファイルを2022/12/20 18:45に保存したので2022/12/22 9:00以降に削除されることを確認します。

S3バケットに格納したファイルが消えたことを確認したらアクセスログを確認していきます。
今回はアクセスログがあまり出力されていなかったのでAthenaを利用せずS3 Selectで確認しました。
S3アクセスログの形式は以下のドキュメントをご確認ください。
Amazon S3 サーバーアクセスログの形式

マネジメントコンソールからS3バケット一覧に移動します。
移動したらアクセスログ格納用S3バケットをクリックします。
上記のCloudFormationテンプレートで作成した場合は末尾に「accesslog」とついています。

画面が遷移したらオブジェクトを選択して「アクション」から「S3 Select を使用したクエリ」をクリックします。

「入力設定」、「出力設定」、「SQL クエリ」は変更せずに「SQL クエリの実行」をクリックします。
クリックすると「クエリ結果」に結果が出力されます。
今回出力された結果は以下になります。

{Bucket Owner} {バケット名} [22/Dec/2022:20:04:27 +0000] - {Remote IP} S3.EXPIRE.OBJECT test.txt "-" - - - 4 - - "-" "-" - {ホスト ID} - - - - - -

オペレーションが「S3.EXPIRE.OBJECT」になっているものがライフサイクルルールで削除されたものになります。
日時を見ると22日の20時 (日本時間だと23日の5時)に削除されたようです。

さいごに

バージョニング設定を有効にした場合は古いバージョンを消すルールを入れる必要があります。