3
1

CDKで既存のS3バケットを管理する

Last updated at Posted at 2023-11-22

概要

最近AWS CDKで環境構築する機会がありました。
その際に既存のS3バケットをCDKの管理下におく方法を調査したので共有させていただきます。
なお、今回はcdk importを使用して既存リソースをインポートしていきます。

準備

まず、CDKのプロジェクトを作成します。

mkdir cdk-import-bucket && cd cdk-import-bucket

cdk init sample-app -l typescript

lib/cdk-import-bucket-stack.tsを確認すると、SNSSQSのリソースを作成する記述があるので削除しておきます。

import { Stack, StackProps } from 'aws-cdk-lib';
import { Construct } from 'constructs';

export class CdkImportBucketStack extends Stack {
  constructor(scope: Construct, id: string, props?: StackProps) {
    super(scope, id, props);

  }
}

一度この状態でデプロイしてAWS上にCloudFormationのスタックを作成しておきます。

cdk deploy

次に、CDKでインポートするS3バケットを作成します。
手動で作成してもいいですが、今回はCloudFormationで作成してみます。

# sample-bucket.yaml
AWSTemplateFormatVersion: 2010-09-09

Resources:
  S3Bucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: sample-bucket-qwer
      AccessControl: Private
      BucketEncryption:
        ServerSideEncryptionConfiguration:
        - ServerSideEncryptionByDefault:
            SSEAlgorithm: AES256
      PublicAccessBlockConfiguration:
        BlockPublicAcls: true
        BlockPublicPolicy: true
        IgnorePublicAcls: true
        RestrictPublicBuckets: true
      OwnershipControls:
        Rules:
          - ObjectOwnership: BucketOwnerEnforced

デプロイ

aws cloudformation deploy --template-file sample-bucket.yaml --stack-name sample-bucket-stack

これでCDKで管理していないS3バケットの作成ができました。

cdk importしてみる

では、上記で作成したS3バケットをCDKの管理下にインポートしていきます。
まず、lib/cdk-import-bucket-stack.tsを下記のように変更してS3バケットの定義を追加します。

import { Stack, StackProps } from 'aws-cdk-lib';
import { Bucket } from 'aws-cdk-lib/aws-s3';
import { Construct } from 'constructs';

export class CdkImportBucketStack extends Stack {
  constructor(scope: Construct, id: string, props?: StackProps) {
    super(scope, id, props);

    new Bucket(this, 'ImportBucket', {})
  }
}

差分を確認してみます。

cdk diff

Stack CdkImportBucketStack
Resources
[+] AWS::S3::Bucket ImportBucket ImportBucketBAF3A8E9 

✨  Number of stacks with differences: 1

新しくS3バケットが作成されようとしているのがわかります。
ではここで定義したS3バケットに対し、cdk importで既存のリソースをインポートしてみます。

cdk import

CdkImportBucketStack
CdkImportBucketStack/ImportBucket/Resource (AWS::S3::Bucket): enter BucketName [undefined]: 

上記のようにインポートするバケット名を聞かれるので入力します。
すると失敗してしまいます。
これは、対象のS3バケットを作成したときにCloudFormationで作成したことが原因です。
すでにCloudFormationで管理されているリソースについてはcdk importができないようです。
なのでS3を作成したCloudFormationスタックを削除しましょう。
削除前にDeletionPolicyを修正して、スタックを削除してもS3バケットが削除されないようにします。

AWSTemplateFormatVersion: 2010-09-09

Resources:
  S3Bucket:
    Type: AWS::S3::Bucket
    DeletionPolicy: Retain  # 追加
    Properties:
      BucketName: sample-bucket-qwer
      AccessControl: Private
      BucketEncryption:
        ServerSideEncryptionConfiguration:
        - ServerSideEncryptionByDefault:
            SSEAlgorithm: AES256
      PublicAccessBlockConfiguration:
        BlockPublicAcls: true
        BlockPublicPolicy: true
        IgnorePublicAcls: true
        RestrictPublicBuckets: true
      OwnershipControls:
        Rules:
          - ObjectOwnership: BucketOwnerEnforced

DeletionPolicyを更新するためにデプロイ

aws cloudformation deploy --template-file sample-bucket.yaml --stack-name sample-bucket-stack

上記が成功したのちスタックの削除

aws cloudformation delete-stack --stack-name sample-bucket-stack

これでCloudFormationのスタックで管理されていないS3バケットが残りました。
もう一度cdk importしてみます。

cdk import
CdkImportBucketStack
CdkImportBucketStack/ImportBucket/Resource (AWS::S3::Bucket): enter BucketName [undefined]: sample-bucket-qwer
CdkImportBucketStack: importing resources into stack...
CdkImportBucketStack: creating CloudFormation changeset...

 ✅  CdkImportBucketStack
Import operation complete. We recommend you run a drift detection operation to confirm your CDK app resource definitions are up-to-date. Read more here: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/detect-drift-stack.html

成功しました!
マネージメントコンソールでスタックのステータスを確認するとIMPORT_COMPLETEになっています。
image.png

うまくいったようですが、cdk importを行った際の出力に気になるメッセージがありました。

We recommend you run a drift detection operation to confirm your CDK app resource definitions are up-to-date. Read more here: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/detect-drift-stack.html

「ドリフトの検出するのをお勧めするよ」と言われてます。
ドリフトとはこちらに書かれている通りなのですが、要はCloudFormationのスタックに定義されている構成と、実際のリソースの構成に差異がないかを検出するために使用されるものです。
なのでCloudFormationで管理しているリソースのプロパティを手動で変更した場合などの検出に使用できます。

今回で言うとCDKにインポートした定義と既存リソースの構成に差異がないかチェックしてねということのようです。

メッセージのURLにドリフト検出の方法が載っているのでそれ通りに進めたところ、ドリフトステータスがIN_SYNC(差分なし)となることを確認しました。
なので正常にインポートが完了したことになります。

プロパティの更新を試す

リソースのインポートができたので、試しにS3バケットのプロパティの更新も試してみます。
ライフサイクルルールを追加してみましょう。

import { Duration, Stack, StackProps } from 'aws-cdk-lib';
import { Bucket } from 'aws-cdk-lib/aws-s3';
import { Construct } from 'constructs';

export class CdkImportBucketStack extends Stack {
  constructor(scope: Construct, id: string, props?: StackProps) {
    super(scope, id, props);

    new Bucket(this, 'ImportBucket', {
      lifecycleRules: [
        {
          id: "DeleteExpiredData",
          enabled: true,
          expiration: Duration.days(30),
        }
      ]
    })
  }
}

差分の確認

cdk diff
Stack CdkImportBucketStack
Resources
[~] AWS::S3::Bucket ImportBucket ImportBucketBAF3A8E9 
 └─ [+] LifecycleConfiguration
     └─ {"Rules":[{"ExpirationInDays":30,"Id":"DeleteExpiredData","Status":"Enabled"}]}

✨  Number of stacks with differences: 1

想定した差分が確認できたのでデプロイ

cdk deploy

ライフサイクルルールが設定されたか確認してみます

aws s3api get-bucket-lifecycle-configuration --bucket sample-bucket-qwer

{
    "Rules": [
        {
            "Expiration": {
                "Days": 30
            },
            "ID": "DeleteExpiredData",
            "Filter": {
                "Prefix": ""
            },
            "Status": "Enabled"
        }
    ]
}

うまくいきました!

出力されたCloudFormationテンプレートでもプロパティが追加されていることを確認できます。
cdk.out > CdkImportBucketStack.template.json

{
 "Resources": {
  "ImportBucketBAF3A8E9": {
   "Type": "AWS::S3::Bucket",
   "Properties": {
    "LifecycleConfiguration": {
     "Rules": [
      {
       "ExpirationInDays": 30,
       "Id": "DeleteExpiredData",
       "Status": "Enabled"
      }
     ]
    }
   },

}

まとめ

CDKで既存のS3バケットをインポートする方法を紹介しました。
今回インポートの対象としたのはS3バケットでしたが、他のリソースでも同じような手順で実行できるのではないかと思います。
どなたかの参考になれば幸いです。

参考

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1