Open21

AWS CDK v2をセットアップして試してみる

セットアップ

公式ドキュメントを参考にインストールしてVersionが表示されることを確認する

npm install -g aws-cdk
cdk --version

設定コマンドを実行して対話に答える

aws configure
AWS Access Key ID [None]: *******************
AWS Secret Access Key [None]: *******************
Default region name [ap-northeast-1]: 
Default output format [json]: 

ドキュメントを参考にCDKでアプリをつくる。

まずはGitにリポジトリ「cdk-sam-example」をつくる。

git clone git@github.com:hiyasichuka/cdk-sam-example.git
cd cdk-sam-example
# リポジトリ内を空にした状態でないとエラーがおきる
cdk init app --language typescript

アプリをつくる

既存のファイルを修正する

lib/cdk-sam-example-stack.ts
import { Stack, StackProps } from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as lambda from 'aws-cdk-lib/aws-lambda';

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

    new lambda.Function(this, 'MyFunction', {
      runtime: lambda.Runtime.PYTHON_3_7,
      handler: 'app.lambda_handler',
      code: lambda.Code.fromAsset('./my_function'),
    });
  }
}

ファイルを作成する

mkdir my_func
cd my_func
touch app.py

コードを書く

my_func/app.py
def lambda_handler(event, context):
    return "Hello from SAM and the CDK!"

実行するとエラー

cdk synth --no-staging

--app is required either in command-line, in cdk.json or in ~/.cdk.json

トラブルシュート

CDKセットアップのAWS アカウントのブーストラップをやっていなかったので、やる。

# Get the account ID
aws sts get-caller-identity

# Bootstrap the account
cdk bootstrap aws://59*****/ap-notheast-1

bootstrapにやたら時間がかかる。

ここで解決策が見つかる。
cdk.jsonが無いディレクトリで実行していた。
ディレクトリを移動して再実行する

cd ..
cdk synth --no-staging

以下のエラーが発生。

/root/repos/cdk-sam-example/node_modules/aws-cdk-lib/core/lib/asset-staging.ts:165
      throw new Error(`Cannot find asset at ${this.sourcePath}`);

WSLの環境を整備

# パッケージリストの更新
sudo apt update
# パッケージのアップデート
sudo apt upgrade -y
# 上記で保留されたパッケージのアップデート
sudo apt dist-upgrade -y
# 不要になったパッケージの削除
sudo apt autoremove -y

pythonインストール

sudo apt install python3 python3-pip -y
sudo pip3 install pip -U

AWS CDKをインストール

npm install -g aws-cdk
cdk --version
2.25.0 (build ae1cb4b)

CDKプロジェクトを作成

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 (`CdkWorkshopStack`)
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

Executing npm install...

リソース作成

cdk bootstrap

実行後

 ⏳  Bootstrapping environment aws://************/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://****************/ap-northeast-1 bootstrapped.

デプロイする

cdk deploy
# 質問されるので y と叩く

実行後

CdkWorkshopStack: deploying...
CdkWorkshopStack: creating CloudFormation changeset...



 ✅  CdkWorkshopStack

Stack ARN:
arn:aws:cloudformation:REGION:ACCOUNT-ID:stack/CdkWorkshopStack/STACK-ID

AWSコンソールからCloudFormationを確認する。

スタックができていることを確認。

コードを修正してスタックを掃除する。
lib/cdk-workshop-stack.tsを開いて、以下に修正する。

lib/cdk-workshop-stack.ts
import * as cdk from 'aws-cdk-lib';

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

    // nothing here!
  }
}

差分を確認する

cdk diff

なるほど、リソースがクリアされると

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

Resources
[-] AWS::SQS::Queue CdkWorkshopQueue50D9D426 destroy
[-] AWS::SQS::QueuePolicy CdkWorkshopQueuePolicyAF2494A5 destroy
[-] AWS::SNS::Subscription CdkWorkshopQueueCdkWorkshopStackCdkWorkshopTopicD7BE96438B5AD106 destroy
[-] AWS::SNS::Topic CdkWorkshopTopicD368A42F destroy

再デプロイして、リソースをきれいにする。

cdk deploy

ラムダ関数を準備する。

mkdir lambda 
touch lambda/hello.js
hello.js
exports.handler = async function(event) {
  console.log("request:", JSON.stringify(event, undefined, 2));
  return {
    statusCode: 200,
    headers: { "Content-Type": "text/plain" },
    body: `Hello, CDK! You've hit ${event.path}\n`
  };
};

スタック定義も修正する。

lib/cdk-workshop-stack.ts
import * as cdk from "aws-cdk-lib";
import * as lambda from "aws-cdk-lib/aws-lambda";

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

    // defines an AWS Lambda resource
    const hello = new lambda.Function(this, "HelloHandler", {
      runtime: lambda.Runtime.NODEJS_14_X, // execution environment
      code: lambda.Code.fromAsset("lambda"), // code loaded from "lambda" directory
      handler: "hello.handler", // file is "hello", function is "handler"
    });
  }
}

差分確認してデプロイ

cdk diff
cdk deploy

ラムダ関数が増えている。

Testしてみる。
EventNameをTest、Amazon API Gateway AWS Proxyを選択して保存する。


testを実行すると200レスポンス。
うまくLamndaのAPIコールしてレスポンスが返ってきている。

Lamndaコードを一部修正して、hotswapでデプロイしてみる。

lambda/hello.js
exports.handler = async function(event) {
  console.log("request:", JSON.stringify(event, undefined, 2));
  return {
    statusCode: 200,
    headers: { "Content-Type": "text/plain" },
    body: `Good Afternoon, CDK! You've hit ${event.path}\n`
  };
};
cdk deploy --hotswap

デプロイ時間が短縮された。
しかし、開発環境のみで本番環境では利用しないようにとのこと。

✨  Synthesis time: 4.46s

⚠️ The --hotswap flag deliberately introduces CloudFormation drift to speed up deployments
⚠️ It should only be used for development - never use it for your production Stacks!
CdkWorkshopStack: deploying...
[0%] start: Publishing 3a07baa4cc6b1efaf68de73c5630ea3a355bfd6f994d013461d0ba6b7b398533:current_account-current_region
[0%] start: Publishing 2c87fe9e7ff3aa19e9474c2d0e3380593039a63c0072c08fd37a6670d2f3fe3c:current_account-current_region
[50%] success: Published 3a07baa4cc6b1efaf68de73c5630ea3a355bfd6f994d013461d0ba6b7b398533:current_account-current_region
[100%] success: Published 2c87fe9e7ff3aa19e9474c2d0e3380593039a63c0072c08fd37a6670d2f3fe3c:current_account-current_region

✨ hotswapping resources:
   ✨ Lambda Function 'CdkWorkshopStack-HelloHandler2E4FBA4D-qeSpI5wJF3LK'
✨ Lambda Function 'CdkWorkshopStack-HelloHandler2E4FBA4D-qeSpI5wJF3LK' hotswapped!

 ✅  CdkWorkshopStack

✨  Deployment time: 3.06s

Stack ARN:
arn:aws:cloudformation:ap-northeast-1:598008326305:stack/CdkWorkshopStack/c6df0d80-db0c-11ec-b2e1-0eec3649f2d5

✨  Total time: 7.52s

API Gatawayを追加する

lambda/hello.js
import * as cdk from "aws-cdk-lib";
import * as lambda from "aws-cdk-lib/aws-lambda";
import * as apigw from "aws-cdk-lib/aws-apigateway";

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

    // defines an AWS Lambda resource
    const hello = new lambda.Function(this, "HelloHandler", {
      runtime: lambda.Runtime.NODEJS_14_X, // execution environment
      code: lambda.Code.fromAsset("lambda"), // code loaded from "lambda" directory
      handler: "hello.handler", // file is "hello", function is "handler"
    });
    
    // defines an API Gateway REST API resource backed by our "hello" function.
    new apigw.LambdaRestApi(this, "Endpoint", {
      handler: hello,
    });
  }
}

watchモードでのデプロイ

cdk watch

デプロイ完了後、以下のような出力が得られる。

Outputs:
CdkWorkshopStack.Endpoint8024A810 = https://***z7g.execute-api.ap-northeast-1.amazonaws.com/prod/

ブラウザからURLへアクセスすると文字列が返ってくることを確認。

最後に以下のコマンドによりリソースを開放する。

cdk destroy

以上。

作成者以外のコメントは許可されていません