CDK for TerraformでTypeScriptのLambda関数をデプロイするチュートリアルをやってみた
以下のCDK for TerraformでTypeScriptのLambda関数をデプロイするチュートリアルをやってみたのでレポートします。
このチュートリアルをやってみたきっかけ
以前、「TypeScriptのLambda関数をTerraformだけでデプロイする」というのをやってみました。
やりたかったことは実現できたのですが、ビルド処理を自前で書かないといけない、かつその量が多いのが煩雑だなと感じました。というのもCDKだとaws-cdk-lib.aws_lambda_nodejs
内の NodejsFunction
constructを使えば、ビルド処理を自前で書く必要がなくCDKがよしなにやってくれるからです。
先にこのCDKの手軽さを知っていたので、これに比べるとTerraformは見劣りするなと。
そんな中、「CDK for Terraformでやったらどんな感じになるんだろう」と漠然と興味を持っていて、ちょうどピッタリのチュートリアルを見つけたので、やってみた次第です。なお私はCDK for Terraformは今回初めて触ります。
やってみた
基本的な解説はチュートリアル内で書いてあるので割愛して、その他で気になった点を記載していきます。
Prerequisites
前述の通り今回が初CDK for Terraformだったので、まず以下を先にやりました。
Explore CDKTF application
使用するサンプルリポジトリは以下です。
このサンプルリポジトリは、TerraformStack
クラスを継承したLambdaStack
からインスタンスを2つ作成しています。TerraformStack
子クラスのインスタンス、つまりCDKでいう「スタック」毎にTerraformでいうところの「ルートモジュール」が作成されるみたいですね。
ビルド(トランスパイル)処理はチュートリアル範囲外!
Notice that both Lambda functions contain pre-compiled dist directories, so you do not have to compile them in this tutorial.
?
なんと、このチュートリアルではTypeScript → JavaScriptのトランスパイル処理は対象外でした。確かに/lambda-hello-name/dist/
と/lambda-hello-world/dist/
にトランスパイル後のjsファイルがありますね… 最初に書いたとおりこのあたりの処理がCDK for Terraformでどのように(どれくらい楽に)書けるのか知りたかったのでちょっとガッカリです。(※ ですが、トランスパイル処理も実装している版がこの後登場しますのでお楽しみに)
TerraformAsset construct
コード内でTerraformAsset constructというものを使用しています。
- Assets - CDK for Terraform | Terraform | HashiCorp Developer
- TerraformAsset | API Reference for Typescript | Terraform | HashiCorp Developer
ローカルファイルをコピーしてきたり、指定したディレクトリ以下のファイル群をZIPファイルにまとめたりすることができるConstructです。今回はこれを使ってjsファイルをZIPファイルにまとめてデプロイパッケージを作成しています。
ZIPファイルを作成するというと、Terraformではarchive_file
Data Sourceがあります。archive_file
を使うともちろんZIPファイル化はTerraformレイヤで行われますが、このTerraformAsset constructはその前、つまりCDKがTerraformコードを生成する前に行われます。
View application stacks
npm install
コマンドで以下のようにエラーになったのでNodeのバージョンを変更しました。最初のチュートリアルがv16.13推奨だったのでそれを使うことにしました。
% npm install npm ERR! code EBADENGINE npm ERR! engine Unsupported engine npm ERR! engine Not compatible with your version of node/npm: @jest/console@29.2.1 npm ERR! notsup Not compatible with your version of node/npm: @jest/console@29.2.1 npm ERR! notsup Required: {"node":"^14.15.0 || ^16.10.0 || >=18.0.0"} npm ERR! notsup Actual: {"npm":"8.1.4","node":"v17.2.0"}
Deploy Hello World function
cdktf deploy lambda-hello-world
コマンドを実行すると、見慣れたterraform plan
やterraform apply
時に表示されるdiffが表示されました。ただ違うのは左列にstack名が表示される点です。
cdktf deploy lambda-hello-world lambda-hello-name
のように複数のスタックをまとめてデプロイできて、その際にどのスタックの出力内容なのか識別するためにこのstack名がいるみたいですね。とはいえ出力が混ざるのはわかりにくいですが…
Deploy Hello Name function
特に気になる点はありませんでした。
Clean up resources
以下コマンドで2スタック同時にdestroyしてみました。
% cdktf destroy lambda-hello-world lambda-hello-name
特に問題なくdestory完了しましたが、やはり出力が混ざるのはわかりにくいですね…
Next steps
この章にてfully-integrated
ブランチが紹介されており、こちらでは先程チュートリアル範囲外とお伝えしたビルド(トランスパイル)処理まで含まれているようです!
チェックしていきましょう。
さきほどのコードと大きく異なる点は、NodejsFunction
というクラスのインスタンスを生成している点です。
const helloWorld = new NodejsFunction(this, 'hello-world', { handler: 'index.foo', path: path.join(__dirname, '..', 'lambda-hello-world') }) const helloName = new NodejsFunction(this, 'hello-name', { handler: 'index.foo', path: path.join(__dirname, '..', 'lambda-hello-name') })
このNodejsFunction
クラスは
/cdktf/lib/nodejs-lambda.ts
で定義されています。
クラス名が最初に紹介したCDK(≠CDK for Terraform)のNodejsFunction
と同じなので期待してしまいましたが、同じ役割を担っているわけではないようです。このリポジトリで定義されているCDK for Terraformの方のNodejsFunction
は、esbuildでts→jsへのトランスパイルを行なって、デプロイパッケージ(zipファイル)を作成するだけです。Lambda関数の定義自体はmain.ts
内にありますし、デプロイパッケージのアップロード先S3バケットの定義もmain.ts
内にあります。
エラー発生1
このコードでcdk deploy
するとエラーになりました。
% cdktf deploy lambda-hello-world 0 Stacks deploying 0 Stacks done 0 Stacks waiting Usage Error: The following dependencies are not included in the stacks to run: . Either add them or add the --ignore-missing-stack-dependencies flag.
エラーメッセージに書かれている通り、--ignore-missing-stack-dependencies
フラグを追加しました。
% cdktf deploy lambda-hello-world --ignore-missing-stack-dependencies
エラー発生2
非サポートのNode.jsのバージョンということでエラーになりました。
1 Stack deploying 0 Stacks done 0 Stacks waiting [2022-12-18T15:40:17.974] [ERROR] default - ╷ │ Error: error creating Lambda Function (1): InvalidParameterValueException: The runtime parameter of nodejs10.x is no longer supported for creating or updating AWS Lambda functions. We recommend you use the new runtime (nodejs16.x) while creating or updating functions. │ { │ RespMetadata: { │ StatusCode: 400, │ RequestID: "3edca239-bbbc-4c14-a591-e815a50be01f" │ }, │ Message_: "The runtime parameter of nodejs10.x is no longer supported for creating or updating AWS Lambda functions. We recommend you use the new runtime (nodejs16.x) while creating or updating functions.", │ Type: "User" │ } │ │ with aws_lambda_function.learn-cdktf-lambda, │ on cdk.tf.json line 175, in resource.aws_lambda_function.learn-cdktf-lambda: │ 175: } lambda-hello-world ╷ │ Error: error creating Lambda Function (1): InvalidParameterValueException: The runtime parameter of nodejs10.x is no longer supported for creating or updating AWS Lambda functions. We recommend you use the new runtime (nodejs16.x) while creating or updating functions. │ { │ RespMetadata: { │ StatusCode: 400, │ RequestID: "3edca239-bbbc-4c14-a591-e815a50be01f" │ }, │ Message_: "The runtime parameter of nodejs10.x is no longer supported for creating or updating AWS Lambda functions. We recommend you use the new runtime (nodejs16.x) while creating or updating functions.", │ Type: "User" │ } │ │ with aws_lambda_function.learn-cdktf-lambda (learn-cdktf-lambda), │ on cdk.tf.json line 175, in resource.aws_lambda_function.learn-cdktf-lambda (learn-cdktf-lambda): │ 175: } │ ╵ 1 Stack deploying 0 Stacks done 0 Stacks waiting non-zero exit code 1
このブランチの最終更新は2021年6月で、その後の 2021年7月30日にNode.js 10は非推奨になり新関数作成ができなくなったようです。
mainブランチと同じ14にNode.jsのバージョンを変更して対応しました。
new LambdaStack(app, 'lambda-hello-world', { path: "../lambda-hello-world/dist", handler: "index.handler", - runtime: "nodejs10.x", + runtime: "nodejs14.x", stageName: "hello-world", version: "v0.0.2" }); new LambdaStack(app, 'lambda-hello-name', { path: "../lambda-hello-name/dist", handler: "index.handler", - runtime: "nodejs10.x", + runtime: "nodejs14.x", stageName: "hello-name", version: "v0.0.1" });
感想
CDKと同程度の楽さでCDK for TerraformでもLambda関数がデプロイできることを期待していたのですが、現状CDK for TerraformではCDKほどの高抽象度でLambda関数をデプロイすることができず、Terraformで書く場合とほぼ同じレベルで書く必要がありそうです。今後に期待ですね。