AWS CDKを始めるハンズオン ─ IaCの第一歩をAWS LambdaとDynamoDBのシンプルな仕組みで学ぶ

アマゾン ウェブ サービスが提供するIaC(Infrastructure as Code)の開発キットがAWS CDK(AWS Cloud Development Kit)です。本記事はAWS CDK入門者向けのチュートリアルとして、AWSでソリューションアーキテクトを務める吉川幸弘(@WinterYukky)さんによる、AWS Lambda関数でDynamoDBテーブルをスキャンするシンプルなハンズオンです。

AWS CDKを始めるハンズオン ─ IaCの第一歩をAWS LambdaとDynamoDBのシンプルな仕組みで学ぶ

みなさん、こんにちは。アマゾン ウェブ サービス ジャパン合同会社でソリューションアーキテクトを務めている吉川幸弘と申します。私は普段、西日本のお客様を中心に技術的なご支援や課題解決などをしています。

さっそくですが、みなさんはInfrastructure as Code(IaC)という概念をご存じでしょうか。IaCは読んで字の如く、インフラストラクチャをコードとして管理できる仕組みです。インフラストラクチャをコードとして管理することで、いくつものメリットが生まれます。

例えばGitなどのバージョン管理の仕組みを利用することで、差分によるインフラの変更を可視化できます。また、コードから環境を構築することで、再現性を持たせつつ速やかにインフラ環境を構築することもできます。最近では、デジタル庁の発信する「政府情報システムにおけるクラウドサービスの適切な利用に係る基本方針」でもIaCを利用したコスト削減が紹介されるほど、ポピュラーなテクノロジーとなりました。

この記事の主役であるAWS Cloud Development Kit(以下、AWS CDK)も、IaCを実現するツールのひとつです。この記事はAWS CDKの入門編ということで、IaCを知らない方がAWS CDKでIaCを始める第一歩になることを目的に、AWS CDKを体験できるコンテンツを用意しています。なお、この記事では「インフラストラクチャ」のことをAWSリソースとして表現します。

なぜAWS CDKなのか

AWS CDKを紹介する前に、そもそもなぜIaCが必要なのかを整理しましょう。

みなさんはこれまで、インフラストラクチャの変更作業のためにExcelなどで作業手順書を作成したことはありませんか。作成したことがない方も、作業手順書を使った手動作業の課題について考えてみてください。作業手順書の通りに検証環境で検証し、その後に本番環境でもう一度同じ手順を実行してリリースするといったフローを実施します。

この作業手順は柔軟性は高いものの、いくつも課題があります。例えば人間が操作する以上、操作ミスなどの人為的ミスが起こる可能性があります。また、作成者以外が理解できない手順書になってしまって属人化する可能性もあります。他にも、変更の継ぎ足しを繰り返してインフラストラクチャ構成が秘伝のタレ化してしまい同じ環境が再現できなくなる、といった課題が考えられます。

そうした課題に困っている場合、IaCを使うことで簡単にこれらの課題を改善できる可能性があります。

冒頭でも簡単に説明しましたが、IaCはインフラストラクチャをコードとして管理できる仕組みです。簡単に表現すると「Webサーバーを3台、ロードバランサーを1台」のような構成情報をコードで定義でき、コマンドなどを通じてクラウド環境などをコードで定義した状態へ変更できます。

一度デプロイした後も、コードにリソースの定義を追加して再度デプロイすれば追加したリソースが作られます。同様に、不要になったリソースをコードから削除してデプロイすれば、そのリソースが削除されます。これにより誰が実行しても同じ状態にでき、現在あるべき構成もコードから把握および再現させることができます。

IaCについての説明が長くなってしまいましたが、AWS CDKもまたIaCを実現するツールのひとつです。AWS CDKは、TypeScriptやJavaなどポピュラーなプログラミング言語で記述でき、使い慣れたIDEやツール、言語知識をそのまま流用できます。2023年3月時点では、JavaScript、TypeScript、Python、Java、.NET、Goをサポートしています。これらのプログラミング言語を使えることで、型チェックや自動テストの仕組みも利用でき、コードを書いてすぐフィードバックを得ることができます。

ほかにもAWS Lambda関数のメモリサイズなど、膨大なリソースの設定値を全て設定せずとも、ベストプラクティスに沿ったデフォルト値が設定される特徴があります。デフォルト値が設定されていることによって、少ない記述量で構築できます。逆に、設定値を細かくカスタマイズしたい場合に使えるエスケープハッチもあり、抽象化のメリットがありながらも幅広いニーズに応える実用性も兼ね備えています。

こうした特徴から、私はIaCをこれから学びたい方へAWS CDKをお勧めしています。

AWS CDKを体験してみよう

百聞は一見に如かずと言いますが、実際に触ってみることが理解への近道です。今回はTypeScriptのAWS CDKを使って、次のようなAmazon DynamoDBテーブルからScanした結果を返すAWS Lambda関数をデプロイしてみましょう。

cdk1

開発環境のセットアップ

AWS CDKを利用するには、Node.js、AWS CDK Toolkit(CLIとも呼ばれます)、AWS認証情報が必要です。次のドキュメントを参考にセットアップしてみてください。

AWS CDKの開始方法 - 前提条件 - AWS CDK v2開発者ガイド

この記事の環境は、以下のバージョン※1で実施しています。

$ node -v
v18.13.0

$ npx aws-cdk@2 --version
2.68.0 (build 25fda51)

またこの記事では、次のようにaws-cdk-exampleディレクトリで作業しています。カレントディレクトリ名は自動生成されるファイル名に影響するので、可能であればaws-cdk-exampleというディレクトリを作成して作業してください。

$ pwd
/<任意の作業ディレクトリ>

$ mkdir aws-cdk-example
$ cd aws-cdk-example

さらにIDEにはVSCodeを利用しますが、みなさんはお好みのIDEをお使いください。


※1: npx cdk --versionとする例も見受けられますが、このcdkパッケージはaws-cdkパッケージへリダイレクトするような補完パッケージです。入力誤りを防いでくれる側面もありますが、不要なパッケージがインストールされることになるので、本記事ではaws-cdkパッケージをインストールしています。

具体的には、次のrequire('aws-cdk/bin/cdk')だけのパッケージがnpmで配布されています。npm のコードタブから/cdk/bin/cdkにアクセスすると、コードの中身が確認できます。

#!/usr/bin/env node
require('aws-cdk/bin/cdk');

AWS CDK Toolkitとソースコードの関係性

開発環境がセットアップできたら、まずプロジェクトを初期化しますが、その前にAWS CDK Toolkitとソースコードの関係性を簡単に説明します。次の図は、開発者がAWS CDK Toolkitを用いて、AWSリソースをデプロイするイメージです。

cdk2

現段階で詳細を把握する必要はありませんが、開発者が操作しているのがソースコードとAWS CDK Toolkitであることに注目してください。AWS CDK Toolkitが、デプロイやプロジェクト初期化などの複雑な手順をコマンドで簡単に操作できるようにしてくれるため、開発者はコードの記述に集中できることが分かります。

このようにAWS CDKを使って開発するときは、基本的にソースコードとAWS CDK Toolkitを利用していくことになります。

プロジェクトを初期化する

AWS CDK Toolkitを使って、さっそくプロジェクトを初期化してみましょう。

$ npx aws-cdk@2 init app --language typescript

プロジェクトを初期化すると次のようなフォルダ構成になり、lib/aws-cdk-example-stack.tsといったファイルが作成されます。

$ tree -I node_modules --dirsfirst
.
|-- bin
|   `-- aws-cdk-example.ts
|-- lib
|   `-- aws-cdk-example-stack.ts
|-- test
|   `-- aws-cdk-example.test.ts
|-- README.md
|-- cdk.json
|-- jest.config.js
|-- package-lock.json
|-- package.json
`-- tsconfig.json

lib/aws-cdk-example-stack.tsを開いてみるとStackクラスを継承したクラスが実装されています。このStackクラスを継承したクラスがAWS CloudFormationのスタックを表します。AWS CDKではこのスタックを単位にリソースをデプロイします。

ブートスラップ

AWS CDKを使用してスタックをデプロイするには、事前にCDK専用のAmazon S3バケットを含むいくつかのリソースを利用できるようにしておく必要があります。この操作をブートスラップと呼びます。

これまでAWS CDKを利用したことのない場合は、利用の前にブートストラップする必要があります。ブートストラップはリージョン毎に実施が必要なため、新しいリージョンで実行する際も実施してください。

$ npm run cdk bootstrap

プロジェクトの初期化にはnpx aws-cdkコマンドを利用しましたが、先のコマンドのように初期化後からはプロジェクトにインストールされたAWS CDK Tookitを利用します。これは、プロジェクトに使われているバージョンと異なるバージョンのAWS CDK Toolkitが使われないようにするためです。

AWS Lambda関数をデプロイしてみよう

まずはAWS Lambda関数をデプロイして、次のようなAWS Lambda関数のみの構成を目指します。

cdk3

lib/aws-cdk-example-stack.tsを開いてください。

$ tree -I 'node_modules|cdk.out' --dirsfirst
.
|-- bin
|   `-- aws-cdk-example.ts
|-- lib
|   `-- aws-cdk-example-stack.ts <-- 編集します
|-- test
|   `-- aws-cdk-example.test.ts
|-- README.md
|-- cdk.json
|-- jest.config.js
|-- package-lock.json
|-- package.json
`-- tsconfig.json

初期テンプレートから不要なコメントアウトを取り除くため、lib/aws-cdk-example-stack.tsを次のように編集します。

 import * as cdk from 'aws-cdk-lib';
 import { Construct } from 'constructs';
- // import * as sqs from 'aws-cdk-lib/aws-sqs';

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

-    // The code that defines your stack goes  here
-
-    // example resource
-    // const queue = new sqs.Queue(this,  'AwsCdkExampleQueue', {
-    //   visibilityTimeout: cdk.Duration. seconds(300)
-    // });
   }
 }

AWS CDKの基本的な書き方

これから実際にコードを記述しますが、その前に簡単にAWS CDKの基本的な書き方を紹介します。AWS CDKではリソースなどを含めてコンストラクトと呼ばれるコンポーネント(≒クラス)で定義されており、基本的に次のような形式でコンストラクトを初期化します。

new コンストラクト(スコープ, "id", { // props
    プロパティ名: プロパティ値,
})

初期テンプレートに含まれていたsqs.Queueというコンストラクトに当てはめると次のようになります。

cdk4

第1引数のスコープというのはコンストラクトの親を指定します。これは、どの論理的なリソースグループに所属するかを指定するものですが、今回はスタックの直下にリソースを作るためthisを指定します。

第2引数のidはそのスコープ内でのIDです。コンストラクト内で一意な文字列を指定してください。

第3引数はpropsと呼ばれており、コンストラクト特有のプロパティを設定できます。例えばAWS Lambda関数ではruntimememorySizeといったプロパティが設定できます。

NodejsFunctionコンストラクトの使用

実際にAWS Lambda関数を定義してみましょう。今回は型の恩恵を受けられるように、TypeScriptで記述したAWS Lambda関数をデプロイしたいと思います。しかし、AWS Lambda関数はそのままだとTypeScriptのコードを実行できないため、通常はデプロイする前にJavaScriptへトランスパイルしておく必要があります。

この課題に対してCDKは、NodejsFunctionという便利なコンストラクトを用意しています。このコンストラクトはTypeScriptで記述されたAWS Lambda関数のコードを自動的にバンドル※2して、効率よくデプロイしてくれます。

NodejsFunctionを使ってtsファイルとNode.js 18ランタイムを指定すると、次のようになります。

new NodejsFunction(this, "Function", {
  entry: "lib/hello-world.ts",
  runtime: Runtime.NODEJS_18_X,
});

※2: 複数のJavaScriptやTypeScriptなどのソースコードを1つにまとめることです。

AWS Lambda関数を定義

例に示したAWS Lambda関数を実際に書いてみましょう。まずはAWS Lambda関数のコードから作成します。

lib/hello-world.tsを新規作成します。

$ tree -I 'node_modules|cdk.out' --dirsfirst
.
|-- bin
|   `-- aws-cdk-example.ts
|-- lib
|   |-- aws-cdk-example-stack.ts <-- 次で編集
|   `-- hello-world.ts           <-- 新規作成
|-- test
|   `-- aws-cdk-example.test.ts
|-- README.md
|-- cdk.json
|-- jest.config.js
|-- package-lock.json
|-- package.json
`-- tsconfig.json

コードの内容は、次のようにHello World!という文字列を返す関数にします。

export const handler = async () => "Hello World!";

aws-cdk-example-stack.tsを編集

lib/aws-cdk-example-stack.tsは、次のように修正します。今回はAWS CDKの書き味を体験していただくため、試しにコピー&ペーストしないでコードを記述してみてください。

 import * as cdk from "aws-cdk-lib";
+import { Runtime } from "aws-cdk-lib/aws-lambda";
+import { NodejsFunction } from "aws-cdk-lib/aws-lambda-nodejs";
 import { Construct } from "constructs";

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

+    const func = new NodejsFunction(this, "Function", {
+      entry: "lib/hello-world.ts",
+      runtime: Runtime.NODEJS_18_X,
+    });
   }
 }

コピー&ペーストせずにコードを書くと、IDEのサポートを受けて自動補完されたのではないでしょうか。これも、既存の言語やツールを利用できるAWS CDKのメリットです。

cdk5

なお、今回はentryruntimeというプロパティを設定しましたが、いざ自分で書こうとすると、プロパティをどう設定したらよいか迷ってしまうこともあるでしょう。そのときは、次にaws_lambda_nodejsの表示例を掲載した「AWS CDK Reference Documentation」を参照することをお勧めします。

cdk6

このようにユースケース毎のプロパティ設定方法をOverviewページでドキュメント化しているので、目的から逆引きできます。

esbuildをインストール

作ったAWS Lambda関数をさっそくデプロイしたいところですが、デプロイする前に次のコマンドでesbuildをインストールします。

$ npm install --save-dev esbuild@0

これはNodejsFunctionがTypeScriptをバンドルする際にesbuildを使用するためです※3


※3: esbuildがインストールされていなければDockerが利用されますが、Dockerをインストールするより簡単なため今回はこちらを採用しています。

デプロイしてみよう

それでは次のコマンドで実際にデプロイしましょう。

$ npm run cdk deploy

下図のようにデプロイの確認が表示されたらyで進めてください。

cdk7

しばらくするとデプロイが完了します。

cdk8

Lambdaのサービスページへアクセスしてみる

AWSマネジメントコンソールからLambdaのサービスページへアクセスしてみると、デプロイされたAWS Lambda関数が確認できます。

cdk9

デプロイされたAWS Lambda関数を開いて、テストタブへ移動します。画面に表示されているテストボタンを押して実行してみると、次のように"Hello World!"が出力されるはずです。

cdk10

おめでとうございます! AWS CDKを使ってAWS Lambda関数をデプロイできました。これでAWS CDKの第一歩を踏み出せました。このままでも良いですが、せっかくなので次のセクションから、このAWS Lambda関数をもう少し価値のあるものに変更してみます。

DynamoDBテーブルをデプロイしてみよう

次は、AWS Lambda関数と同様にDynamoDBテーブルを追加して、次のような構成を目指します。

cdk11

lib/aws-cdk-example-stack.tsを開いてください。

$ tree -I 'node_modules|cdk.out' --dirsfirst
.
|-- bin
|   `-- aws-cdk-example.ts
|-- lib
|   |-- aws-cdk-example-stack.ts <-- 編集
|   `-- hello-world.ts
|-- test
|   `-- aws-cdk-example.test.ts
|-- README.md
|-- cdk.json
|-- jest.config.js
|-- package-lock.json
|-- package.json
`-- tsconfig.json

aws-cdk-example-stack.tsを編集

AWS Lambda関数と同様にlib/aws-cdk-example-stack.tsを次のように編集してDynamoDBテーブルを定義します。

 import * as cdk from "aws-cdk-lib";
+import { AttributeType, Table } from "aws-cdk-lib/aws-dynamodb";
 import { Runtime } from "aws-cdk-lib/aws-lambda";
 import { NodejsFunction } from "aws-cdk-lib/aws-lambda-nodejs";
 import { Construct } from "constructs";

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

+    const itemTable = new Table(this, "ItemTable", {
+      partitionKey: {
+        name: "pk",
+        type: AttributeType.STRING,
+      },
+      removalPolicy: cdk.RemovalPolicy.DESTROY,
+    });
     const func = new NodejsFunction(this, "Function", {
       entry: "lib/hello-world.ts",
       runtime: Runtime.NODEJS_18_X,
     });
   }
 }

DynamoDBテーブルには、partitionKeyremovalPolicyのプロパティを設定しています。

partitionKeyはいわゆるテーブルの主キーにあたるもので、pkという文字列型の属性を指定しています。またremovalPolicyは、データベースやAmazon S3バケットのような永続データの維持をするリソースに設定でき、コンストラクトやスタックが破棄されたときにリソースを削除するかどうかを決定します。

今回は、この体験後にみなさんがDynamoDBテーブルを消せるようにRemovalPolicy.DESTROYを指定していますが、ご自身の環境でリソースを扱う際は注意して設定してください。RemovalPolicyについては次のドキュメントから確認できます。

リソース - 削除ポリシー - AWS CDK v2開発者ガイド

デプロイして確認

再度デプロイしましょう。

$ npm run cdk deploy

デプロイ完了後、マネジメントコンソールから確認すると、DynamoDBテーブルが作成されています。

cdk12

暗号化などの設定方法を知りたい場合は、AWS Lambda関数と同様にAWS CDK Reference Documentationを参照してください。

aws-cdk-lib.aws_dynamodb module - AWS CDK Reference Documentation

AWS Lambda関数からDynamoDBテーブルのデータを読み取ろう

体験も最終セクションです。これまでのセクションでAWS Lambda関数とDynamoDBテーブルを作成しました。このセクションではAWS Lambda関数を変更して、DynamoDBテーブルのアイテムをScanする仕組みにします。

cdk13

テーブルへの読み取りアクセスを許可

そのためにはまず、DynamoDBテーブルへの読み取りアクセスを、AWS Lambda関数に許可する必要があります。CDKでは次のようにgrantから始まるメソッドで、アクセスを許可できます。

アクセスされるリソース.grantXxx(アクセスを許可するリソース)

grantXxxXxx部分はgrantReadのようにアクションを意味する名称が入ります。どのようなメソッドがあるかはIDEの自動補完やAWS CDK Reference Documentationのコンストラクトページで確認できます。

class Table (construct) - Methods - AWS CDK Reference Documentation

先ほど作ったAWS Lambda関数とDynamoDBテーブルで実践してみましょう。lib/aws-cdk-example-stack.tsを開いてください。

$ tree -I 'node_modules|cdk.out' --dirsfirst
.
|-- bin
|   `-- aws-cdk-example.ts
|-- lib
|   |-- aws-cdk-example-stack.ts <-- 編集
|   `-- hello-world.ts
|-- test
|   `-- aws-cdk-example.test.ts
|-- README.md
|-- cdk.json
|-- jest.config.js
|-- package-lock.json
|-- package.json
`-- tsconfig.json

lib/aws-cdk-example-stack.tsを次のように編集します。

 import * as cdk from "aws-cdk-lib";
 import { AttributeType, Table } from "aws-cdk-lib/aws-dynamodb";
 import { Runtime } from "aws-cdk-lib/aws-lambda";
 import { NodejsFunction } from "aws-cdk-lib/aws-lambda-nodejs";
 import { Construct } from "constructs";

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

     const itemTable = new Table(this, "ItemTable", {
       partitionKey: {
         name: "pk",
         type: AttributeType.STRING,
       },
       removalPolicy: cdk.RemovalPolicy.DESTROY,
     });
     const func = new NodejsFunction(this, "Function", {
       entry: "lib/hello-world.ts",
       runtime: Runtime.NODEJS_18_X,
     });
+    itemTable.grantReadData(func);
   }
 }

変更を確認してデプロイしてみる

この状態でデプロイすると何が起こるのか確認してみましょう。次のコマンドで、デプロイする前に変更を確認できます。

$ npm run cdk diff

cdk diffコマンドを実行すると、次のような出力が得られます。

cdk14

出力内容から、AWS Lambda関数にDynamoDBテーブルへの読み取りアクセス許可ポリシーが付与されていることがわかります。このようにgrantメソッドを利用することで、最小権限の原則に沿った実装が簡単に実現できます。

デプロイしてみましょう。

$ npm run cdk deploy

cdk15

デプロイが完了しました。

DynamoDBテーブルのアイテムをScanするコードを記述

それではDynamoDBテーブルのアイテムをScanするように、AWS Lambda関数のコードを変更していきましょう。今回はScanするためにAWS SDK for JavaScript v3を利用します。

AWS SDK for JavaScriptは、AWSのサービスを簡単に呼び出すことができるライブラリです。次のコマンドでインストールします。

$ npm install @aws-sdk/client-dynamodb

AWS Lambda関数のコードを編集するために、lib/hello-world.tsを開いてください。

$ tree -I 'node_modules|cdk.out' --dirsfirst
.
|-- bin
|   `-- aws-cdk-example.ts
|-- lib
|   |-- aws-cdk-example-stack.ts <-- 後で編集
|   `-- hello-world.ts           <-- 今から編集
|-- test
|   `-- aws-cdk-example.test.ts
|-- README.md
|-- cdk.json
|-- jest.config.js
|-- package-lock.json
|-- package.json
`-- tsconfig.json

lib/hello-world.tsの内容をすべて削除し、次のように編集します。

import { DynamoDBClient, ScanCommand } from "@aws-sdk/client-dynamodb";

const ddbClient = new DynamoDBClient({});

const listItems = async (tableName: string) => {
  const command = new ScanCommand({
    TableName: tableName,
  });
  return (await ddbClient.send(command)).Items;
};

export const handler = async () => {
  // DynamoDB テーブルの名前は環境変数から取得する
  const itemTableName = process.env.ITEM_TABLE_NAME!;
  return await listItems(itemTableName);
};

process.envは、Node.jsで環境変数の値を参照する方法です。今回はITEM_TABLE_NAMEという環境変数から取得する仕組みにしました。

aws-cdk-example-stack.tsを編集

上記で説明したように、AWS Lambda関数のITEM_TABLE_NAMEという環境変数に、DynamoDBテーブルのテーブル名を設定する必要があります。こちらもCDKから直感的に設定が可能です。

lib/aws-cdk-example-stack.tsを次のように編集します。

 import * as cdk from "aws-cdk-lib";
 import { AttributeType, Table } from "aws-cdk-lib/aws-dynamodb";
 import { Runtime } from "aws-cdk-lib/aws-lambda";
 import { NodejsFunction } from "aws-cdk-lib/aws-lambda-nodejs";
 import { Construct } from "constructs";

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

     const itemTable = new Table(this, "ItemTable", {
       partitionKey: {
         name: "pk",
         type: AttributeType.STRING,
       },
       removalPolicy: cdk.RemovalPolicy.DESTROY,
     });
     const func = new NodejsFunction(this, "Function", {
       entry: "lib/hello-world.ts",
       runtime: Runtime.NODEJS_18_X,
+      environment: {
+        ITEM_TABLE_NAME: itemTable.tableName,
+      },
     });
     itemTable.grantReadData(func);
   }
 }

hotswapオプションでデプロイ

このままこれまでと同じようにデプロイしてもよいのですが、ちょっとしたTipsとして、ここでhotswapオプションを紹介しておきます。

hotswapdeployコマンドのオプションで、--hotswapもしくは--hotswap-fallback※4をつけることで、高速にデプロイできます。これはAWS CDK ToolkitがCloudFormationチェンジセットを生成してデプロイする代わりに、AWSリソースを直接更新してくれるためです。

次のコマンドでホットスワップデプロイしてみましょう。

$ npm run cdk deploy -- --hotswap-fallback

cdk16

わずか2.9秒でデプロイが完了しました。ほかにもcdk watchのようにファイル変更を監視して自動的にデプロイしてくれるコマンドもあります。詳しくはAWS CDK ToolkitのREADMEをご覧ください。

なお注意点として、ホットスワップは開発用の機能です。そのため本番環境には利用しないでください。本番環境にはCI/CDを用いて、手動でデプロイしないことをお勧めします。また、すべてのリソースには対応していないため※5、どのリソースでも高速にデプロイできるわけではありません。こちらもご注意ください。


※4: --hotswap--hotswap-fallbackでは、ホットスワップデプロイできないリソースがあった際の挙動が異なります。ホットスワップデプロイできないリソースがあった場合に、--hotswapは無視しますが、--hotswap-fallbackは自動で通常のデプロイに切り替わります。

※5: ホットスワップデプロイできるリソースの種類については、AWS CDK ToolkitのREADME.mdをご確認ください。

テスト実行

それではマネジメントコンソールから、DynamoDBテーブルに任意のデータを登録して、AWS Lambda関数をテスト実行してみましょう。

下図のような実行結果が表示されれば成功です。

cdk17

リソース削除

最後に、今回作成したリソースを削除します。IaCで管理していると、検証したリソースの削除も簡単です。次のコマンドで削除が可能です。

$ npm run cdk destroy

削除の確認にyで答えると、自動的にリソースが削除されます。

cdk18

お疲れさまでした。以上で体験は終了です。

初心者からよくされる質問

初心者からよくされる質問を簡単にピックアップしてみました。

Q.1 言語は何を使えばよいですか?

A. ドキュメントが見やすいので個人的にはTypeScript推しですが、どの言語を利用しても大丈夫です。

言語を選ぶ基準として「開発しているアプリケーション言語と合わせる」ことや「メンバーが慣れている言語で書く」ことが考えられます。チームで相談して、自分たちにマッチする言語を選んでください。

Q.2 AWS CDKはどんな人に向いていますか?

A. インフラエンジニア、アプリケーションエンジニアを問わず利用できます。

アプリケーションエンジニアからすると、使い慣れたツールや言語知識をそのまま利用できるため、インフラ知識のギャップを言語の型情報などから埋めることも可能です。逆にインフラエンジニアからすると、自動補完の効く書きやすい設定ファイルのような感覚で記述できます。これはAWS CDKがアプリケーションのような複雑なコードを書く必要がなく、深い言語知識を必要としていないためです。

インフラエンジニアとアプリケーションエンジニアの両者が利用しやすいということは、それぞれの役割が完全なサイロ化されることを防ぎ、DevOpsの実現を加速させることも可能です。

Q.3 スタックの分け方はどうすればよいですか?

A. スタックを分けるべき理由がない場合は、ひとつのスタックで管理することを検討してください。

スタックを分けずに運用したほうがシンプルで簡単になります。コード量が増えて可読性の低下を危惧する場合は、スタックではなくコンストラクトを分離する方法が考えられます。独自のコンストラクトを別のファイルで作成して管理することで可読性と再利用性を確保できます。

以上、初心者によくある質問をピックアップしてみました。ほかにもCDKを利用する上でのベストプラクティスが公式ドキュメントにまとめられています。よろしければこちらもご覧ください。

AWS CDKによるクラウドインフラストラクチャの開発と導入のベストプラクティス

終わりにー次のステップは

今回は、AWS Lambda関数でDynamoDBテーブルをScanするだけの、非常にシンプルな仕組みを作成しました。コンストラクトを作る話など、本稿ではお伝えできなかった部分も多くあります。

次のステップとして、このハンズオンより深い内容に触れている「AWS CDK Workshop」や「TypeScriptの基礎から始めるAWS CDK開発入門」といったワークショップがあります。今回触れられなかったコンストラクトを作る部分や、そもそもTypeScriptについて学ぶことから始められます。この記事でAWS CDKの魅力を少しでも感じられた方は、ぜひこれらのワークショップにも挑戦してみてください。

吉川 幸弘(YOSHIKAWA Yukihiro) GitHub: WinterYukky / Twitter: @WinterYukky

cdk19
AWS CDKが大好きな大阪のエンジニア。社会人2年目で立ち上げから参加したSI企業の成長に、AWSを利用したWebアプリケーション開発で尽力する。AWSの日本コミュニティであるJAWS-UGで、他数名と共にCDK支部を設立。2022年末にアマゾン ウェブ サービス ジャパン合同会社に転職し、現在はソリューションアーキテクトを務める。

編集:中薗 昴
制作:はてな編集部

若手ハイキャリアのスカウト転職