[アップデート]AWS CDKでIaCジェネレーターを利用して、既存リソースからCDKアプリケーションを作成できるようになりました(cdk migrate –from-scan)

2024.02.05

先日、IaCジェネレーターが発表されました。

AWS CDKのアップデートに以下がありました。

migrate: Add CDK Migrate --from-scan functionality (#28962) (bbc14b3)

Release v2.126.0 · aws/aws-cdk

IaCジェネレーターのCloudFormationスタックに関連付けられていないAWS リソースから、CDKアプリを生成するオプションのようです。

早速試してみました。

注意点として、cdk migrateは現時点(2024/2時点)で実験的な機能になっています。今後破壊的な変更が起きる可能性があります。

前提

  • aws-cdk: v2.126.0以上

やってみた

既存のSQSをターゲットにして、cdk migrate--from-scanオプションでCDKアプリケーションを作成します。

対象は以下のSQSキューです。

実行対象を判別するために、migrate-testタグを付与します。

migrateコマンドを実行します。

$ cdk migrate --language typescript --from-scan --stack-name MigrateTest --filter tag-key=migrate-test
This is an experimental feature and development on it is still in progress. We make no guarantees about the outcome or stability of the functionality.
Using the latest successful scan which is 0 days, 0 hours, and 6 minutes old.
Applying filters to resource scan.
finding related resources.
Found 1 resources.
Generating CFN template from scanned resources.
Please wait, template creation in progress. This may take a couple minutes.
[CREATE_IN_PROGRESS] Template Creation in Progress
Template successfully generated!
 ⏳  Generating CDK app for MigrateTest...
Applying project template app for typescript
Initializing a new git repository...
Executing npm install...
✅ All done!

MigrateTestディレクトリが作成され、CDKアプリケーションが作成されています。

$ cd MigrateTest
$ tree -L 2 -I 'node_modules'
.
├── bin
│   └── migrate_test.ts
├── cdk.json
├── cdk.out
│   ├── cdk.out
│   ├── manifest.json
│   ├── MigrateTest.assets.json
│   ├── MigrateTest.template.json
│   └── tree.json
├── jest.config.js
├── lib
│   └── migrate_test-stack.ts
├── migrate.json
├── package.json
├── package-lock.json
├── README.md
├── test
│   └── migrate_test.test.ts
└── tsconfig.json

bin/migrate.tslib/migrate_test-stack.tsの中身は以下のようになっていました。

bin/migrate.ts

#!/usr/bin/env node
import 'source-map-support/register';
import * as cdk from 'aws-cdk-lib';
import { MigrateTestStack } from '../lib/migrate_test-stack';

const app = new cdk.App();
new MigrateTestStack(app, 'MigrateTest', {
  /* If you don't specify 'env', this stack will be environment-agnostic.
   * Account/Region-dependent features and context lookups will not work,
   * but a single synthesized template can be deployed anywhere. */

  /* Uncomment the next line to specialize this stack for the AWS Account
   * and Region that are implied by the current CLI configuration. */
  // env: { account: process.env.CDK_DEFAULT_ACCOUNT, region: process.env.CDK_DEFAULT_REGION },

  /* Uncomment the next line if you know exactly what Account and Region you
   * want to deploy the stack to. */
  // env: { account: '123456789012', region: 'us-east-1' },

  /* For more information, see https://docs.aws.amazon.com/cdk/latest/guide/environments.html */
});

lib/migrate_test-stack.ts

import * as cdk from 'aws-cdk-lib';
import * as sqs from 'aws-cdk-lib/aws-sqs';

export interface MigrateTestStackProps extends cdk.StackProps {
}

export class MigrateTestStack extends cdk.Stack {
  public constructor(scope: cdk.App, id: string, props: MigrateTestStackProps = {}) {
    super(scope, id, props);

    // Resources
    const sqsQueue00migratetest003Bu1s = new sqs.CfnQueue(this, 'SQSQueue00migratetest003Bu1s', {
      sqsManagedSseEnabled: true,
      receiveMessageWaitTimeSeconds: 0,
      delaySeconds: 0,
      messageRetentionPeriod: 345600,
      maximumMessageSize: 262144,
      visibilityTimeout: 30,
      queueName: 'migrate-test',
      tags: [
        {
          value: 'hoge',
          key: 'migrate-test',
        },
      ],
    });
    sqsQueue00migratetest003Bu1s.cfnOptions.deletionPolicy = cdk.CfnDeletionPolicy.RETAIN;
  }
}

コマンド一発でここまで作ってくれるのは、楽ですね!

L1コンストラクトな点と、変数名が長くて読みづらいのは気になりますが、必要に応じてリファクタリングしましょう。

cdk migrateコマンドでは、CDKアプリケーションの作成までを行います。スタックの作成は行いません。

スタックを作成していきます。

まずは、cdk diffで差分を確認します。

$ cdk diff
Hold on while we create a read-only change set to get a diff with accurate replacement information (use --no-change-set to use a less accurate but faster template-only diff)
Parameters and rules created during migration do not affect resource configuration.
Parameters
[+] Parameter BootstrapVersion BootstrapVersion: {"Type":"AWS::SSM::Parameter::Value<String>","Default":"/cdk-bootstrap/hnb659fds/version","Description":"Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]"}

Conditions
[+] Condition CDKMetadata/Condition CDKMetadataAvailable: {"Fn::Or":[{"Fn::Or":[{"Fn::Equals":[{"Ref":"AWS::Region"},"af-south-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"ap-east-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"ap-northeast-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"ap-northeast-2"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"ap-south-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"ap-southeast-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"ap-southeast-2"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"ca-central-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"cn-north-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"cn-northwest-1"]}]},{"Fn::Or":[{"Fn::Equals":[{"Ref":"AWS::Region"},"eu-central-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"eu-north-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"eu-south-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"eu-west-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"eu-west-2"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"eu-west-3"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"il-central-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"me-central-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"me-south-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"sa-east-1"]}]},{"Fn::Or":[{"Fn::Equals":[{"Ref":"AWS::Region"},"us-east-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"us-east-2"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"us-west-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"us-west-2"]}]}]}

Resources
[←] AWS::SQS::Queue SQSQueue00migratetest003Bu1s SQSQueue00migratetest003Bu1s import

Other Changes
[+] Unknown Rules: {"CheckBootstrapVersion":{"Assertions":[{"Assert":{"Fn::Not":[{"Fn::Contains":[["1","2","3","4","5"],{"Ref":"BootstrapVersion"}]}]},"AssertDescription":"CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI."}]}}


✨  Number of stacks with differences: 1

注目してほしいのは、Resoucesのところがimportになっている点です。

cdk importなどを実行して、別途importする必要があると考えていましたが、cdk migrateではimportまでやってくれるようです。

あとは、cdk deployを実行するだけです。

$ cdk deploy

CloudFormationスタックも無事作成されています。

リソースの関連付けどうやっている

cdk importコマンドでは、リソースを関連付けるために、コマンド実行時にリソースを識別するための値を渡す必要があります。(SQSだったら、キューURL)

しかし、今回のcdk migrateコマンドでは不要でした。

ファイルを見たところmigrate.jsonにSQSのキューURLが書かれており、このファイルが使われているようです。(一回目のdeploy成功時にこのファイルは削除されます)

migrate.json

{
  "//": "This file is generated by cdk migrate. It will be automatically deleted after the first successful deployment of this app to the environment of the original resources.",
  "Source": "arn:aws:cloudformation:ap-northeast-1:201472471660:generatedTemplate/986bb8b3-179e-4eab-8bff-c12da54cc34d",
  "Resources": [
    {
      "ResourceType": "AWS::SQS::Queue",
      "LogicalResourceId": "SQSQueue00migratetest200nqtDV",
      "ResourceIdentifier": {
        "QueueUrl": "https://sqs.ap-northeast-1.amazonaws.com/XXXXXX/migrate-test-2"
      }
    }
  ]
}

おわりに

IaCジェネレーターのおかげで、既存リソースのCDK化も捗りそうです。

生成されるコードがL1であることと、変数名やIDが読みづらいという部分もありますが、今までの方法より格段にimport作業が楽になりそうです。今後に期待の機能ですね。

以上、AWS事業本部の佐藤(@chari7311)でした。

参考