今回はAWS CDKを使ってLambdaをデプロイしたいと思います。 単一なLambdaをデプロイするところから始まり、最終的には VPCを作成し、その中にLambdaを配置したものをゴールとします。
aws-cdk
をグローバルインストールしましょう。
# aws-cdkをインストール
npm install -g aws-cdk
インストール後にcdk
コマンドが通るかどうか確認します。
以下のコマンドでバージョンが表示されればOKです。
# バージョンの確認
cdk --version
続いて初期化処理です。
まずはcdk-workshop
というディレクトリを作成し、その配下に移動しましょう。
mkdir cdk-workshop && cd cdk-workshop
ここでcdk init
コマンドを実行し、初期化を行います。
オプションでTypescript
を使用することを宣言します。
cdk init sample-app --language typescript
しばらく待つとcdk-workshop
内に各種ディレクトリ・ファイルが作成されると思います。
以下のような構成になっているはずです。
cdk-workshop
デフォルトではAWS SQS
のキューとAWS SNS
のトピックを作成するものとなっているので、ここを書き換えて行きます。
まずはLambda
の作成を行います。
cdk-workshop
の配下にlambda
ディレクトリを作成し、hello.js
ファイルを作成します。
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`,
};
};
作成したhello.js
を使うようにスタックを更新します。
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);
// Lambdaリソースを宣言
const hello = new lambda.Function(this, 'HelloHandler', {
// ランタイムの指定
runtime: lambda.Runtime.NODEJS_14_X,
// lambdaディレクトリを指定
code: lambda.Code.fromAsset('lambda'),
// hello.jsのhandler関数を指定
handler: 'hello.handler'
});
}
}
ここまでの手順で何か誤りがないか確認してみます。 以下のコマンドを実行しましょう。
npm run watch
以下のように表示されればOKです。
Starting compilation in watch mode...
Found 0 errors. Watching for file changes.
npm run watch
はtsc
を用いてTypescript
のファイルをコンパイルし、エラーがあるかどうかを監視しています。
この状態でTS
ファイルを編集すると監視が走り、コンソールが更新されることが分かります。
エラーがないことを確認したら、以下のコマンドでテンプレートを生成してみましょう。
cdk synth
しばらく待つと、cdk.out
というディレクトリが生成されていると思います。
AWS CDK
はAWS
インフラをコードで記載することができますが、最終的にその内容をAWS
に反映させるためにCloud Formation
を使います。
その際に用いるテンプレートを生成するのが今のcdk synth
コマンドです。
cdk.out/CdkWorkshopStack.template.json
を参照すると、Cloud Formation
の形式に従ってテンプレートが生成されていることが分かります。
それでは早速デプロイ...といいたいところですが、まだ準備があります。
先ほど述べたように、デプロイ時にもCloud Formation
を用いるのですが、
そのテンプレートなどを一時的にS3
にアップロードする必要があります。
そのためにブートストラップスタック、というものを用意する必要があります。 「必要がある」とはいっても、実際には下記のコマンドをデプロイの前に実行するだけです。 ※これは「デプロイ先のリージョンごと」に「初回のみ」の手順になります。
cdk bootstrap
実行後S3
のバケットを確認するとcdktoolkit-*****
といった名前のものが作成されているかと思います。
いよいよデプロイです。 下記コマンドを実行しましょう。
cdk deploy
コンソール上に差分(今回は新規作成なので、全て新規)が表示され、確認を経た後でデプロイが行われます。
Cloud Formation
のコンソールでもスタックが作成され、完了後にはLambda
が作成されました。
今度は作成したLambda
に独自で定義した実行ロールを付けて、さらにVPC
の中に配置します。
lib/cdk-workshop-stack.ts
を以下のように修正しましょう。
import * as cdk from 'aws-cdk-lib';
import * as lambda from 'aws-cdk-lib/aws-lambda';
import * as ec2 from 'aws-cdk-lib/aws-ec2';
import * as iam from 'aws-cdk-lib/aws-iam';
export class CdkWorkshopStack extends cdk.Stack {
constructor(scope: cdk.App, id: string, props?: cdk.StackProps) {
super(scope, id, props);
// VPCを宣言
const vpc = new ec2.Vpc(this, 'WorkshopVPC', {
// CIDR
cidr: '10.1.0.0/16',
// PublicとPrivateのサブネットを定義
subnetConfiguration: [
{
cidrMask: 24,
name: 'WorkshopPublicSubnet',
subnetType: ec2.SubnetType.PUBLIC
},
{
cidrMask: 24,
name: 'WorkshopPrivateSubnet',
subnetType: ec2.SubnetType.PRIVATE_ISOLATED
}
]
});
// Lambdaの実行ロールを宣言
const role = new iam.Role(this, 'WorkshopRole', {
// ロール名
roleName: 'workshop-role',
// LambdaサービスからこのロールにAssumeRoleできるよう設定
assumedBy: new iam.ServicePrincipal('lambda.amazonaws.com'),
// ポリシーの宣言
managedPolicies: [
iam.ManagedPolicy.fromAwsManagedPolicyName(
'service-role/AWSLambdaVPCAccessExecutionRole'
),
],
});
// Lambdaリソースを宣言
const hello = new lambda.Function(this, 'HelloHandler', {
// ランタイムの指定
runtime: lambda.Runtime.NODEJS_14_X,
// lambdaディレクトリを指定
code: lambda.Code.fromAsset('lambda'),
// hello.jsのhandler関数を指定
handler: 'hello.handler',
// VPC内に配置
vpc: vpc,
// 実行ロールの設定
role: role,
});
}
}
単一のスタックの記述が長くなりました。
この辺りはCloud Formation
のテンプレートを自身で書く場合と同様に、レイヤーごとなどでスタックを切り分けると管理がしやすくなります。
それでは再度デプロイしてみましょう。
cdk deploy
先ほどと同様の手順通りに進んでいけば、Lambda
がVPC
の中に入り、実行ロールが変わっていることが確認できると思います。
今回はCDK
を使ってVPC
の中にLambda
を配置し、独自に定義した実行ロールを割り当てるところまでの実装を行いました。
実際の運用を考える場合にはLambda
はGitHub
やCodeCommit
などからpull
してきたものを用いるので、cdk deploy
を走らせる前にソースのプルを行う必要があります。
上記のように、実運用する場合には必要な要素がまだ欠けていますが、CDK
に置き換えやすい箇所から順番に置き換えていくと、後々デプロイを自動化しやすくなるのではないかと思いました。
今回の内容が役立ちましたら幸いです。