dshimizu/blog/alpha

とりとめのないITブログ

AWS CDK について調べながら AWS CDK in TypeScript のサンプルアプリケーションを動かしてみた時の備忘録

はじめに

AWS CDK に触れたいと思っていたのと、TypeScript を学びたいと思っていたので、AWS CDK について調べながら AWS CDK in TypeScript でサンプルアプリケーションの内容等を見てみました。

AWS CDK

AWS CDK(Cloud Development Kit)は、プログラミング言語を用いてAWSのリソースを構築するためのフレームワーク、だと思ってます。

2024/1 時点では TypeScript、JavaScriptPythonJavaC#、Go を用いてコードによって、AWSリソースの定義ができるようです。 裏では AWS CloudFormation スタックが作成されてデプロイされるようです。

docs.aws.amazon.com

以下のAWSブログでは、AWS CDK は、次の 3 つの主要なコンポーネントで構成されている、とあります(ブログは CDK v1 時代に書かれたものと思いますが、主要コンポーネントは大きくは変わっていないのではと思います)

コアフレームワークとConstruct Library

TypeScript で実装されているようで、 Construct Library とあわせてnpm パッケージの aws-cdk-lib としてまとめて配布されているもののようです。

CDK CLI ツール

AWS CDK をインストールしたら、 cdk コマンドを実行可能になります。 実態は Node モジュール内の node_modules/aws-cdk/bin/cdk.js のようでした。

ベストプラクティス

AWS CDK にはいくつかの観点でのベストプラクティスが公開されています。

その中に下記のような記載がありました。

Treat AWS CloudFormation as an implementation detail that the AWS CDK uses for robust cloud deployments, not as a language target. You’re not writing AWS CloudFormation templates in TypeScript or Python, you’re writing CDK code that happens to use CloudFormation for deployment.

AWS CDK で開発するのは CloudFormation テンプレートではなく、CDK のアプリケーションである、とのことです。 最終的には CDK アプリから CloudFormation テンプレートが出力され、また出力されたテンプレートの内容を確認することもあると思いますが、開発するのはあくまで AWS CDK アプリであるとのことです。 この観点は重要な気がしました。

Construct

AWS CDK には Construct(コンストラクト) という単語ができてます。

A construct is the basic building block of an AWS CDK application. A construct can represent a single AWS resource, such as an Amazon Simple Storage Service (Amazon S3) bucket, or it can be a higher-level abstraction consisting of multiple AWS related resources. The components of a construct can include a worker queue with its associated compute capacity, or a scheduled job with monitoring resources and a dashboard. The AWS CDK includes a collection of constructs called the AWS Construct Library. The library contains constructs for every AWS service. You can use the Construct Hub to discover additional constructs from AWS, third parties, and the open-source AWS CDK community.

Constructs are the basic building blocks of AWS Cloud Development Kit (AWS CDK) applications. A construct is a component within your application that represents one or more AWS CloudFormation resources and their configuration. You build your application, piece by piece, by importing and configuring constructs.

Constructs are classes that you import into your CDK apps. Constructs are available from the AWS Construct Library. You can also create and distribute your own constructs, or use constructs created by third-party developers.

Constructs are part of the Construct Programming Model (CPM). They are available to use with other tools such as CDK for Terraform (CDKtf), CDK for Kubernetes (CDK8s), and Projen.

ドキュメントによると、コンストラクトはアプリの基本的な構成要素で、1 つ以上の AWS CloudFormation リソース、AWSリソース等を表す CDK アプリケーション内のコンポーネント、ということになるようです

Costruct レベル

  • L1

    Level 1 (L1) constructs

    L1 constructs, also known as CFN resources, are the lowest-level construct and offer no abstraction. Each L1 construct maps directly to a single AWS CloudFormation resource. With L1 constructs, you import a construct that represents a specific AWS CloudFormation resource. You then define the resource’s properties within your construct instance.
    
    L1 constructs are great to use when you are familiar with AWS CloudFormation and need complete control over defining your AWS resource properties.
    
    In the AWS Construct Library, L1 constructs are named starting with Cfn, followed by an identifier for the AWS CloudFormation resource that it represents. For example, the CfnBucket construct is an L1 construct that represents an AWS::S3::Bucket AWS CloudFormation resource.
    
    L1 constructs are generated from the AWS CloudFormation resource specification. If a resource exists in AWS CloudFormation, it'll be available in the AWS CDK as an L1 construct. New resources or properties may take up to a week to become available in the AWS Construct Library. For more information, see AWS resource and property types reference in the AWS CloudFormation User Guide.
    

L1コンストラクトでは抽象化はなく、CDKアプリケーション上で、CloudFormation テンプレートで扱うのとほぼ同等の形でリソースと必要なパラメーターを定義することでCloudFormation スタックとして設定して扱える、ということかと思います。(YAMLテンプレートを書くのと同じことをそのままCDKアプリケーション上でやるイメージ) 「L1 constructs are great to use when you are familiar with AWS CloudFormation and need complete control over defining your AWS resource properties.」とあるので、完全に CDK アプリケーション開発者自身で全て制御したい場合は L1 コンストラクトを用いる形になるのかなと思いあmした。

  • (L2)https://docs.aws.amazon.com/cdk/v2/guide/constructs.html#constructs_lib_levels_two

    Level 2 (L2) constructs

    L2 constructs, also known as curated constructs, are thoughtfully developed by the CDK team and are usually the most widely used construct type. L2 constructs map directly to single AWS CloudFormation resources, similar to L1 constructs. Compared to L1 constructs, L2 constructs provide a higher-level abstraction through an intuitive intent-based API. L2 constructs include sensible default property configurations, best practice security policies, and generate a lot of the boilerplate code and glue logic for you.
    
    L2 constructs also provide helper methods for most resources that make it simpler and quicker to define properties, permissions, event-based interactions between resources, and more.
    

    : :

CDKアプリケーション上で設定した値を CloudFormation スタックとして設定できるが、細かいパラメーターをCDKアプリケーション上で定義しない場合は、あらかじめベストプラクティスやセキュリティが考慮されたデフォルト値として設定されるコンストラクトレベル、ということかと思いました。 このレイヤが最もよく使われるもののようです。

  • (L3)https://docs.aws.amazon.com/cdk/v2/guide/constructs.html#constructs_lib_levels_three

    Level 3 (L3) constructs

    L3 constructs, also known as patterns, are the highest-level of abstraction. Each L3 construct can contain a collection of resources that are configured to work together to accomplish a specific task or service within your application. L3 constructs are used to create entire AWS architectures for particular use cases in your application.
    
    To provide complete system designs, or substantial parts of a larger system, L3 constructs offer opinionated default property configurations. They are built around a particular approach toward solving a problem and providing a solution. With L3 constructs, you can create and configure multiple resources quickly, with the fewest amount of input and code.
    

    : :

AWSリソース単体ではなく、必要なリソースの組み合わせたものをまとめて作成・管理できるもの、といったイメージでしょうか。 1つのクラスで、必要なものをまとめて作成することができる、というイメージかと思いました。

Costruct ツリー

CDK アプリケーションは App クラスを起点したツリー構成となるようです。 内部的には AWS CloudFormation テンプレート内のリソース作成・管理するための順序の暗黙的な定義になるようです。 Costruct ツリー構造を意識したCDKアプリケーション開発を行う必要がある、ということのように思いました。

  • (Costruct ツリー)https://docs.aws.amazon.com/cdk/v2/guide/constructs.html#constructs_tree

    Constructs are defined inside of other constructs using the scope argument that is passed to every construct, with the App class as the root. In this way, an AWS CDK app defines a hierarchy of constructs known as the construct tree.

    The root of this tree is your app, which is an object of the App class. Within the app, you instantiate one or more stacks. Within stacks, you instantiate either AWS CloudFormation resources or higher-level constructs, which may themselves instantiate resources or other constructs, and so on down the tree. : : : Technically, it's possible to pass some scope other than this when instantiating a construct. You can add constructs anywhere in the tree, or even in another stack in the same app. For example, you could write a mixin-style function that adds constructs to a scope passed in as an argument. The practical difficulty here is that you can't easily ensure that the IDs you choose for your constructs are unique within someone else's scope. The practice also makes your code more difficult to understand, maintain, and reuse. It is almost always better to find a way to express your intent without resorting to abusing the scope argument.

AWS CDK のセットアップ

一通りドキュメントを見てみたところで、AWS CDKをインストールして少し触ってみます。

環境

Debian 12 の環境を利用します。

% uname -svor
Linux 6.1.0-12-cloud-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.52-1 (2023-09-07) GNU/Linux

Node.js は 18.14.0 を使ってます。

% node -v
v18.14.0

npx は 9.3.1 を使ってます。

% npx -v
9.3.1

TypeScript は 4.9.5 を使ってます。

% npx tsc -v
Version 4.9.5

AWS CLI の設定では、 sandbox という名前の認証プロファイルを作成して、このプロファイルを利用することとします。

  • ~/aws/credentials
[sandbox]
aws_access_key_id=********************
aws_secret_access_key=****************************************
  • ~/aws/config
[default]
region = ap-northeast-1
output = json

[profile sandbox]
region = ap-northeast-1
output = json
source_profile = default
role_arn = arn:aws:iam::**********:role/AdminRole

AWS CDK のインストール

CDK をインストールします。

% npm install aws-cdk aws-cdk-lib

インストールできました。

% npx cdk --version
2.212.0 (build 9f2b78c )

AWS CDKアプリケーション作成用のAWS環境へのブートストラップ処理実行

AWS アカウント/リージョン内に AWS CDK を初めてデプロイする際には、まずブートストラップスタックをデプロイする必要があるようです。 以下で、ブートストラップスタックを AWS アカウントの指定したリージョンにデプロイできます。

実行する際に、CloudFormation の CreateChangeSet の権限が必要なようなので、権限がない場合は追加します。

% npx cdk bootstrap --profile sandbox 
 ⏳  Bootstrapping environment aws://123456789012/ap-northeast-1...
Trusted accounts for deployment: (none)
Trusted accounts for lookup: (none)
Using default execution policy of 'arn:aws:iam::aws:policy/AdministratorAccess'. Pass '--cloudformation-execution-policies' to customize.
CDKToolkit: creating CloudFormation changeset...
 ✅  Environment aws://123456789012/ap-northeast-1 bootstrapped.

CDKToolkit という名前のCloudFormationスタックが作成されました。 このスタックによって作成されるリソースは下記のようなものでした。

ECR, S3, Paramter Storeといくつかの IAM Policy, Role でした。これらが何に使われるのかはまだよく分かっていません。

% aws cloudformation describe-stack-resources --stack-name CDKToolkit --query 'StackResources[].[StackName,PhysicalResourceId,ResourceType]' --profile sandbox 
[
    [
        "CDKToolkit",
        "/cdk-bootstrap/abcdefg12/version",
        "AWS::SSM::Parameter"
    ],
    [
        "CDKToolkit",
        "cdk-abcdefg12-cfn-exec-role-123456789012-ap-northeast-1",
        "AWS::IAM::Role"
    ],
    [
        "CDKToolkit",
        "cdk-abcdefg12-container-assets-123456789012-ap-northeast-1",
        "AWS::ECR::Repository"
    ],
    [
        "CDKToolkit",
        "cdk-abcdefg12-deploy-role-123456789012-ap-northeast-1",
        "AWS::IAM::Role"
    ],
    [
        "CDKToolkit",
        "cdk-abcdefg12-file-publishing-role-123456789012-ap-northeast-1",
        "AWS::IAM::Role"
    ],
    [
        "CDKToolkit",
        "CDKTo-File-************",
        "AWS::IAM::Policy"
    ],
    [
        "CDKToolkit",
        "cdk-abcdefg12-image-publishing-role-123456789012-ap-northeast-1",
        "AWS::IAM::Role"
    ],
    [
        "CDKToolkit",
        "CDKTo-Imag-*************",
        "AWS::IAM::Policy"
    ],
    [
        "CDKToolkit",
        "cdk-abcdefg12-lookup-role-123456789012-ap-northeast-1",
        "AWS::IAM::Role"
    ],
    [
        "CDKToolkit",
        "cdk-abcdefg12-assets-123456789012-ap-northeast-1",
        "AWS::S3::Bucket"
    ],
    [
        "CDKToolkit",
        "CDKToolkit-StagingBucketPolicy-***************",
        "AWS::S3::BucketPolicy"
    ]
]

以上で、AWS CDKアプリケーションを実行する環境の準備ができました。


AWS CDKアプリケーションを作る

どんなものか確認するために、 AWS CDKアプリケーションを作ってみます。

AWS CDKアプリケーションのプロジェクトの作成

AWS CDKアプリケーションのプロジェクトを作成してみます。

プロジェクト用のディレクトリを作成して、移動します。ここではテスト用に cdk-sandbox というディレクトリにしています。

% mkdir cdk-sandbox && cd cdk-sandbox

cdk init では app, lib, sample-app の 3 つのテンプレートが選択できるようです。通常のプロジェクトとして開始する場合は app を利用するようです。省略した場合は app がデフォルトになるようです。

lib は CDK ライブラリを作成する場合に利用し、 sample-app はその名の通りでサンプルアプリケーションが動くCDKコードが生成されるようです。

% npx cdk init --list
Available templates:
* app: Template for a CDK Application
   └─ cdk init app --language=[csharp|fsharp|go|java|javascript|python|typescript]
* lib: Template for a CDK Construct Library
   └─ cdk init lib --language=typescript
* sample-app: Example CDK Application with some constructs
   └─ cdk init sample-app --language=[csharp|fsharp|go|java|javascript|python|typescript]

typescript でプロジェクトを作成します。

% npx cdk init sample-app --language typescript
Applying project template sample-app for typescript
# Welcome to your CDK TypeScript project

You should explore the contents of this project. It demonstrates a CDK app with an instance of a stack (`CdkSandboxStack`)
which contains an Amazon SQS queue that is subscribed to an Amazon SNS topic.

The `cdk.json` file tells the CDK Toolkit how to execute your app.

## Useful commands

* `npm run build`   compile typescript to js
* `npm run watch`   watch for changes and compile
* `npm run test`    perform the jest unit tests
* `cdk deploy`      deploy this stack to your default AWS account/region
* `cdk diff`        compare deployed stack with current state
* `cdk synth`       emits the synthesized CloudFormation template

Initializing a new git repository...
hint: Using 'master' as the name for the initial branch. This default branch name
hint: is subject to change. To configure the initial branch name to use in all
hint: of your new repositories, which will suppress this warning, call:
hint:
hint:   git config --global init.defaultBranch <name>
hint:
hint: Names commonly chosen instead of 'master' are 'main', 'trunk' and
hint: 'development'. The just-created branch can be renamed via this command:
hint:
hint:   git branch -m <name>
Executing npm install...
✅ All done!

以下のようなファイルが生成されます。

% tree -L 2
.
├── README.md
├── bin
│   └── cdk-sandbox.ts
├── cdk.json
├── jest.config.js
├── lib
│   └── cdk-sandbox-stack.ts
├── node_modules
│   ├── @ampproject
 :
│   ├── yn
│   └── yocto-queue
├── package-lock.json
├── package.json
├── test
│   └── cdk-sandbox.test.ts
└── tsconfig.json

221 directories, 9 files

bin/cdk-sandbox.ts というファイルが生成されており、これが CDK アプリケーションのエントリーポイント(アプリケーションの中で一番最初に呼び出される部分)となるようで、1つのアプリケーションとなる元になるもようなので、まずはこれをみてみます。 ../lib/cdk-sandbox-stack から CdkSandboxStack というクラスを読み込んで、インスタンスを生成しているようです。

#!/usr/bin/env node
import * as cdk from 'aws-cdk-lib';
import { CdkSandboxStack } from '../lib/cdk-sandbox-stack';

const app = new cdk.App();
new CdkSandboxStack(app, 'CdkSandboxStack');

bin/cdk-sandbox.ts で読み込まれている lib/cdk-sandbox-stack.ts というファイルが生成されているので見てみます。 SQS を作成するための定義のサンプルがコメントアウト状態であるだけでした。

lib/ 配下にリソースを作成・管理するファイルを生成していくのがベースとなるように思いました。

生成されたサンプルアプリケーションでは、 sqs.Queue, sns.Topic で、L2コンストラクトでリソースが作成されるようになっており、細かいパラメーターの指定は無さそうです。 topic.addSubscription(new subs.SqsSubscription(queue)); で、SQSキューをSNSサブスクリプションとして登録しているようです。

import { Duration, Stack, StackProps } from 'aws-cdk-lib';
import * as sns from 'aws-cdk-lib/aws-sns';
import * as subs from 'aws-cdk-lib/aws-sns-subscriptions';
import * as sqs from 'aws-cdk-lib/aws-sqs';
import { Construct } from 'constructs';

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

    const queue = new sqs.Queue(this, 'CdkSandboxQueue', {
      visibilityTimeout: Duration.seconds(300)
    });

    const topic = new sns.Topic(this, 'CdkSandboxTopic');

    topic.addSubscription(new subs.SqsSubscription(queue));
  }
}

SQS 部分を L1 コンストラクトにすると以下のような感じになるかと思います

import { Duration, Stack, StackProps } from 'aws-cdk-lib';
import * as sns from 'aws-cdk-lib/aws-sns';
import * as subs from 'aws-cdk-lib/aws-sns-subscriptions';
import * as sqs from 'aws-cdk-lib/aws-sqs';
import { Construct } from 'constructs';

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

    declare const redriveAllowPolicy: any;
    declare const redrivePolicy: any;
    // L1 コンストラクタ
    // 細かいパラメーターの是非は置いておいて、以下のように色々指定する必要がある
    const cfnQueue = new sqs.CfnQueue(this, 'MyCfnCdkSandboxQueue', /* all optional props */ {
      contentBasedDeduplication: false,
      deduplicationScope: 'deduplicationScope',
      delaySeconds: 300,
      fifoQueue: false,
      fifoThroughputLimit: 'fifoThroughputLimit',
      kmsDataKeyReusePeriodSeconds: 123,
      kmsMasterKeyId: 'kmsMasterKeyId',
      maximumMessageSize: 123,
      messageRetentionPeriod: 123,
      queueName: 'queueName',
      receiveMessageWaitTimeSeconds: 123,
      redriveAllowPolicy: redriveAllowPolicy,
      redrivePolicy: redrivePolicy,
      sqsManagedSseEnabled: false,
      tags: [{
        key: 'key',
        value: 'value',
      }],
      visibilityTimeout: 123,
    });


    const topic = new sns.Topic(this, 'CdkSandboxTopic');

    topic.addSubscription(new subs.SqsSubscription(queue));
  }
}

AWS CDKアプリケーションのデプロイ

サンプルアプリケーションをデプロイしてみます。 cdk synth コマンドで、CDK アプリケーションによって生成される CloudFormation テンプレートを出力できます。

% npx cdk synth --profile sandbox 
Resources:
  CdkSandboxQueue35D1CC67:
    Type: AWS::SQS::Queue
    Properties:
      VisibilityTimeout: 300
    UpdateReplacePolicy: Delete
    DeletionPolicy: Delete
    Metadata:
      aws:cdk:path: CdkSandboxStack/CdkSandboxQueue/Resource
  CdkSandboxQueuePolicyECA3AEDD:
    Type: AWS::SQS::QueuePolicy
    Properties:
      PolicyDocument:
        Statement:
          - Action: sqs:SendMessage
            Condition:
              ArnEquals:
                aws:SourceArn:
                  Ref: CdkSandboxTopic334B4C0A
            Effect: Allow
            Principal:
              Service: sns.amazonaws.com
            Resource:
              Fn::GetAtt:
                - CdkSandboxQueue35D1CC67
                - Arn
        Version: "2012-10-17"
      Queues:
        - Ref: CdkSandboxQueue35D1CC67
    Metadata:
      aws:cdk:path: CdkSandboxStack/CdkSandboxQueue/Policy/Resource
  CdkSandboxQueueCdkSandboxStackCdkSandboxTopic2372C543BE098F61:
    Type: AWS::SNS::Subscription
    Properties:
      Endpoint:
        Fn::GetAtt:
          - CdkSandboxQueue35D1CC67
          - Arn
      Protocol: sqs
      TopicArn:
        Ref: CdkSandboxTopic334B4C0A
    DependsOn:
      - CdkSandboxQueuePolicyECA3AEDD
    Metadata:
      aws:cdk:path: CdkSandboxStack/CdkSandboxQueue/CdkSandboxStackCdkSandboxTopic2372C543/Resource
  CdkSandboxTopic334B4C0A:
    Type: AWS::SNS::Topic
    Metadata:
      aws:cdk:path: CdkSandboxStack/CdkSandboxTopic/Resource
  CDKMetadata:
    Type: AWS::CDK::Metadata
    Properties:
      Analytics: v2:deflate64:H4sIAAAAAAAA/1WOQQ7CIBBFz+KejtK46L4X0Na9aQGTaSu0DGgM4e4CTUzczLz/8pOZGnjdwOkwvKkScq4WHCH0bhAzS+oeaCMIV6+8Yu1D71DmxSwoPj+5x8hIp37vRxIWV4dG58ZfvpkVRbYFYszYKTLeinKjNVpibkamjVQw0fHFG+Dn9OVEiJX12uFTQbfvL6/ADjHCAAAA
    Metadata:
      aws:cdk:path: CdkSandboxStack/CDKMetadata/Default
    Condition: CDKMetadataAvailable
Conditions:
  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
Parameters:
  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]
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.

cdk deploy コマンドでデプロイします。

% npx cdk deploy --profile sandbox 

以下のような出力がされ、リソースが作成されます。

✨  Synthesis time: 7.86s

CdkSandboxStack:  start: Building c5494d4703a1842b58ae20a6f5b7672a6f9c9b21dde4fec33ca109e44498501d:current_account-current_region
CdkSandboxStack:  success: Built c5494d4703a1842b58ae20a6f5b7672a6f9c9b21dde4fec33ca109e44498501d:current_account-current_region
CdkSandboxStack:  start: Publishing c5494d4703a1842b58ae20a6f5b7672a6f9c9b21dde4fec33ca109e44498501d:current_account-current_region
CdkSandboxStack:  success: Published c5494d4703a1842b58ae20a6f5b7672a6f9c9b21dde4fec33ca109e44498501d:current_account-current_region
This deployment will make potentially sensitive changes according to your current security approval level (--require-approval broadening).
Please confirm you intend to make the following modifications:

IAM Statement Changes
┌───┬────────────────────────┬────────┬─────────────────┬───────────────────────────┬────────────────────────────────────────────────────────┐
│   │ Resource               │ Effect │ Action          │ Principal                 │ Condition                                              │
├───┼────────────────────────┼────────┼─────────────────┼───────────────────────────┼────────────────────────────────────────────────────────┤
│ + │ ${CdkSandboxQueue.Arn} │ Allow  │ sqs:SendMessage │ Service:sns.amazonaws.com │ "ArnEquals": {                                         │
│   │                        │        │                 │                           │   "aws:SourceArn": "${CdkSandboxTopic}"                │
│   │                        │        │                 │                           │ }                                                      │
└───┴────────────────────────┴────────┴─────────────────┴───────────────────────────┴────────────────────────────────────────────────────────┘
(NOTE: There may be security-related changes not in this list. See https://github.com/aws/aws-cdk/issues/1299)

Do you wish to deploy these changes (y/n)? y
CdkSandboxStack: deploying... [1/1]
CdkSandboxStack: creating CloudFormation changeset...

 ✅  CdkSandboxStack

✨  Deployment time: 62.17s

Stack ARN:
arn:aws:cloudformation:ap-northeast-1:123456789012:stack/CdkSandboxStack/36198690-d23b-11ee-af56-0a4a4aa379bb

✨  Total time: 70.03s

デプロイが成功すれば以下のリソースが作成されました。SNSで処理を受け取った場合にSQSキューに蓄積するための一連のリソースのようです。特に何に使われるわけでもなく、これが作成されるだけでは料金がかかることはなさそうです。

  • SQS
    • キュー
  • SNS
  • IAM ポリシー
    • トピックがキューにメッセージを送信することを許可するポリシー

その他のコマンド

デプロイ済みのスタックがある場合は以下のコマンドで一覧を表示できます。

% npx cdk list --profile sandbox 
CdkSandboxStack

CDK アプリを修正した場合は以下のコマンドで差分を表示できます。

% npx cdk diff --profile sandbox 
CdkSandboxStack

スタックの削除

% npx cdk destroy --profile sandbox

以下のような出力によって削除が完了します。

Are you sure you want to delete: CdkSandboxStack (y/n)? y
CdkSandboxStack: destroying... [1/1]

 ✅  CdkSandboxStack: destroyed

まとめ

AWS CDK について理解を深めるために色々調べながら、AWS CDK in TypeScript を初期セットアップし、サンプルアプリケーションを作成して動かしてみました。

ドキュメントを読んでいく中で、CDK では CloudFormation ではなく CDK アプリケーションを開発する、という点が重要そうであると感じました。

今回は凝ったことはしてませんが、プログラミングの知識とAWSの知識が必要となり、CloudFormation や Terraform などの IaC コードにある宣言型や命令型のアプローチでやっていたインフラ専門のITエンジニアが触れていくには最初は学習コストは高そうな印象はありました。 ただ、CloudFormation よりは CLI で扱いやすそうだったり、またプログラミングを始めるきっかけになるかもしれません。

L1コンストラクトよりL2コンストラクトの方が抽象度が高い分記述量の少ないコードを書けることはわかりました。ただ、Construct プログラミングモデルについてもまだよく理解できていないので、色々触りながら理解を深めていきたいと思います。

また、CDK アプリの分割や、CloudFomrtionスタックの分割も踏まえたCDKアプリケーション開発をどのように行うのが良いのか、なども模索していければと思います。

参考