2021年の「re:Invent」で一般提供が開始された「CDK v2」

亀田治伸氏(以下、亀田):みなさんこんにちは、お元気でしょうか。AWSでエバンジェリストをやっている亀田と申します。

このあとのセッションは、実際にCDKを使っているというかなりコアな話が多いので、まず「CDKっていったい何ができるんですか?」「v1とv2って何が違うんですか?」という内容を30分ほど、デモを交えて話そうと思っています。

CDK v2は2021年の「re:Invent」でgenerally available(一般提供)が開始されましたが、実は1年くらいプレビューの状態が続いていたんですね。AWSウォッチャーからすると、もうそろそろ来るだろう、re:Inventで発表されるだろうと、ある程度予想していたアップデートです。「Git」のレポジトリも、実は米国時間のKeynoteの前日の真夜中(日本時間では昼間)にいきなり表記が変わったので、「ああ、これは来るな」と思っていたらKeynoteで発表されました。それがCDK v2です。

従来のCDK v1から大きく変わったわけでもなく、後方互換性はきちんと持っているので、基本的にはシームレスにv2へ移行できるような作りです。CDK Watchはけっこういい機能ですね。TypeScriptで設定パラメーターを書き換えると、裏側でAWSのリソースをぐるっと自動で回してくれます。

CDK v2は、コミュニティベースで開発が進んでいる点もちょっと特殊です。基本的にはAWSの人だけが作るのではなく、世界中のコミュニティデベロッパーと一緒に作っていこうという思想のもとに開発が進んでいますが、コミュニティのみなさんが自分たちで作ったものを「Construct」と言います。

Constructについては、あとで資料を使って説明しますが、ざっくり言うと、設定ファイルからAWSなど外部のさまざまなリソースを操作するようなもので、それを作ってここに公開することができます。

今日の登壇者のアジェンダの中に、Stripe(ストライプジャパン株式会社)の方がいらっしゃったので、おそらくCDKからStripe操作をする話をしてくれるのではないかと思いますが、re:Inventでは「Datadog」をサンプルとして紹介していました。

Infrastructure as Codeとは何か?

亀田:CDKは、いわゆるInfrastructure as Codeを実現するツールですが、おさらいするとコードでインフラをプロビジョニングする手法です。いろいろなやり方があり、特にCDKに限った話ではありません。AWSでは、「AWS CLI」「AWS SDK」、ローレイヤーのものですね。さらに、少し抽象化が進んだものとして「CloudFormation」や、「Ansible」「Chef」にも対応しています。CDKの実体はCloudFormationです。CloudFormationの可読性をより高めて、抽象化を高めて作業しやすくしたものがCDK。そんなイメージです。

CloudFormationは基本的に、YAMLもしくはJSONのテンプレートファイルをもとに動きますが、かなり細かいAWSのリソースの設定を書き込まないといけないので、可読性も悪くなるし、設定ファイルも長くなる。それを抽象化してCloudFormationテンプレートをいい感じに作ってくれるのがCDKという関係性です。

CDKの特徴

亀田:(スライドを指して)右側のようなさまざまな言語、Python、JS、TypeScript、Java、C#、Goなどに対応しているのが非常に大きな特徴です。左下のAbstraction(抽象度)は、かなり少ないコードで多くのものを操作することができます。例えば今画面に出ているのはConstructの一例ですが、たった6行で「ECS Fargate」、サーバーレスのコンテナ基盤を起動してくれます。

ECS Fargateを起動する際、CloudFormationであれば、当然先に「VPC」を作っておく必要があります。Fargateにユーザーのリクエストをルーティングするためのロードバランサなども作っておく必要があります。

CDKでは、そのへんがまとめて抽象化されているので、デプロイのタイミングでCloudFormationをデフォルト値で出力してくれます。当然、みなさんがそのデフォルト値を書き換えたいケースも出てくると思います。その場合は、この6行に対して追加のパラメーターを書き込んでいくという使い方ができます。

CDK v1とCDK v2の違い

亀田:v1とv2の大きな違いについて。スライドの左側がv1、右側がv2です。v1はAWSサービスごとにライブラリが存在していて、それぞれが互いに依存関係にあるという状況でした。何かを入れ替えると、関連する別のモジュールに破壊的な変更を及ぼす可能性があり、開発者はここで苦労することがありました。また、私たちは日本語で「非安定版」と言っていますが、アルファ版やベータ版がこの中に入ってくる可能性も十分にあります。

右側のCDK v2で何が変わったかというと、まず安定版のConstructが「aws-cdk-lib」というものにまとまりました。AWSは、今後このaws-cdk-libには安定版のみをマージしていくと言っています。まだv2で対応していないものや、v2で対応しているものの安定版とは言えないものについては、右側の上から4行目のように「aws-iot-alpha」と記載されています。それを追加で読み込むことで、みなさんが安定して使えるものと、動作検証が必要なものを明示的に区別できるようになり、より使いやすくなったのがCDK v2。そんなイメージです。

re:Inventで発表されていたものには、「App Runner」「Kinesis」「AWS Service Catalog」「IoT」など、まだまだ対応していないものがあります。これらの開発をコミュニティの人と一緒に進めていくということです。

(スライドを指して)先ほどご紹介した「Construct Hub」はAWS純正で開発したものも、コミュニティのエンジニアが開発したものも入っていますが、さまざまなConstruct Libraryをここで呼び出せます。その際、v1対応用かv2用かがフラグとして、検索結果で表示されるようになっています。

CDKの中のコンポーネントは、大きく3つで構成されています。1つがCore Framework、AWSのリソースを操作するもの。真ん中がConstruct Libraryで、aws-cdk-libの中に各AWSのサービスを操作するConstruct Libraryが入っています。繰り返しますが、aws-cdk-libの中には安定版のみがマージされていくので、一部のAWSサービスはまだ対応していません。それらはみなさんが明示的に追加で読み込めますし、外部のさまざまなサービスを操作するものも読み込めます。右側が、それを操作するAWS CDK CLIです。

デプロイ前の流れ

亀田:デプロイ前の流れについて。まず、みなさんは設定ファイル、Stack、Constructを任意の言語で書き込めます。アンケートを取ったわけではありませんが、デベロッパーと話をすると半数以上の方がTypeScriptを使っているようです。

cdk synthというコマンドがあります。このコマンドを叩くとCloudFormation Stackを作ってくれます。デプロイのタイミングでCloudFormation Stackが実行されます。

cdk diffは、わりと便利なコマンドです。要は、過去に作った環境に対してなんらかの修正を加えた際、cdk synthで新しいCloudFormation Stackを作り直して、cdk diffを実行することで過去との差分を教えてくれます。そのあたりを確認して、管理者が問題ないと判断できれば、cdk deployでCloudFormationを起動するという動きをします。

その際、CloudFormationと少し考え方が違うのがパラメーターの取扱いです。CloudFormationテンプレートにはパラメーターを設定することができ、パラメーターを設定したStackを実行すると、VPCの名前とか、起動したEC2のインスタンスタイプとか、リージョンを指定してくださいとか、そういったものの入力を求められます。それらを指定しないと、パラメーターを持っているCloudFormationテンプレートは実行されません。CloudFormationは1つのテンプレートからステージング環境や商用環境など、複数の環境を生み出すことができます。そんな使い方です。

一方CDKは、パラメーターのインプットというより、事前に変数でそこを処理しておきます。先ほどcdk synthの話をしましたが、CloudFormationのテンプレートを生み出す段階からテンプレートを派生させるという動きをします。なので、1テンプレート、1 Stack。Stackは環境のことですね。このように、少し違いがあるのが運用上の注意点です。

複数のAWSリソースを操作するL2から派生するL3

亀田:CDKの学習をする中でみなさんを混乱に陥れるのが、ConstructのL3です。L1、L2はAWSのドキュメントに明示的に書いてありますが、L3はフワッと記載されていて私も最初は理解できなかったので、お伝えします。

みなさんが標準で使うのはL2 Constructです。CDKを使い始める際は、まずL2 Constructを使います。これは従来のCloudFormationのさまざまなパラメーターを抽象化しているので、非常に使いやすいです。短いソースコードでいろいろなリソースを処理できますが、CloudFormationで操作できるすべてのパラメーターを操作することはできません。一部、デフォルトでしか設定できないものがあるということです。

それが運用上厳しい場合は、L1 Constructを使います。これは基本的に、すべての設定項目がCloudFormationのパラメーターと1対1でマッピングしてくれます。しかし、その分書き込まないといけないものが増えていくので、CDKの1つのメリットである高い抽象度、少ないソースコードで大量のリソースを操作できるという利点が一部失われます。なので、まずはL2でできるかどうかを判断する必要があります。

では、L3とは何か。基本的に、L2の中で複数のAWSリソースを一度に操作しようとするものを作った場合、L3というものになります。

例えば、先ほどご紹介したECSの例では、PVC、ロードバランサなどを同時に設定することになるのでL3になります。また、「Lambda」の関数を設定しようとする場合、APIゲートウェイを一緒に1つのファイルの中で設定することが多いと思います。そうすると、気がついたらその設定は勝手にL3 Constructになっている。そんなイメージです。

L1とL2は技術的な違いが明確に存在し、どちらで作業するかをみなさん意識する必要がありますが、L3は、L2の作業をしていく中で、放っておけばほとんどの場合L3になっていくという関係性を持っています。

おそらくこのあとのセッションでは、CDKで作業した話が出てくると思います。多くの場合はL3、もしくはL1でガチガチに新しいもの作ってみたという話になるのではないかと思っていますが、こんな関係性があることを覚えておいてください。

CDK v2のデモ

亀田:ここからは実際に触ってみます。

(スライドを指して)今、「StreamYard」のブラウザが出ています。まずCDKの実行環境を作っていきます。今日のデモは「Cloud9」を使いますが、別になんでもいいです。私にとってはCloud9が一番便利なだけなので、「Visual Studio Code」を使っている方はそれでもかまいません。

実は、AWS純正のCDKワークショップというものがあるのですが、日本語化されておらず、V1の情報も残っています。2022年2月にCDK Conferenceプリデイがありましたが、その時に私のほうでワークショップをやりました。CDKに触ってみたい方は、(スライドを指して)ここに私が日本語化したものがあります。

LambdaとAPIゲートウェイを起動して、CDK WatchでLambdaの関数を裏側でぐるっとホットスワップで入れ替えるようなシナリオになっています。

ここから実際の実行環境を作っていきます。起動に2、3分かかるので、少しCPUを速くして待ちます。Cloud9の利点は、CDKがもともとインストール済みであることです。AWS CLIもインストール済みで、あらかじめAWSを操作する専用のIDEなので、非常に便利です。

もう少し文字を大きくすると見やすいですね。CDKがあらかじめ入っているのでバージョンが出てきます。

最初にやるのは、作業ディレクトリを作ることです。このディレクトリ単位でプロジェクトというものが作られていくというイメージです。複数環境を混在させる場合は、ディレクトリを分けていくという使い方です。

まずinitです。JavaScript用にプロジェクトをinitすると初期のサンプルをいろいろ作ってくれます。今、deprecatedのウォーニングがnpmインストールで出ていますが、このへんは気にしない。イニシャライズできました。package.jsonが作られていますね。ここで使うライブラリなどを指定したりしています。

1つ、注目ポイントです。(スライドを指して)「"test": "jest"」というものがあると思いますが、CloudFormationの場合はStackのデプロイが終わるとそれで終わりですが、みなさんはさらにテストを書き込む必要があります。CDKの場合は、この一連のデプロイの流れの中にユニットテストみたいなものをここに埋め込んでおくことができます。これが1つの特徴です。使うライブラリなどがこのへんで指定されているというイメージです。

今JavaScriptでinitしたので、サンプルのStackができていて、HelloCdkStackというものが作られています。このaws-cdk-libを読み込んでいる。中身は空です。このStackがlibの下のhello-cdk-stackで定義されている。ここが、みなさんがふだんAWSリソースを作業するための実体です。ここに対してさらにLambdaの関数を起動するという設定をするのであればLambdaの関数、Node.jsで作るのであれば、そのJSファイルをまた別のところに配置する必要が出てくる。そんな関係性です。

例えば先ほど紹介した、S3バケットを最初に簡単に作りましょうというシナリオがハンズオンの中の第1ステップですが、それをこのようにコピーします。ここはv1とv2の中の区別がわかりにくいところで、「結局AWSのリソースごとにrequireで呼び出すんだ。じゃあ、これってv1なの?」と勘違いしがちですが、そうではありません。aws-cdk-libの中のaws-s3を呼び出しているということです。例えばLambdaを使うのであれば、Lambda用に宣言をしていく必要があります。やることは単純です。バージョニングがオンになったMyFirstBucketというS3バケットを作って、これを保存します。

先ほど言ったcdk synthです。そうすると、かなり長い何かが出てきていますが、これがCloudFormation Stackです。先ほど、だいぶ抽象度が高いという話をしましたが、CloudFormation Stackテンプレートの実体を作ってくれるということです。

次にやるのが「Bootstrap」というコマンドです。このBootstrapは毎回必要なのではなく、リージョンごと、言語ごとに1回だけ必要です。やっていく気持ちみたいなものの宣言ですね。こいつが具体的に何をやっているのか。CloudFormationの実行のためには、CloudFormation StackテンプレートファイルをS3に保存しておいて、CloudFormationをそこから引っ張っていくという動きをする必要があるので、CDKが実際にAWSリソースをデプロイするための初期設定をやるのがBootstrapです。

私が朝実行したから、何かが重複したかもしれないな。ROLLBACK_IN_PROGRESSが動いていて、ちょっと嫌な感じだな。朝、よかれと思ってリハーサルしたのが何か被っているな。S3バケットが残りっぱなしですね。消しますね。

今もう一度、Bootstrapを実行しています。初期設定や実行環境の準備として、必要なIAM Roleを作ったり、S3のバケットを作ったりしています。これらの画面は、実際にCloudFormationを使っている方であればだいたい見たことがありますよね。なぜなら実体はCloudFormationだからです。

CREATE_COMPLETEになりましたね。これでBootstrapが終わりました。先ほどcdk synthで、outファイルでテンプレートができているので、あとはデプロイです。

デプロイすると、まずCloudFormation Change Setを作りますが、今は初めて作るためChange Setがないので、新規のCloudFormation Stackを実行します。スライドを見ると、できていますね。こいつは先ほど指定したMyFirstBucketというS3のバケットを作ろうとしています。先ほどの話でいうと、このlibのhello-cdk-stack.jsを作ろうとしています。今、出来上がりました。CloudFormation Stackの実行が完了していて、S3のバケットを見ると、こういうものができています。

先ほど、設定ファイルの中の変数をベースに名前を切り替えていくという話をしました。いろいろな修飾がぐちゃぐちゃ付いていますが、ステージングのようなものはテンプレートのパラメーターではなく、テンプレートを作る前にCDKの変数で設定しておいて切り出していくということです。

また、みなさんが商用環境でCDKを使う際に「BLEA(Baseline Environment on AWS)」というものを紹介したいと思います。今日はこのあと、ソリューションアーキテクトの大村さん(大村幸敬氏)が実際に解説のセッションをやってくれますが、なんと大村さんの作ったものがAWS Samplesにマージされています。私は初めてそれを知った時、相当衝撃を受けました。実際に、日本のソリューションアーキテクトの人が作ったものがこういうところに入るのを私自身は初めて体験したので、「おお、すごいな」と思いました。

大村さんがBaseline Environment on AWS、BLEAの実際の使い方や、設計思想を説明してくれるので、みなさん、楽しみにしていてください。私からは以上です。

質疑応答

新居田晃史氏(以下、新居田):亀田さん、ありがとうございました。

吉田真吾氏(以下、吉田):ありがとうございました。

亀田治伸氏(以下、亀田):いやあ、焦ったよ。エラーになるとは思わなかった。直ってよかった(笑)。

新居田:デモあるあるですね(笑)。

亀田:そうそう。気を利かせて朝テストをすると、ろくなことないんだよ。

吉田:でも普通はみんな、ToolkitはBootstrapしっぱなしにしておきますよね。リージョンのところに。

亀田:そうです。リージョンごと、言語ごとに1回だけですね。

吉田:あんなにやり直してハマったりするのは、直面することはないんじゃないかなと思います。

新居田:では、質問が来ているので紹介していきます。1つ目は、「L2、L3、L1もそうですが、名称が分かれている意味はなんでしょうか?」。L1はCloudFormationそのままでパラメーターに紐づいているということですが、L2とL3は両方抽象化されていてわかりにくいところがあったという質問だと思います。

亀田:なぜ分かれているんですかね。ただ、みなさんがテストを始める時は最初に1つのAWSサービス、リソースだけを操作するところから複雑化していくので、そういう意味で、まずL2から作業するという話なんだと思います。

吉田:サーバーレスのアプリケーションなどで考えても、APIゲートウェイもLambdaも「DynamoDB」もL2で1つずつ別々に作りますが、L3でまとめていったらみたいな使い方ですよね、たぶん。

亀田:そうですね。

吉田:ユースケースに合わせてまとめていくならL3で、みたいな。

新居田:僕は触ったことがないんですが、書いている人はL2やL3を意識して書くような感じなんですか? それとも特に意識しなくても?

亀田:L2、L3は意識しなくて大丈夫です。勝手にL3になっていくというイメージですね。

新居田:なるほど、ありがとうございます。「登壇内容には関連しませんが……CDK Watch、LambdaやECSのアセットはわかりますが、ステートマシン定義もホットスワップとなると、CloudFormationと実リソースで差分が生じてしまいそうです。いい感じに動くのでしょうか?」。ホットスワップだと、SDKで直接変更したところを、またあとでCloudFormationで上書きできるの?という疑問だと思います。

亀田:おっしゃるとおりです。ホットスワップは便利ですが、常に使い続けるものではないと理解しています。運用設計次第ですが、本当に緊急にやりたい時とかですね。先ほどハンズオンのシナリオを放流してくださいとお願いしましたが、実際にホットスワップをやるとLambda関数の入れ替えは2秒か3秒くらいですが、cdk synthからやると50秒くらいかかります。本当に緊急の時、もしくは開発時に開発者がきちんと把握できる間だけホットスワップを使う感じになるんじゃないかと思います。

吉田:僕がサーバーレスでアプリ作っていて、観測している限りでは、Lambdaのコードの部分くらいかなと思っていたんです。ほかはCloudFormationのChange Setのほうができて、例えばConstructを増やす時は、全部CloudFormation。明らかにChange Setが発生するので、そこはいい感じで検知してくれて入れ替えてくれます。ステートマシン定義についてはやったことがないのでわからないんですけど。

亀田:実際にCDKはいったん忘れて、CloudFormation経由で作ったLambda関数を手で直接書き換えるのと同じことをやっているので、その中で運用をどうするかを考えてもらったほうがわかりやすいと思います。

新居田:なるほど。運用面とあわせて、このへんをきちんとやっていこうということですかね。

亀田:そうですね。

新居田:次は「CDKとCloudFormationで同じプロビジョニングをした場合のコード量の差がどれくらいか知りたいです」。

吉田:これは後ほど、やまたつさん(山本達也氏)が出すと言っています。出すというか、もともとこんな感じみたいなのがあるらしいです。とはいえ、自分のコードの部分での違いなので、AWSの300行が3行になるというL3のコードとは違うかもしれませんが。

新居田:では後ほど。

亀田:先ほどの私のプレゼンテーションの中でサンプルで出していたFargateのものは、CDKだと6行だけど、CloudFormationテンプレートだと832行です。

吉田:120倍(笑)。でもあれは、吐き出したCloudFormationのテンプレートの中に山ほどリージョンが書かれていますが、実際に手でCloudFormationを書くならあんなリージョンは書かないですよね。us-east-1くらいしか書かないと思う。機械的にきれいに生成して出るものに比べると、圧倒的に簡単になる場合が多いという感じですかね。

新居田:もう1ついきましょう。「AWS初心者ですが、おすすめの書籍を教えてもらいたいです。また、おすすめの学習方法も教えてください」。

亀田:私は書籍のことはわかりませんが、常になるべく新しいものを買ったほうがいいとは言っています。ブックオフで100円で売っているものもありますが、AWSはバージョンアップが激しいので100円で買わずに、2,000円くらいしたとしてもなるべく新しいものを。ずっと本屋の本棚に残っているものではなく、裏の初版の日付を見て買ったほうがいいんじゃないかな。たぶん質問者は「そんな答えは求めてないよ、もっと具体的に言えよ」という話なんでしょうが。

吉田:僕は2方向あると思っています。なんとなくAWSの資格を取る方向に向かって、座学でまんべんなく体系的に学んでいく知識の獲得という方向性。CDKは特にそうですが、ドキュメントを読み進めるとけっこうハンズオンなんですよね。これ動かして覚えていこうぜというノリのドキュメントの進み方が多い。

僕は言われたとおり動かしてみて、「ああ、これがこういう話なのね」とやっていくほうが楽しいし、長続きするというか覚えやすい。ですが、中には、AWSのいろいろなサービスや、SAの資格を取るために体系的に学習する方向からやったほうが全体を掴みやすくていいという人もいると思います。そういう人には、AWSの資格の本がここ2、3年ですごくたくさん出ているので、そういうものでやっていくのもありなんじゃないかなと思います。

亀田:そうですね。

吉田:CDKに限定するなら、「AWS CDK」ってググるとAWSの公式のドキュメントが出てきます。それを読み進めていくと手を動かさざるを得ないので、順番にやっていく。先ほど亀田さんがやったことをどんどんやらされるので、そっちのほうが楽しくていいんじゃないかなと思います。

亀田:先ほどBootstrapは言語ごとに必要かという話をしたと思います。そこだけ、仕様の話と私の好き嫌いをごっちゃに説明してしまった気がします。CDKの仕様はアカウント単位、リージョン単位です。言語の切り替えでBootstrapが同じリージョンであれば必要ありませんが、なんだか気持ち悪いので毎回言語を替えるたびにBootstrapを、という話をまとめてしちゃったので、勘違いさせたなというお詫びです。

新居田:なるほど。言語が変わってもBootstrapはアカウント、リージョン単位で。

亀田:私自身はBootstrapせずに言語を切り替えたことがないんですが、大丈夫なはずです。

新居田:ありがとうございます。

吉田:アカウントがよく使うリージョンには、だいたいみんなCDK ToolkitというStackがずっといる。たぶんこの先もずっといると思います。

亀田:そうですね。

新居田:聞いている人はみんな、今日(※登壇当時)からそうなっているということですよね。

吉田:そのはずです。

新居田:ほかの質問については、Twitterで後ほど亀田さんに回答していただこうと思うので、ここで終了します。

亀田:ありがとうございました。