概要
AWS CDK WorkshopをJavaでやってみた。
その際に感じたことのメモ。
前提
OS: macOS Ventura 13.2
プロセッサ: 2.4 GHz 8コアIntel Core i9
cdkのversion: 2.63.2 (build e08e34a)
New Project
(自分用メモ)cdkコマンドをインストール
npm install -g aws-cdk
コマンドを実行する。
cdk init
上記ページの通り、ディレクトリを作って cdk init をする。 Executing 'mvn package
が長くかかったが焦らず待つ。
Project structure
上記ページの通りの構成になっていることを眺める。
なんとなくSQS,SNSのことを操作していることを感じ取る。
cdk synth
上記ページに従ってcdk synth
を実行すると、標準出力にCloudFormationのtemplateが出力される。
cdk deploy
ここから実際にAWS上にリソースを作ることになるので若干慎重に。
まずaws sts get-caller-identity
して、aws cliの向き先があっていることを確認する。
ここからはこのページに従って、まずcdk bootstrap
する。
これでCloudFormationスタックとしてAWS CDKが利用するリソースを準備できる模様。
そこからmvn package
して、cdk deploy
実行する。
下記のような感じでどんな影響が出るか確認できる。
IAM Statement Changes
┌───┬─────────────────────────┬────────┬─────────────────┬───────────────────────────┬─────────────────────────────────────────────────────────┐
│ │ Resource │ Effect │ Action │ Principal │ Condition │
├───┼─────────────────────────┼────────┼─────────────────┼───────────────────────────┼─────────────────────────────────────────────────────────┤
│ + │ ${CdkWorkshopQueue.Arn} │ Allow │ sqs:SendMessage │ Service:sns.amazonaws.com │ "ArnEquals": { │
│ │ │ │ │ │ "aws:SourceArn": "${CdkWorkshopTopic}" │
│ │ │ │ │ │ } │
└───┴─────────────────────────┴────────┴─────────────────┴───────────────────────────┴─────────────────────────────────────────────────────────┘
終わるとSQS,SNSのリソースが作成されている。
Hello, CDK
API GatewayとLambdaを使ったサンプルを作っていきますよ、と。
Cleanup sample
コードからSQS, SNSの記述を消し去り(テストも消す)、再度デプロイする。
cdk diff
して、差分を確認できる。terraform plan
みたいなものかな。
┌───┬─────────────────────────────────┬────────┬─────────────────┬───────────────────────────┬─────────────────────────────────────────────────────────────────┐
│ │ 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
すると、コードから消したリソースがAWSからも消える。
Hello Lambda
lambdaにjsのコードをあげてみる。
書きながら、どんなリソースを作ろうとしているのか理解していく。
lambdaの作成は手順に従っていけばすんなりできる。
このページで、簡単にcdkのsdkで提供しているクラスの概念的なものを説明している。
cdkのsdkで提供されているクラスはconstruct
(何かの要素を組み合わせてできたもの、というイメージ?)であると説明している。
construct
を組み合わせたものがconstruct
を構成するという、入れ子なイメージ。
また、各クラスのコンストラクタが(scope, id, props)
というシグニチャを持っており、それらが何を意図しているか説明している。
- scopeはその
construct
が作成されたscope(scopeとは?という気持ちになるが我慢して進める。コンテキスト、みたいなイメージか?)を指し示す。基本的にthisを渡す。 - idは
construct
内で一意になる値を渡す。 - propsは各
construct
の性質によって取りうる値が異なる。lambda.Function
ならruntime
,code
,handler
など
CDK Watch
lambdaのコードだけ変えるのに、cdk deploy
するのだと時間かかってしょうがないよね。。?みたいな問題提起からこの章は始まる。
cdk deploy --hotswap
を使えば、cloud formationを経由せずにデプロイできるため、デプロイ時間短縮につながる。
実際、この章でやってるコマンドを私の環境でやってみたところ、普通のcdk deploy
だと40s近かったが、cdk deploy --hotswap
だと10秒くらいで完了した。
そして、CDKではcdk watch
コマンドなるものを用意している。
手元でcdk watch
コマンドを流しておけば、コードの変更を勝手に検知して、AWSリソースに変更を加えてくれる。
コードに変更を加えた際にhotswapで変更可能(cloud formationを介さくても良い変更)であればhotswapでデプロイし、そうでなければcloud formationでデプロイする。
手元でcdk watch
を試してみたところ、lambdaにあげているjsファイルを変更した際にはhotswapでのデプロイが走り、lambdaのhandler名を変えた場合にはcloud formationを介したデプロイが走った。
API Gateway
API Gatewayを上で作成したLambdaの前段に置いてあげましょう、という章。
コードを記述してcdk deploy
すると、標準出力に
Outputs:
CdkWorkshopStack.Endpoint~~~~~~~~ = https://~~~~~~~~~~~~.execute-api.ap-northeast-1.amazonaws.com/prod/
みたいな感じでエンドポイントが表示されるのでcurlなりブラウザなりでアクセスできる。
Writing constructs
これまでの構成要素にDynamoDBを加えて、URLをアクセスした回数をカウントするようにする。
Define the HitCounter API
HitCounter.java
なるクラスと、HitCounterProps.java
なるインターフェースを作成する。
Hit counter Lambda handler
hitcounter.js
なるLambdaにあげるファイルを作成する。
hitcounter.js
を記述するにあたって必要なLambdaの識別子、DynamoDBの接続先はdeployの際に確定するので、コード上は環境変数としている。
これらはconstructのコード(Javaのコード)に記述していく。
Define resources
HitCounter.java
にDynamoDBのリソース定義とLambdaのリソース定義を記述している。
1つ前の章で言及した環境変数は、ここで注入するためのコードを書いている。
Use the hit counter
CdkWorkshopStack.java
にHitCounter.java
というconstructを利用する旨を記述する。
API Gatewayからはhitcounter.js
を携えたlambdaを呼ぶようにする。
この状態でcdk deploy
したものにアクセスすると502 Bad Gatewayになる。
CloudWatch Logs
CloudWatchにエラーをみにいく方法が書いてある。DynamoDBに書き込みにいく権限が無さげなエラーが出ていることがわかる。
(Lambdaあまり使ってない勢からするとこういうエラー解析の説明はかなり助かる)
Granting permissions
hitcounterのLambdaから、DynamoDBとhelloのLambdaを叩く権限を与える。
すると、200が返るようになる。
Test the hit counter
色々なパスにアクセスして、DynamoDBのコンソールから正しくカウントされていることを確認する。
また、HitCounterは再利用可能で、maven centralにあげて、誰でも容易に同じようなことができるよ、と言及している。
Using construct libraries
cdk-dynamo-table-viewerというconstructのライブラリを利用して、Webページからhitcounterのテーブル情報をみれるようにする。
Learning about the Table Viewer construct
cdk-dynamo-table-viewerの紹介。
ざっとみた感じ、DynamoDBから情報を取得し、それを元にhtmlを組み立て返すLambdaを作成しているようだった。
(TypeScriptで記述されているっぽいが、これをどうやってJavaのライブラリとして固めているんだ、、?jsiiがよしなにやってくれるのだろうか)
あと、これは権限制御とかせずにDynamoDBの中身が見れちゃうので本番では使うなよ、と。
Installing the library
pom.xml
にライブラリの設定を加える。
Add a table viewer to your stack
上記ライブラリ由来のconstructを加えるコードをCdkWorkshopStack.java
に付け足す。
Deploying our app
cdk deploy
してブラウザから、どのパスに何回アクセスしたか見れることを確認する。
また、Constuctライブラリは便利な反面、IAMの権限などをいじったりするので、信頼できるもの以外は使わないようにとの注意喚起をしている。
Extra credit
ブラウザ表示された表はhitsの降順であるとのこと。
(extra creditは、おまけ、みたいな意味なのだろうか)
Clean up
cdk destroy
で作ったリソースを消していく。
この際、DynamoDBのテーブルはデフォルトの設定だと残り続けるので、明示的にRemovalPolicy.DESTROY
の設定を入れてやることで消せるようになる。
また、CloudWatch Logsのログは手で消すしかないとのこと。
所感
私の環境だと全く詰まることなく実行できた。
IaCはこんなに進んでいるのか、という感想を得た(今更感)。
特にcdk watch
のあたりはリアルタイムにローカルのコードがAWSに反映されており、開発スピード向上に役立ちそうである。
実際に導入するとなると、
- test、staging、productionの資材をどう書き分けるか
- ディレクトリ構成をどうするのか
- 汎用化したクラスを作るべきなのか(terraform のmoduleみたいな感じで)
とかを考える必要がありそう。この辺はどんなIaCツールを使おうとも考慮が必要だろう。
cdkの対抗馬として考えるならterraform。
例えばJavaを専門に扱っているチームなのであれば、JavaでやってしまえばHCLを新たに覚える必要はなくなるので良いのかなぁ。(AWSを離れるという選択がありうる場合はterraformの方が安心感はあるが)