🎃

[AWS CDK] S3ライフサイクルルールでExpirationとTransitionの日数設定エラーを解決する方法

に公開

AWS CDKでS3バケットのライフサイクルルールを設定してデプロイを実行したところ、以下のエラーが発生しました。

Resource handler returned message: "'Days' in the Expiration action for filter '(prefix=)' must be greater than 'Days' in the Transition action (Service: S3, Status Code: 400, Request ID: MJMZYYAYPWD8PCAY...)

このエラーメッセージから分かることは、S3のライフサイクルルールにおいて「Expiration(削除)」の日数が「Transition(ストレージクラス移行)」の日数より大きくなければならない、という制約に違反していることです。

問題の原因を理解する

S3のライフサイクルルールでは、オブジェクトに対して以下のような処理を段階的に実行できます。

  1. 標準ストレージで保存開始
  2. 指定日数後に低頻度アクセスストレージクラスへ移行
  3. さらに指定日数後にGlacierへ移行
  4. 最終的に指定日数後にオブジェクトを削除

重要なのは、これらの処理は時系列順に実行される必要があることです。つまり、削除日数は必ず移行日数より後でなければなりません。

実際のコード例で問題を確認

今回問題となったコードは以下のような設定でした。

lifecycleRules: [
  {
    id: 'DeleteOldReports',
    enabled: true,
    transitions: [
      {
        storageClass: s3.StorageClass.INFREQUENT_ACCESS,
        transitionAfter: cdk.Duration.days(30),
      },
      {
        storageClass: s3.StorageClass.GLACIER,
        transitionAfter: cdk.Duration.days(90),
      },
    ],
    expiration: cdk.Duration.days(props.environment === 'production' ? 365 : 90),
  },
],

このコードの問題点は、本番環境以外ではexpirationが90日に設定されているのに対し、Glacierへの移行も90日に設定されていることです。

AWSでは削除日数が移行日数と同じ、または小さい場合にエラーが発生します。ファイルがGlacierに移行される前に削除されてしまうような設定は論理的に矛盾するためです。

エラーの解決方法

解決策はシンプルです。削除日数を移行日数よりも大きい値に設定します。

lifecycleRules: [
  {
    id: 'DeleteOldReports',
    enabled: true,
    transitions: [
      {
        storageClass: s3.StorageClass.INFREQUENT_ACCESS,
        transitionAfter: cdk.Duration.days(30),
      },
      {
        storageClass: s3.StorageClass.GLACIER,
        transitionAfter: cdk.Duration.days(90),
      },
    ],
    // 90日より大きい値に修正
    expiration: cdk.Duration.days(props.environment === 'production' ? 365 : 120),
  },
],

この修正により、開発環境では以下のような流れになります。

  • 30日後:低頻度アクセスストレージクラスへ移行
  • 90日後:Glacierへ移行
  • 120日後:オブジェクト削除

これで論理的に一貫した設定となり、エラーが解消されます。

よくある間違いパターン

ライフサイクルルール設定でよく見かける間違いパターンをいくつか紹介しておきます。

パターン1: 削除日数が移行日数と同じ

// NGパターン
transitions: [
  {
    storageClass: s3.StorageClass.GLACIER,
    transitionAfter: cdk.Duration.days(90),
  },
],
expiration: cdk.Duration.days(90), // 同じ日数でエラー

パターン2: 削除日数が移行日数より小さい

// NGパターン  
transitions: [
  {
    storageClass: s3.StorageClass.GLACIER,
    transitionAfter: cdk.Duration.days(90),
  },
],
expiration: cdk.Duration.days(60), // 移行前に削除されてしまう

パターン3: 複数の移行設定がある場合

// NGパターン
transitions: [
  {
    storageClass: s3.StorageClass.INFREQUENT_ACCESS,
    transitionAfter: cdk.Duration.days(30),
  },
  {
    storageClass: s3.StorageClass.GLACIER,
    transitionAfter: cdk.Duration.days(90),
  },
],
expiration: cdk.Duration.days(90), // 最後の移行と同じ日数でエラー

複数の移行設定がある場合は、最後の移行日数より大きい値を削除日数に設定する必要があります。

まとめ

S3のライフサイクルルール設定では、削除日数は必ず移行日数より大きく設定する必要があります。今回のケースのように、開発環境で短期間の設定を行う場合でも、移行と削除の順序は守らなければなりません。

このエラーに遭遇した際は、まずライフサイクルルールの設定を見直し、移行と削除の日数関係を確認してください。適切な日数設定により、コスト効率的でありながら運用しやすいストレージ戦略を実現できます。

デジタルキューブ

Discussion