AWS CDK 使ってみた! (Pythonでインフラ構築)

はじめに

あけましておめでとうございます、SCSKの根岸です。

近頃はAWS CloudformationやTerraformによるコードでのインフラ管理もスタンダードになりつつありますが、面倒くさがりの私はそれらのテンプレートですら「楽して書けたらいいのになあ…」と正月のこたつの中で思っていました。

Cloudformationの場合、テンプレートはyamlかjsonの形式で作成しますが記載しなくてはならない量がそこそこ多く大変です。

そんな中、ネットの海で見つけたのがAWS CDKでした。「これは…!」と思いさらに調べてみたところ、ちょうど良さそうなハンズオン(summit-online-japan-cdk)がありましたのでこちらに挑戦してみました。

この記事にはハンズオンのページには記載されていない補足情報(「ここの手順はこうやったらいまくいったよ~」等)も記載していますので、お時間ある方はぜひ一緒に挑戦してみましょう!

AWS CDKの概要

AWS CDKとは

そもそもAWS CDK(以下、CDKと記載)とは何なのか、公式ページには以下のように記載されています。

AWS Cloud Development Kit (AWS CDK) は、使い慣れたプログラミング言語を使用してクラウドアプリケーションリソースを定義するためのオープンソースのソフトウェア開発フレームワークです。(引用元 – AWS クラウド開発キット – アマゾン ウェブ サービス)

詳細は公式ページを参照いただきたいのですが、簡単にまとめるとyamlやjsonではない使い慣れたプログラミング言語でAmazon Web Services(AWS)のリソースを定義できるツールと言うことができます。現在はTypeScript、JavaScript、Python、Java、C#、Goの6つのプログラミング言語が対応しているようです。

プログラミング言語で記載されたリソースの定義はCDKツールによって最終的にCloudformationのテンプレートに変換されて実際の環境にデプロイされていきます。

CDKのメリット

CDKのメリットはいろいろありますが個人的なお気に入りポイントは以下の通りです。

(参考 – 20200303 AWS Black Belt Online Seminar AWS Cloud Development Kit (CDK))

一般のプログラミング言語が使える

もともとプログラミング言語に詳しいユーザはその知識をそのまま生かせますし、どちらかと言うと私みたいにプログラミングに疎いユーザはインフラの構築と一緒にプログラミングの勉強もできちゃいます。

エディタによる型チェック、サジェスト、API仕様の参照が可能

エディタの機能によってコードの記載もスムーズに行うことができます。

一般にコード量が少なくなる

ここが超おすすめポイントです!

なんとCDKでは必要最低限の記載と自分が重要だと思う設定をしっかり記載すれば、その他のこだわらない設定についてCDK側がすべていい感じに設定してくれるのです。その分だけユーザ側で書かなくてはならないコード量が減るというわけです。

言葉だけだと説明しづらい部分もありますので、実際に下記のハンズオンに挑戦してみましょう!

AWS CDK Intro Workshopをやってみよう (準備編)

実際にCDKによる前にハンズオンの環境を整えていきましょう。

ハンズオンの環境について

今回は「AWS Cloud9」をハンズオンの環境として採用します。Amazon Elastic Compute Cloud(Amazon EC2)でインスタンスを自分で作成して試したり、ローカルにdockerコンテナを作成して試したりしましたが、AWS Cloud9であれば必要なツールのほとんどが最初からインストールされているため手軽にハンズオンを実施することができます。また、今回は掲題の通りPythonでCDKを使用してみたいと思います。

CDKに必要なツールは以下の通りです。

必要なツール 今回の記事で利用しているバージョン・その他備考
AWS CLI 1.19.112 AWS Cloud9に初期状態でインストール済み
Node.js v16.13.1 AWS Cloud9に初期状態でインストール済み
AWS CDKツールキット 2.3.0
AWS Cloud9にv1が初期状態でインストール済みだが
今回はv2を新たにインストールして使用
Python 3.7.4

AWS Cloud9環境の起動

コンソール画面からAWS Cloud9を選択します。

Cloud9の検索

Cloud9の開始

名前はなんとなくで大丈夫です。ここでは「cdk-handson」と入れています。

Cloud9の環境名

今回はSSM経由でコンソールにログインしたかったので、「Create a new no-ingress EC2 ~」を選択しています。その他はデフォルトのままで進めました。EC2インスタンスを作成するVPCを選択した場合は画面下部の方から設定できます。

Cloud9の設定

設定完了後、数分待つとAWS Cloud9の環境が立ち上がりました!

Cloug9環境の完成

必要なツールの確認

下記の4つのコマンドを打って必要なツールが念のためインストールされているかを確認します。cdkはすでにバージョン1がインストールされていますが、今回はバージョン2を使っていきたいのでバージョン1を削除してバージョン2をインストールしていきます。

$ aws –version
aws-cli/1.19.112 Python/2.7.18 Linux/4.14.256-197.484.amzn2.x86_64 botocore/1.20.112
$ node -v
v16.13.1
$ cdk –version
1.135.0 (build 3825f59)
$ python –version
Python 3.7.10
この状態でcdkのインストールコマンドを打っても下記のように怒られます。エラー文に書いてある通り、「/home/ec2-user/.nvm/versions/node/v16.13.1/bin/cdk」を削除してあげてからもう一度cdkのインストールコマンドを打ちます。

$ npm install -g aws-cdk
npm notice
npm notice New minor version of npm available! 8.1.2 -> 8.3.0
npm notice Changelog: https://github.com/npm/cli/releases/tag/v8.3.0
npm notice Run npm install -g npm@8.3.0 to update!
npm notice
npm ERR! code EEXIST
npm ERR! path /home/ec2-user/.nvm/versions/node/v16.13.1/bin/cdk
npm ERR! EEXIST: file already exists
npm ERR! File exists: /home/ec2-user/.nvm/versions/node/v16.13.1/bin/cdk
npm ERR! Remove the existing file and try again, or run npm
npm ERR! with –force to overwrite files recklessly.

npm ERR! A complete log of this run can be found in:
npm ERR! /home/ec2-user/.npm/_logs/2022-01-03T13_04_19_636Z-debug.log

$ rm /home/ec2-user/.nvm/versions/node/v16.13.1/bin/cdk
$ npm install -g aws-cdk

added 198 packages, and audited 199 packages in 6s

found 0 vulnerabilities
$ cdk –version
2.3.0 (build beaa5b2)

OKですね!cdkバージョンが2.3になりました。

なお、自分で作成したAmazon EC2やローカルでCDKを実行する場合はAWS認証情報の設定が必要になります。下記コマンドを実行して認証情報を設定してください。今回のようにAWS Cloud9を利用する場合は、権限周りはAWS Cloud9がよしなにしてくれるので改めての権限設定は不要です。

$ aws configure

プロジェクトディレクトリの作成

ハンズオンの資料に沿って進めていきます。ディレクトリを作成し移動します。

$ mkdir cdk-workshop && cd cdk-workshop
cdk initコマンドでプロジェクトを作成します。実行するといろいろ出てきますが気にしなくても大丈夫です。(virtualenvによる仮想環境もここで自動作成されています。)
$cdk init sample-app –language python
Applying project template sample-app for python                                            

# Welcome to your CDK Python project!

You should explore the contents of this project. It demonstrates a CDK app with an instance of a stack (`cdk_workshop_stack`)
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.

This project is set up like a standard Python project. The initialization process also creates
a virtualenv within this project, stored under the .venv directory. To create the virtualenv
it assumes that there is a `python3` executable in your path with access to the `venv` package.
If for any reason the automatic creation of the virtualenv fails, you can create the virtualenv
manually once the init process completes.

To manually create a virtualenv on MacOS and Linux:

“`
$ python3 -m venv .venv
“`

After the init process completes and the virtualenv is created, you can use the following
step to activate your virtualenv.

“`
$ source .venv/bin/activate
“`

If you are a Windows platform, you would activate the virtualenv like this:

“`
% .venv\Scripts\activate.bat
“`

Once the virtualenv is activated, you can install the required dependencies.

“`
$ pip install -r requirements.txt
“`

At this point you can now synthesize the CloudFormation template for this code.

“`
$ cdk synth
“`

You can now begin exploring the source code, contained in the hello directory.
There is also a very trivial test included that can be run like this:

“`
$ pytest
“`

To add additional dependencies, for example other CDK libraries, just add to
your requirements.txt file and rerun the `pip install -r requirements.txt`
command.

## Useful commands

* `cdk ls` list all stacks in the app
* `cdk synth` emits the synthesized CloudFormation template
* `cdk deploy` deploy this stack to your default AWS account/region
* `cdk diff` compare deployed stack with current state
* `cdk docs` open CDK documentation

Enjoy!

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>
Please run ‘python3 -m venv .venv’!
Executing Creating virtualenv…
✅ All done!

Virtualenvのアクティブ化

上述の通り、cdk initコマンドによってすでに仮想環境は作成されていますので下記のコマンドでアクティベートします。資料には.envと記載がありますが、今回実際に作成されている仮想環境は.venvなのでその点が異なります。成功すると、コマンドラインの先頭に(.venv)とつくようになります。

$ source .venv/bin/activate
仮想環境をアクティベートしている状態で、aws-cdk-libとconstructsをインストールしていきます。フォルダ内にrequirement.txtが用意してあるので下記のコマンドを実行してインストールしていきます。
$ pip install -r requirements.txt
Collecting aws-cdk-lib==2.3.0
Downloading aws_cdk_lib-2.3.0-py3-none-any.whl (57.6 MB)
|████████████████████████████████| 57.6 MB 33 kB/s
Collecting constructs<11.0.0,>=10.0.0
Downloading constructs-10.0.23-py3-none-any.whl (50 kB)
|████████████████████████████████| 50 kB 10.5 MB/s
Collecting jsii<2.0.0,>=1.47.0
Downloading jsii-1.50.0-py3-none-any.whl (382 kB)
|████████████████████████████████| 382 kB 22.7 MB/s
Collecting publication>=0.0.3
Downloading publication-0.0.3-py2.py3-none-any.whl (7.7 kB)
Collecting typing-extensions<5.0,>=3.7
Downloading typing_extensions-4.0.1-py3-none-any.whl (22 kB)
Collecting cattrs<1.10,>=1.8; python_version >= “3.7”
Downloading cattrs-1.9.0-py3-none-any.whl (25 kB)
Collecting python-dateutil
Downloading python_dateutil-2.8.2-py2.py3-none-any.whl (247 kB)
|████████████████████████████████| 247 kB 24.7 MB/s
Collecting attrs~=21.2
Downloading attrs-21.4.0-py2.py3-none-any.whl (60 kB)
|████████████████████████████████| 60 kB 10.0 MB/s
Collecting six>=1.5
Downloading six-1.16.0-py2.py3-none-any.whl (11 kB)
Installing collected packages: publication, typing-extensions, attrs, cattrs, six, python-dateutil, jsii, constructs, aws-cdk-lib
Successfully installed attrs-21.4.0 aws-cdk-lib-2.3.0 cattrs-1.9.0 constructs-10.0.23 jsii-1.50.0 publication-0.0.3 python-dateutil-2.8.2 six-1.16.0 typing-extensions-4.0.1
WARNING: You are using pip version 20.1.1; however, version 21.3.1 is available.
You should consider upgrading via the ‘/home/ec2-user/environment/cdk-workshop/.venv/bin/python3 -m pip install –upgrade pip’ command.

cdk bootstrapの実行

ハンズオンの資料にはもう少し後ろのページで説明されますが、各リージョンにて初めてCDKを利用する場合には下記のコマンドの実行が必要です。

$ cdk bootstrap aws://<アカウント番号>/<リージョン名>

(bootstrapの実行結果の例)
$ cdk bootstrap 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.

こちらのコマンドを実行すると、リージョン内のCloudformationで「CDKToolkit」というテンプレートが適用されます。これにより、リージョン内にCDKを利用するために必要なロール、ECR、Amazon Simple Storage Service(Amazon S3)バケットなどが作成されます。

CDKToolkitのデプロイ

すでに「CDKToolkit」が適用されているリージョンでは再度実行する必要はありません。ただ、すでに「CDKToolkit」が適用されているリージョンで再度bootstrapを実行しても特に悪いことは起きないのでCDKを使いたいときはとりあえず一度実行してみる感じでいいと思います。

(再度bootstrapを実行した結果の例)
$ cdk bootstrap aws://123456789012/ap-northeast-1
⏳ 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.
✅ Environmentaws://123456789012/ap-northeast-1 bootstrapped (no changes).

AWS CDK Intro Workshopをやってみよう (サンプルコード編)

これにて準備は完了です、お疲れ様でした!

いよいよこの章からCDKを触っていきます。

サンプルコードをcdk synthしてみる

cdk_workshop/cdk_workshop_stack.pyを開いてみましょう。どのようなAWSリソースを構築していきたいかについては主にこちらのファイルの「super().__init__(scope, construct_id, **kwargs)」以降に書いていくことになります。

このファイルにはすでにサンプルコードとしてSQSキューとSNSトピックの設定が記載されています。10行にも満たない記述量ですね。

from constructs import Construct
from aws_cdk import (
    Duration,
    Stack,
    aws_iam as iam,
    aws_sqs as sqs,
    aws_sns as sns,
    aws_sns_subscriptions as subs,
)


class CdkWorkshopStack(Stack):

    def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
        super().__init__(scope, construct_id, **kwargs)
    
        queue = sqs.Queue(
            self, "CdkWorkshopQueue",
            visibility_timeout=Duration.seconds(300),
        )

        topic = sns.Topic(
            self, "CdkWorkshopTopic"
        )

        topic.add_subscription(subs.SqsSubscription(queue))

ここでcdk synthコマンドを実行してみましょう。なお、cdkコマンドはcdk.jsonファイルが存在するルートディレクトリのみで実行できます。cdkコマンド実行時にエラーが出た場合は確認してみましょう。

$ cdk synth
cdk synthコマンドを実行すると、cdk_workshop_stack.pyに記載されている内容がCloudformationのテンプレート化されたyamlファイルが出力されます。
Resources:
  CdkWorkshopQueue50D9D426:
    Type: AWS::SQS::Queue
    Properties:
      VisibilityTimeout: 300
    UpdateReplacePolicy: Delete
    DeletionPolicy: Delete
    Metadata:
      aws:cdk:path: cdk-workshop/CdkWorkshopQueue/Resource
  CdkWorkshopQueuePolicyAF2494A5:
    Type: AWS::SQS::QueuePolicy
    Properties:
      PolicyDocument:
        Statement:
          - Action: sqs:SendMessage
            Condition:
              ArnEquals:
                aws:SourceArn:
                  Ref: CdkWorkshopTopicD368A42F
            Effect: Allow
            Principal:
              Service: sns.amazonaws.com
            Resource:
              Fn::GetAtt:
                - CdkWorkshopQueue50D9D426
                - Arn
        Version: "2012-10-17"
      Queues:
        - Ref: CdkWorkshopQueue50D9D426
    Metadata:
      aws:cdk:path: cdk-workshop/CdkWorkshopQueue/Policy/Resource
  CdkWorkshopQueuecdkworkshopCdkWorkshopTopicA7BCA841EC3B13D1:
    Type: AWS::SNS::Subscription
    Properties:
      Protocol: sqs
      TopicArn:
        Ref: CdkWorkshopTopicD368A42F
      Endpoint:
        Fn::GetAtt:
          - CdkWorkshopQueue50D9D426
          - Arn
    Metadata:
      aws:cdk:path: cdk-workshop/CdkWorkshopQueue/cdkworkshopCdkWorkshopTopicA7BCA841/Resource
  CdkWorkshopTopicD368A42F:
    Type: AWS::SNS::Topic
    Metadata:
      aws:cdk:path: cdk-workshop/CdkWorkshopTopic/Resource
  CDKMetadata:
    Type: AWS::CDK::Metadata
    Properties:
      Analytics: v2:deflate64:H4sIAAAAAAAA/1WNQQ6CMBBFz8K+HVEWHoALILg3UGocwQ522hjS9O7Skpi4mf//y0vmBBWURf9hqcZJzjhA6FyvJrGhW+A3Q7h47bWo72Yv+TY0o1p/cJ9RsNn8zg+sLC4OySTjb19pQZVoLjGm2momb1X+UZMZMZlRNKt7kDlUcIZjWTwZUVpvHL40tHt+AbotFgG9AAAA
    Metadata:
      aws:cdk:path: cdk-workshop/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
              - 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::Or:
          - Fn::Equals:
              - Ref: AWS::Region
              - us-west-1
          - Fn::Equals:
              - Ref: AWS::Region
              - us-west-2
Parameters:
  BootstrapVersion:
    Type: AWS::SSM::Parameter::Value
    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_workshop_stack.pyの記述量のわりにしっかりとしたCloudformationテンプレートが作成されていることがわかります。

サンプルコードをcdk deployしてみる

それでは実際にサンプルコードの内容をデプロイしてみましょう!

$ cdk deploy
CDKでのDeploy
画像の文字が小さく恐縮ですが、変更内容の確認がされます。問題なさそうであれば「y」を入力します。

Do you wish to deploy these changes (y/n)? y
cdk-workshop: deploying…
current credentials could not be used to assume ‘arn:aws:iam::123456789012:role/cdk-hnb659fds-deploy-role-123456789012-ap-northeast-1’, but are for the right account. Proceeding anyway.
[0%] start: Publishing 81eb927eff6f3c9d3bf7eba4529be70e26d340173805072ba87fac4ffe23731c:current_account-current_region
current credentials could not be used to assume ‘arn:aws:iam::123456789012:role/cdk-hnb659fds-file-publishing-role-123456789012-ap-northeast-1’, but are for the right account. Proceeding anyway.
[100%] success: Published 81eb927eff6f3c9d3bf7eba4529be70e26d340173805072ba87fac4ffe23731c:current_account-current_region
cdk-workshop: creating CloudFormation changeset…

✅ cdk-workshop

Stack ARN:
arn:aws:cloudformation:ap-northeast-1:123456789012:stack/cdk-workshop/57227180-6d02-11ec-9a81-06794c0fdd17

デプロイが完了しました!コンソール上からCloudformationを確認してみると「cdk-workshop」というテンプレートがデプロイされています。

サンプルコードのデプロイ

サンプルコードの内容を変更してcdk diffしてみる

続いて、せっかく作成したリソースですが内容を変更(すべて削除)してみようと思います。
cdk_workshop/cdk_workshop_stack.pyを開いて下記のように「super().__init__(scope, construct_id, **kwargs)」以降をすべて消してしまいます。変更後はCtr+Sなどでファイルの保存を忘れずに実施しましょう。

from constructs import Construct
from aws_cdk import (
    Duration,
    Stack,
    aws_iam as iam,
    aws_sqs as sqs,
    aws_sns as sns,
    aws_sns_subscriptions as subs,
)


class CdkWorkshopStack(Stack):

    def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
        super().__init__(scope, construct_id, **kwargs)

cdk diffコマンドを実行します。

$ cdk diff
こちらのコマンドを実行すると、現在のcdk_workshop_stack.pyの内容と実際にデプロイされているリソースの差分が表示されます。cdk_workshop_stack.pyのリソース記述部分はすべて消してしまって空っぽなので、「このままdeployすると全部のリソースが消えちゃうよ~」と記載されています。
CDKのdiff
ここでcdk deployを実行してみます。
$ cdk deploy
deployを実行すると既存のCloudformationのスタックがアップデートされ、スタック自体は残っているものの中身のリソースは空っぽの状態になりました。(メタデータだけは残っています)
CDKリソースの変更

AWS CDK Intro Workshopをやってみよう (Hello,CDK!編)

サンプルコード(SQSとSNS)で作成されたリソースを実際に動かすことは無かったのであまりありがたみが実感できませんでしたが、いよいよ実際に動くアプリケーションをデプロイしていきます。

ここでは、簡単な応答を返すAWS Lambda + Amazon API Gatewayを作成していきます。ハンズオン資料ではLambdaの作成、API Gatewayの作成と段階を踏んで進めていますが、この記事ではLambdaとAPIGatewayを一緒にデプロイしてしまいます。

補足:コンストラクタライブラリのインストールについて

ハンズオン資料には下記のようにLambdaとAPI Gatewayのコンストラクタライブラリをインストールするように指示がありますが、この記事に従って進めていただいている場合は個別にコンストラクタライブラリのインストールは不要です。

$ pip install aws-cdk.aws-lambda

$ pip install aws-cdk.aws_apigateway

というのも、こちらの記事に以下のような記載があります。

v1パッケージの体験に関するお客様のフィードバックに基づき、安定したAWSコンストラクトライブラリのすべてをaws-cdk-libという単一のパッケージに統合しました。このパッケージをインストールすることで、すべての安定したAWS CDKコンストラクトにアクセスでき、サードパーティのコンストラクトライブラリも同様にこのパッケージへの依存関係を満たすだけで済みます。(引用 – Experimental construct librariesがAWS CDK v2で利用可能になりました | Amazon Web Services ブログ)

aws-cdk-libの利用は Python内のコードで言うところの「import aws_cdk」の部分と理解しています。(参考)

つまり、この記事では冒頭の準備段階でaws-cdk-lib(2.3.0)をインストール済みで、それを丸ごとimportしている状態なので、個別にLamdaやAPI Gatewayのコントラクタライブラリはインストールしなくても問題ないということです。

ハンズオンで取り扱っているCDKのバージョン記載を見つけることができませんでしたが、おそらくバージョン1を利用しているものと思われます。

今回の検証では個別のコンストラクタライブラリのインストールをしなくても以降の手順で正常にリソースのデプロイができましたので、この記事でもコンストラクタライブラリのインストール手順は割愛させていただきます。

Lambdaのコード作成

ルートディレクトリ(cdk.jsonファイルがあるところと同じ階層)にlambdaディレクトリを作成します。そのlambdaディレクトリの配下に下記の通りhello.pyを作成します。

import json

def handler(event, context):
    print('request: {}'.format(json.dumps(event)))
    return {
        'statusCode': 200,
        'headers': {
            'Content-Type': 'text/plain'
        },
        'body': 'Hello, CDK! You have hit {}\n'.format(event['path'])
    }

cdk_workshop_stack.pyの修正

続いてcdk_workshop_stack.pyを下記の通り修正します。from aws_cdk import 内の宣言を忘れないようにしましょう。

from constructs import Construct
from aws_cdk import (
    Duration,
    Stack,
    aws_lambda as _lambda,
    aws_apigateway as apigw,
)


class CdkWorkshopStack(Stack):

    def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
        super().__init__(scope, construct_id, **kwargs)

        # Defines an AWS Lambda resource
        hello = _lambda.Function(
            self, 'HelloHandler',
            runtime=_lambda.Runtime.PYTHON_3_7,
            code=_lambda.Code.from_asset('lambda'),
            handler='hello.handler',
        )

        apigw.LambdaRestApi(
            self, 'Endpoint',
            handler=hello,
        )

また、code=_lambda.Code.from_asset(‘lambda’)の行ですが、ハンズオン資料ではcode=_lambda.Code.asset(‘lambda’)と記載されている点に注意してください。ハンズオン資料の書き方はバージョン1での書き方のようです。ファイルの更新が完了したら、cdk diffを実行してみましょう。

$ cdk diff
CDKdiff
このままデプロイを実行した場合すごくたくさんのリソースが作成されることがわかります。
cdk_workshop_stack.pyの中身には10行くらいしか書いていないのに…。
 
[+] AWS::IAM::Role HelloHandler/ServiceRole HelloHandlerServiceRole11EF7C63
[+] AWS::Lambda::Function HelloHandler HelloHandler2E4FBA4D
[+] AWS::ApiGateway::RestApi Endpoint EndpointEEF1FD8F
[+] AWS::IAM::Role Endpoint/CloudWatchRole EndpointCloudWatchRoleC3C64E0F
[+] AWS::ApiGateway::Account Endpoint/Account EndpointAccountB8304247
[+] AWS::ApiGateway::Deployment Endpoint/Deployment EndpointDeployment318525DA808eeef0ae3eb0745f2faa622f752de3
[+] AWS::ApiGateway::Stage Endpoint/DeploymentStage.prod EndpointDeploymentStageprodB78BEEA0
[+] AWS::ApiGateway::Resource Endpoint/Default/{proxy+} Endpointproxy39E2174E
[+] AWS::Lambda::Permission Endpoint/Default/{proxy+}/ANY/ApiPermission.cdkworkshopEndpoint424A4D39.ANY..{proxy+} EndpointproxyANYApiPermissioncdkworkshopEndpoint424A4D39ANYproxyED9F30E3
[+] AWS::Lambda::Permission Endpoint/Default/{proxy+}/ANY/ApiPermission.Test.cdkworkshopEndpoint424A4D39.ANY..{proxy+} EndpointproxyANYApiPermissionTestcdkworkshopEndpoint424A4D39ANYproxy4FB922C2
[+] AWS::ApiGateway::Method Endpoint/Default/{proxy+}/ANY EndpointproxyANYC09721C5
[+] AWS::Lambda::Permission Endpoint/Default/ANY/ApiPermission.cdkworkshopEndpoint424A4D39.ANY.. EndpointANYApiPermissioncdkworkshopEndpoint424A4D39ANYC722176D
[+] AWS::Lambda::Permission Endpoint/Default/ANY/ApiPermission.Test.cdkworkshopEndpoint424A4D39.ANY.. EndpointANYApiPermissionTestcdkworkshopEndpoint424A4D39ANYB0C9FB02
[+] AWS::ApiGateway::Method 
 
また、もしよければcdk synthコマンドも実行してみてください。
$ cdk synth
この記事では実行結果は省略しますが、とてつもない量のコードが記載されたyamlファイルが出力されます。
yamlファイルを見ていくとcdk_workshop_stack.py内に明記されていない設定値についてはCDKの方でいい感じに設定してくれていることがとてもよくわかります。スゲー。

Hello,CDKのデプロイ

それでは、いよいよデプロイしてみましょう。変更確認をされたらいつもの通り「y」と入力します。

$ cdk deploy

下記の通りデプロイに成功しました!

アプリケーションのdeploy

しかも、よく見ると出力の最後の方にこのような記述があります。(※この記事では一部伏せています)

Outputs:
cdk-workshop.Endpointxxxxxxxxx = https://xxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/prod/

なんとこちらAPIエンドポイントのURLが出力されています。なんて親切なんだ…。

ブラウザからこのURLにアクセスしてみると無事にアプリケーションからレスポンスがありました!

“Hello, CDK! You’ve hit /”と表示されれば成功です!

サンプルアプリ実行結果

ハンズオンの後片付け

この記事で紹介する部分は以上になります。ハンズオン資料ではこの後コントラクトの作成と続いていきますが、今回はいったんここで一区切りとさせていただきます。(続きを実施した際には、また記事を投稿させていただこうと思っています)

以下、ハンズオン環境の片付けの手順になります。

アプリケーションの削除

下記のコマンドを実行するとアプリケーションのCloudFormationスタックごと削除されます。もしちゃんと削除されているか気になる場合はブラウザからコンソールを開いてCloudFormationのページを見に行ってみましょう。リソースの作成もそうですが、削除も簡単なところがいいですよね。

$ cdk destroy

開発環境の削除

もし不要であればAWS Cloud9の環境も削除しましょう。コンソールからAWS Cloud9のページを開いて、Your environmentから今回作成した環境を選択して「Delete」を選択すれば今回準備した環境はきれいさっぱり削除されます。AWS Cloud9も裏でCloudformationにて作成されており、そちらのスタックごと削除されます。

Cloud9環境の削除

CDKToolkitの削除

CDKToolkitについてもAmazon S3バケットなどに利用料金が本当にわずかながらにかかるので、気になるようであれば削除してもいいかと思います。削除のコマンドも調べてみたのですが見つけることができなかったので、CloudformationにあるCDKToolkitスタックをそのまま削除してしまっていいかと思います。(こちら試せていないのですが、事前にAmazon S3バケットの中身を消しておかないと削除に失敗するかもしれません)

以上を実施すればハンズオンの前の状態に復旧することができます。

おわりに

CDKのハンズオンいかがでしたでしょうか。私自身、Pythonをはじめとするプログラミング言語には疎いので完全に使いこなすにはまだまだ時間がかかりそうですが、それでもCDKのすごさを知ることができました。今回は私の好みでPythonを利用してハンズオンを進めましたが、CDKではTypeScriptを利用するのが主流なようなので、ゼロから学習される方でTypeScriptに抵抗が無ければそちらを学習していったほうがお得かもしれないです。

それでは私はこたつの中に戻ることにします。最後までお読みいただきありがとうございました。

タイトルとURLをコピーしました