AWS CDK v2.90.0 で RemovalPolicy.RETAIN_EXCEPT_ON_CREATE が利用可能になりました

2023.08.06

こんにちは、CX事業本部 Delivery部の若槻です。

先週のアップデートで CloudFormation の新しい DeletionPolicy として RetainExceptOnCreate が使用できるようになりました。

これにより、作成後に DeletionPolicy を RETAIN としたいリソースの作成時のトライアンドエラーが簡単になります。

そして、昨日リリースされた AWS CDK v2.90.0 でも RemovalPolicy.RETAIN_EXCEPT_ON_CREATE がサポートされ、RetainExceptOnCreate が利用できるようになりました。

core: new RemovalPolicy.RETAIN_EXCEPT_ON_CREATE to only retain resources that have been successfully created (#26602) (c84666c), closes #26595

試してみる

今回はリソースの重複によりデプロイのロールバックを起こしみます。予め重複させるためのトピックを作成しておきます。

aws sns create-topic --name cdk-sample-topic

モジュールのアップデート

AWS CDK のモジュールを v2.90.0 以上にアップグレードします。

npm i aws-cdk@latest aws-cdk-lib@latest

RETAIN を使った場合

まず比較のために RETAIN を使った場合を試してみます。新規作成するロググループの RemovalPolicy に RETAIN を指定しています。また、新規作成するトピックは先程作成したのものと名前が重複するようにしています。

lib/cdk-sample-stack.ts

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

export class CdkSampleStack extends Stack {
  public readonly myFileObjectKey: string;

  constructor(scope: Construct, id: string, props: StackProps) {
    super(scope, id, props);

    new aws_logs.LogGroup(this, 'LogGroup', {
      logGroupName: '/aws/lambda/cdk-sample',
      removalPolicy: RemovalPolicy.RETAIN,
    });

    // 作成時にトピック名の重複によりデプロイがエラーになる
    new aws_sns.Topic(this, 'Topic', {
      topicName: 'cdk-sample-topic',
    });
  }
}

デプロイを行うと、予想通りエラーになりました。

$ cdk deploy

  Synthesis time: 2.6s

CdkSampleStack:  start: Building cafaa30c876810addfbaa2f01d3dd4e2ade0a14ca1c37f9e1bbbda5cc820599f:current_account-current_region
CdkSampleStack:  success: Built cafaa30c876810addfbaa2f01d3dd4e2ade0a14ca1c37f9e1bbbda5cc820599f:current_account-current_region
CdkSampleStack:  start: Publishing cafaa30c876810addfbaa2f01d3dd4e2ade0a14ca1c37f9e1bbbda5cc820599f:current_account-current_region
CdkSampleStack:  success: Published cafaa30c876810addfbaa2f01d3dd4e2ade0a14ca1c37f9e1bbbda5cc820599f:current_account-current_region
CdkSampleStack: deploying... [1/1]
CdkSampleStack: creating CloudFormation changeset...
[█████████▋················································] (2/12)

2:56:38 AM | CREATE_FAILED        | AWS::SNS::Topic     | Topic
Resource handler returned message: "Resource of type 'AWS::SNS::Topic' with identifier 'cdk-sample-top
ic' already exists." (RequestToken: bdbdbd39-3e57-74db-ea41-d533e4f31b36, HandlerErrorCode: AlreadyExi
sts)

そして、ロググループの存在を確認してみると、削除されずに残っています。RETAIN の設定が効いていますね。

$ aws logs describe-log-streams --log-group-name /aws/lambda/cdk-sample
{
    "logStreams": []
}

しかしこれだとロールバック時に削除されずに残ったリソースを手動で削除する必要があります。

RETAIN_ON_UPDATE_OR_DELETE を使った場合

次に RETAIN_ON_UPDATE_OR_DELETE を使った場合を試してみます。

先程作成されたロググループは手動で削除しておきます。

aws logs delete-log-group --log-group-name /aws/lambda/cdk-sample

新規作成するロググループの RemovalPolicy に RETAIN_ON_UPDATE_OR_DELETE を指定します。

lib/cdk-sample-stack.ts

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

export class CdkSampleStack extends Stack {
  public readonly myFileObjectKey: string;

  constructor(scope: Construct, id: string, props: StackProps) {
    super(scope, id, props);

    new aws_logs.LogGroup(this, 'LogGroup', {
      logGroupName: '/aws/lambda/cdk-sample',
      removalPolicy: RemovalPolicy.RETAIN_ON_UPDATE_OR_DELETE,
    });

    // 作成時にトピック名の重複によりデプロイがエラーになる
    new aws_sns.Topic(this, 'Topic', {
      topicName: 'cdk-sample-topic',
    });
  }
}

デプロイをすると、今回も予想通りエラーになりました。

$ cdk deploy

  Synthesis time: 3.03s

CdkSampleStack:  start: Building 62c9db75936dd4907ba305c5317188247dd8d9e7fe25784cd575e22cb835ede8:current_account-current_region
CdkSampleStack:  success: Built 62c9db75936dd4907ba305c5317188247dd8d9e7fe25784cd575e22cb835ede8:current_account-current_region
CdkSampleStack:  start: Publishing 62c9db75936dd4907ba305c5317188247dd8d9e7fe25784cd575e22cb835ede8:current_account-current_region
CdkSampleStack:  success: Published 62c9db75936dd4907ba305c5317188247dd8d9e7fe25784cd575e22cb835ede8:current_account-current_region
CdkSampleStack: deploying... [1/1]
CdkSampleStack: creating CloudFormation changeset...
[██████████████▌···········································] (3/12)

3:07:17 AM | CREATE_FAILED        | AWS::SNS::Topic     | Topic
Resource handler returned message: "Resource of type 'AWS::SNS::Topic' with identifier 'cdk-sample-top
ic' already exists." (RequestToken: bcb9058f-38a3-d4dc-e2e3-aea4174fbc24, HandlerErrorCode: AlreadyExi
sts)

そして、ロググループの存在を確認してみると、作成されていません。

$ aws logs describe-log-streams --log-group-name /aws/lambda/cdk-sample

An error occurred (ResourceNotFoundException) when calling the DescribeLogStreams operation: The specified log group does not exist.

CloudFormation のイベントを確認してみると、ロググループは一度作成が行われた後にロールバックにより削除されていることがわかります。

RETAIN_ON_UPDATE_OR_DELETE が動作していることが確認できました。

おわりに

AWS CDK v2.90.0 で RemovalPolicy.RETAIN_EXCEPT_ON_CREATE が利用可能になったので試してみました。

リソース名重複などにより CDK デプロイがロールバックされることはよくあるのですが、その際に RETAIN となっているリソースが作成されてしまっていたら、手動で削除をしないといけないので面倒です。それが RETAIN_EXCEPT_ON_CREATE が使えるようになったことで、そのような手間が省けるようになりました。デプロイ作業時のハンドリングの効率化に役立てていきたいですね。

以上