AWS CDK Developer GuideのチュートリアルをTypeScriptでやってみた

2020.09.17

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

最近対応した案件でAWS CDKを初めて使う機会がありました。今まではAWSリソースの定義やデプロイはCloudFormationしか使ってこなかったのですが、AWS CDKはTypeScriptを使うことによる型補完機能がとても便利で感動しています。

今回は、そんなAWS CDKの再入門ということで、AWS CDKのDeveloper Guideで紹介されているGetting startedチュートリアルをTypeScriptでやってみました。

やってみた

今回やってみたGetting startedの内容は次の通りとなります。(URLリンクは元記事のページです)

作業環境は予め次のようにして作成しました。

% mkdir myCdk && cd myCdk
% npm init
% npm install typescript

前提条件

AWS CDKを利用する上での前提条件(2020年9月時点)は以下とのことです。

  • Node.js10.3.0以降
    • 13.0.0から13.6.0を除く
  • 以下のいずれかによりAWS CDKでのデプロイ先のAWSアカウントの認証情報とAWSリージョンが指定されていること
    • ファイル~/.aws/configおよび~/.aws/credentials
    • 環境変数AWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEYおよびAWS_DEFAULT_REGION
  • TypeScript2.7以降
    • 開発言語にTypeScriptを使う場合

今回使用した作業環境は次の通りです。

% node -v
v12.14.0
% ./node_modules/.bin/tsc --version
Version 4.0.2

AWS CDKのインストール

AWS CDKをグローバルにインストールする場合は次のコマンドを実行します。

npm install -g aws-cdk

今回は作業環境のnpmプロジェクトで管理したかったので次の通りローカルインストールを行いまいした。

% npm install aws-cdk
npm WARN myCdk@1.0.0 No description
npm WARN myCdk@1.0.0 No repository field.

+ aws-cdk@1.63.0
added 216 packages from 187 contributors and audited 217 packages in 7.458s

7 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities

% cdk --version
1.51.0 (build 8c2d53c)

CDK Appの作成

まずCDK Appのプロジェクトディレクトリhello-cdkを作成してその中に移動します。

% mkdir hello-cdk
% cd hello-cdk

CDK Appの初期化は、cdk initコマンドをテンプレート名と開発言語を指定して実行します。

今回はappというテンプレート名でTypeScript向けにCDK Apphello-cdkを初期化します。

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

This is a blank project for TypeScript development with CDK.

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...
Executing npm install...
npm WARN deprecated request@2.88.2: request has been deprecated, see https://github.com/request/request/issues/3142
npm WARN deprecated request-promise-native@1.0.9: request-promise-native has been deprecated because it extends the now deprecated request package, see https://github.com/request/request/issues/3142
npm WARN deprecated har-validator@5.1.5: this library is no longer supported
npm WARN deprecated resolve-url@0.2.1: https://github.com/lydell/resolve-url#deprecated
npm WARN deprecated urix@0.1.0: Please see https://github.com/lydell/urix#deprecated
npm notice created a lockfile as package-lock.json. You should commit this file.
npm WARN hello-cdk@0.1.0 No repository field.
npm WARN hello-cdk@0.1.0 No license field.

✅ All done!
**************************************************
*** Newer version of CDK is available [1.63.0] ***
*** Upgrade recommended                        ***
**************************************************

hello-cdkディレクトリ配下に次のようなファイルやディレクトリが作成されました。 image.png

CDK Appのビルド

CDK Apphello-cdkを初期化した直後の時点では、hello-cdk/lib配下には次のTypeScriptコードによるCDKテンプレートが作成されています。

hello-cdk/lib/hello-cdk-stack.ts

import * as cdk from '@aws-cdk/core';

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

    // The code that defines your stack goes here
  }
}

開発言語にTypeScriptを使用する場合はデプロイを行う前にCDKテンプレートがビルド(コンパイル)されている必要があります。ただし、ビルドの実行はToolkitが代わりに自動で行ってくれるため、開発者が手動で行う必要はありません。もしデバッグ用途などでビルドしたい場合はnpm run buildコマンドにより実施します。

実際にビルドしてみます。

% npm run build

> hello-cdk@0.1.0 build /Users/user/works/200916_cdk/hello-cdk
> tsc

すると、hello-cdk/lib配下にさらに次の2ファイルがCDKテンプレートとして生成されました。

  • hello-cdk-stack.js
  • hello-cdk-stack.d.ts

上記CDKテンプレートによりCDK Apphello-cdkのスタックが定義されています。

CDK Appのスタック一覧の確認

作成されたCDK Appのスタック一覧はcdk lsコマンドで確認可能です。

% cdk ls
HelloCdkStack

CDKテンプレート内で定義されたスタックHelloCdkStackが確認できます。

CDK AppへのS3バケットの追加

ここまでで作成したCDK Appのテンプレートはリソースを何も定義していないためスタックHelloCdkStackは空となっています。このCDK AppへS3バケットの定義を追加してみます。

TypeScriptによりAmazon S3のCDKリソースを定義するためには次のようにして@aws-cdk/aws-s3パッケージをインストールする必要があります。

npm install @aws-cdk/aws-s3

実際にインストールしてみます。

% npm install @aws-cdk/aws-s3
npm WARN @aws-cdk/aws-s3@1.63.0 requires a peer of @aws-cdk/core@1.63.0 but none is installed. You must install peer dependencies yourself.
npm WARN @aws-cdk/aws-events@1.63.0 requires a peer of @aws-cdk/core@1.63.0 but none is installed. You must install peer dependencies yourself.
npm WARN @aws-cdk/aws-iam@1.63.0 requires a peer of @aws-cdk/core@1.63.0 but none is installed. You must install peer dependencies yourself.
npm WARN @aws-cdk/aws-kms@1.63.0 requires a peer of @aws-cdk/core@1.63.0 but none is installed. You must install peer dependencies yourself.
npm WARN hello-cdk@0.1.0 No repository field.
npm WARN hello-cdk@0.1.0 No license field.

+ @aws-cdk/aws-s3@1.63.0
added 65 packages from 8 contributors and audited 839 packages in 5.933s

20 packages are looking for funding
  run `npm fund` for details

すると@aws-cdk/aws-s3のインストールは行われましたが、@aws-cdk/core@1.63.0がインストールされてない旨の警告が出ました。

npm listコマンドで現在のインストール済みパッケージのバージョンを確認してみます。

% npm list --depth=0
hello-cdk@0.1.0 /Users/wakatsuki.ryuta/works/200916_cdk/hello-cdk
├── @aws-cdk/assert@1.51.0
├── @aws-cdk/aws-s3@1.63.0
├── UNMET PEER DEPENDENCY @aws-cdk/core@1.51.0
├── @types/jest@25.2.3
├── @types/node@10.17.5
├── aws-cdk@1.51.0
├── jest@25.5.4
├── source-map-support@0.5.19
├── ts-jest@25.5.1
├── ts-node@8.10.2
└── typescript@3.7.5

npm ERR! peer dep missing: @aws-cdk/core@1.63.0, required by @aws-cdk/aws-s3@1.63.0
npm ERR! peer dep missing: @aws-cdk/core@1.63.0, required by @aws-cdk/aws-s3@1.63.0
npm ERR! peer dep missing: @aws-cdk/core@1.63.0, required by @aws-cdk/aws-events@1.63.0
npm ERR! peer dep missing: @aws-cdk/core@1.63.0, required by @aws-cdk/aws-iam@1.63.0
npm ERR! peer dep missing: @aws-cdk/core@1.63.0, required by @aws-cdk/aws-kms@1.63.0
npm ERR! peer dep missing: @aws-cdk/core@1.63.0, required by @aws-cdk/aws-iam@1.63.0
npm ERR! peer dep missing: @aws-cdk/core@1.63.0, required by @aws-cdk/aws-iam@1.63.0

@aws-cdk/aws-s3のバージョンが1.63.0であるのに対して、@aws-cdk/coreのバージョンが1.51.0であるためこちらでも警告が出ています。

この状態でCDKテンプレートを@aws-cdk/aws-s3を使用してS3バケットのリソースを定義するコードに更新してみます。

hello-cdk/lib/hello-cdk-stack.ts

import * as core from "@aws-cdk/core";
import * as s3 from "@aws-cdk/aws-s3";

export class HelloCdkStack extends core.Stack {
  constructor(scope: core.App, id: string, props?: core.StackProps) {
    super(scope, id, props);

    new s3.Bucket(this, "MyFirstBucket", {
      versioned: true,
    });
  }
}

すると次のようなビルドエラーとなりました。

this: this
Argument of type 'this' is not assignable to parameter of type 'Construct'.
  Type 'HelloCdkStack' is not assignable to type 'Construct'.
    Types of property 'node' are incompatible.
      Property 'host' is missing in type 'import("/Users/wakatsuki.ryuta/works/200916_cdk/hello-cdk/node_modules/@aws-cdk/core/lib/construct-compat").ConstructNode' but required in type 'import("/Users/wakatsuki.ryuta/works/200916_cdk/hello-cdk/node_modules/@aws-cdk/aws-events/node_modules/@aws-cdk/core/lib/construct-compat").ConstructNode'.ts(2345)
construct-compat.d.ts(174, 22): 'host' is declared here.

素直に@aws-cdk/coreのバージョンを1.63.0以上に更新してみます。

% npm install @aws-cdk/core@^1.63.0
npm WARN @aws-cdk/core@1.63.0 requires a peer of @aws-cdk/cloud-assembly-schema@1.63.0 but none is installed. You must install peer dependencies yourself.
npm WARN @aws-cdk/core@1.63.0 requires a peer of @aws-cdk/cx-api@1.63.0 but none is installed. You must install peer dependencies yourself.
npm WARN hello-cdk@0.1.0 No repository field.
npm WARN hello-cdk@0.1.0 No license field.

+ @aws-cdk/core@1.63.0
added 854 packages from 471 contributors and audited 854 packages in 13.612s

20 packages are looking for funding
  run `npm fund` for details

するとhello-cdk/lib/hello-cdk-stack.tsで先ほどのビルドエラーは出なくなりました。これで問題なさそうです。

CloudFormationテンプレートへの変換

CDKテンプレートがデプロイされる際にはCloudFormationテンプレートへ変換された上でデプロイされます。cdk synthコマンドを実行するとどのようなCloudFormationテンプレートに変換されるかを確認することができます。

実際に確認してみます。

% cdk synth
Resources:
  MyFirstBucketB8884501:
    Type: AWS::S3::Bucket
    Properties:
      VersioningConfiguration:
        Status: Enabled
    UpdateReplacePolicy: Retain
    DeletionPolicy: Retain
    Metadata:
      aws:cdk:path: HelloCdkStack/MyFirstBucket/Resource
  CDKMetadata:
    Type: AWS::CDK::Metadata
    Properties:
      Modules: aws-cdk=1.51.0,@aws-cdk/aws-events=1.63.0,@aws-cdk/aws-iam=1.63.0,@aws-cdk/aws-kms=1.63.0,@aws-cdk/aws-s3=1.63.0,@aws-cdk/cloud-assembly-schema=1.63.0,@aws-cdk/core=1.63.0,@aws-cdk/cx-api=1.63.0,@aws-cdk/region-info=1.63.0,jsii-runtime=node.js/v12.14.0
    Condition: CDKMetadataAvailable
Conditions:
  CDKMetadataAvailable:
    Fn::Or:
      - Fn::Or:
          - 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::Equals:
              - Ref: AWS::Region
              - eu-central-1
      - Fn::Or:
          - Fn::Equals:
              - Ref: AWS::Region
              - eu-north-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
              - me-south-1
          - Fn::Equals:
              - Ref: AWS::Region
              - sa-east-1
          - 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

今回のCDKテンプレートをデプロイするとMyFirstBucketB8884501という論理名でS3バケットのリソースが定義されたCloudFormationテンプレートが作られるようです。

スタックのデプロイ

CDKデプロイのスタックはcdk deployコマンドにより実施します。

スタックをデプロイする際には、デプロイ先のAWSアカウントの認証情報とAWSリージョンが指定されている必要があります。今回は次の記事のワンライナーを使用してAssumeRoleしたAWSアカウントの情報を環境変数に設定しました。

スタックのデプロイを実施してみます。

% cdk deploy
HelloCdkStack: deploying...
HelloCdkStack: creating CloudFormation changeset...





 ✅  HelloCdkStack

Stack ARN:
arn:aws:cloudformation:ap-northeast-1:XXXXXXXXXXXX:stack/HelloCdkStack/e757fa20-f80c-11ea-8ef6-0af1581a9dde

スタックが正常に作成できました。

% aws s3 ls 
2020-09-16 20:08:23 hellocdkstack-myfirstbucketb8884501-1ejjv9zhl0qpu

バケットもちゃんと作成できているようです。

CDK Appの修正

デプロイ済みのCDKスタックを更新してみます。

スタックHelloCdkStackのS3バケットの定義を修正します。

hello-cdk/lib/hello-cdk-stack.ts

import * as core from "@aws-cdk/core";
import * as s3 from "@aws-cdk/aws-s3";

export class HelloCdkStack extends core.Stack {
  constructor(scope: core.App, id: string, props?: core.StackProps) {
    super(scope, id, props);

    new s3.Bucket(this, "MyFirstBucket", {
      versioned: true,
      removalPolicy: core.RemovalPolicy.DESTROY,
    });
  }
}

既にデプロイされているスタックと現在のCDKテンプレートの差分はcdk diffコマンドにより確認できます。

% cdk diff
Stack HelloCdkStack
Resources
[~] AWS::S3::Bucket MyFirstBucket MyFirstBucketB8884501 
 ├─ [~] DeletionPolicy
 │   ├─ [-] Retain
 │   └─ [+] Delete
 └─ [~] UpdateReplacePolicy
     ├─ [-] Retain
     └─ [+] Delete

前述のCDKテンプレートの修正により発生するリソースの差分が確認できました。

差分を実際に反映させる場合は再度cdk deployコマンドを実行してスタックのデプロイを行います。

% cdk deploy
HelloCdkStack: deploying...
HelloCdkStack: creating CloudFormation changeset...

 ✅  HelloCdkStack

Stack ARN:
arn:aws:cloudformation:ap-northeast-1:XXXXXXXXXXXX:stack/HelloCdkStack/e757fa20-f80c-11ea-8ef6-0af1581a9dde

再度cdk diffを実行しても差分はないため表示されなくなりました。

% cdk diff
Stack HelloCdkStack
There were no differences

CDK Appの削除

デプロイ済みのCDKスタックを削除する場合はcdk destroyコマンドを使用します。

% cdk destroy
Are you sure you want to delete: HelloCdkStack (y/n)? y
HelloCdkStack: destroying...



 ✅  HelloCdkStack: destroyed

スタックが削除されたのでリソースのS3バケットも削除され見当たらなくなりました。

% aws s3 ls

おわりに

AWS CDKのDeveloper Guideで紹介されているGetting startedチュートリアルをTypeScriptでやってみました。

今後ガンガンCDKを使いこなして行きたいと思います。

参考

以上