[AWS CDK] AWS Lambda-backed カスタムリソースは、もう必要ない!(場合もある)
1 はじめに
CX事業本部の平内(SIN)です。
AWS CloudFormation(以下、CFn)では、Lambda関数とカスタムリソースを関連付けて、CFnで記述できないリソースなどを扱うことが出来ます。
しかし、AWS CDK (Cloud Development Kit) は、TypeScript等の言語で記述されるため、AWS SDKをimportしたりして各種のリソースにアクセスする事も可能なので、わざわざ、テンプレートからLambdaを実行しなくても、条件によっては、必要な作業を完了させてしまうことができます。
AWSのドキュメントでは、AWS Lambda-backed カスタムリソースの例として、以下のチュートリアルが紹介されています。
チュートリアル: Amazon マシンイメージ ID を参照する
今回は、上記のような作業を、カスタムリソース無しでAWS CDKで書いてみました。
2 場合もある
最初に、誤解のないように記載させて頂きますが、タイトルにも書いたように 「場合もある」 ということに注意が必要です。
カスタムリソースでは、CFnで、Create/Update/Deleteの各ステージで作業内容を記述できますが、ここでやっていることは、あくまで、Create/Update時の処理であり、スタック削除で、削除が必要なリソースを扱うことはできません。
このような場合は、AWS CDKからでも、素直にカスタムリソースを使用しましょう。
参考:AWS CDK(Cloud Development Kit)を使用したカスタムリソースの利用
3 AWS CDK
下記がコードです。
チュートリアルでは、カスタムリソースのLamdaで処理されていた、最新のAMIのイメージIDを取得する処理は、getAmiId()という関数にしました。
getAmiId()は、awaitで呼び出す必要があるため、AWS CDKのコンストラクタ内で呼び出すことは出来ません。
そこで、CDKでリソースを生成する前にコールしてしまって、取得したイメージIDをCDKのコンストラクタに引数で送っています。
#!/usr/bin/env node import 'source-map-support/register'; import * as aws from 'aws-sdk'; import cdk = require('@aws-cdk/core'); import ec2 = require('@aws-cdk/aws-ec2'); const amiList = [ {id:"PV64", namePattern: "amzn-ami-pv*x86_64-ebs" , owner: "amazon"}, {id:"HVM64", namePattern: "amzn-ami-hvm*x86_64-gp2" , owner: "amazon"}, {id:"HVMG2", namePattern: "amzn-ami-graphics-hvm*x86_64-ebs*" , owner: "679593333241"} ] async function getAmiId(region: string, architecture: "PV64"|"HVM64"|"HVMG2"): Promise<string|undefined> { const ec2 = new aws.EC2({region: region}); const ami = amiList.find(a => {return a.id == architecture})! const describeImagesParams = { Filters: [{ Name: "name", Values: [ami.namePattern]}], Owners: [ami.owner] }; try { const data = await ec2.describeImages(describeImagesParams).promise(); let images = data.Images; if(images){ images.sort(function(x, y) { return y.Name!.localeCompare(x.Name!) }); const target = images.find( i => { return (i.Name!.toLowerCase().indexOf("beta") == -1 && i.Name!.toLowerCase().indexOf(".rc") == -1) } ) if(target){ console.log(JSON.stringify(target)); return target.ImageId; } } } catch (err) { console.log(err); } return undefined; } export class CdkSampleEC2InstanceStack extends cdk.Stack { constructor(scope: cdk.Construct, id: string, amiId: string, props?: cdk.StackProps) { super(scope, id, props); new ec2.CfnInstance(this, "sample-instance" , { imageId: amiId }) } } async function job(){ // イメージIDの取得 const amiId = await getAmiId("ap-northeast-1", "PV64"); if (amiId) { // スタックの生成 const app = new cdk.App(); new CdkSampleEC2InstanceStack(app, 'sampleEC2Instance', amiId); } } job();
4 deploy
以下が、deployの様子です。スタックが作成前に、IMAの情報取得が終わっていることが確認できます。
先の条件では、本日(2019/8/16)時点の最新は、「Amazon Linux AMI 2018.03.0.20190611 x86_64 PV ebs」ということのようです。
5 最後に
CFnでカスタムリースとしてLambdaを呼び出すのは、ちょっと手間のかかる作業かも知れませんが、条件によっては、AWS CDKなら、もっと簡単に書けかも知れないという確認でした。