(これはMoT Advent Calender 2022の24日目です)
データエンジニアの渡部徹太郎です。私の担当しているプロジェクトでは、Infra as CodeにTerraformではなくCDKというツールを使っているので、その話をします。
CDKの概要
CDKとはAWS専用のInfra as Codeツールです。正式名称AWS クラウド開発キット (AWS Cloud Development Kit)です。
$ cdk deploy S3Stack
例1: S3バケットの作成
ここからは実際にどのようにプロジェクトでCDKを利用しているか紹介します
アプリケーションのレポジトリの中に、アプリケーションのソースコードと一緒に、アプリケーション固有のAWSリソースのCDKのコードを管理します。例えば、IAM Role、CloudWatch Log Group、S3、Lambdaなどそのアプリケーションでしか使わないAWSリソースなどです。
アプリケーションを跨ぐ共通のリソースは、「共通インフラ」のレポジトリのCDKで管理します。例えば、VPC、RDS、ALBなどどのアプリケーション使うAWSリソースなどです。
アプリケーションのCDKのStackから、共通インフラのCDKのStackのリソースを参照する場合は、共通インフラ側でSSMパラメータを登録し、アプリケーション側からはそのパラメータをもとにlookupします。
例:共通インフラ側ではVPCを作り、VPC IDをSSMパラメータに登録
// VPCの定義
const vpc = new ec2.Vpc(this, 'Vpc', {
cidr: "192.168.0.0/16",
maxAzs: 2,
})
//他でも使うためSSM パラメータに登録する
new ssm.StringParameter(this, `StringParameterVpcId`, {
parameterName: `${env}-cm-vpc-id`,
stringValue: vpc.vpcId
})
アプリ側では、SSMパラメータをもとにVPC IDを取得し、Vpc.fromLookup()によりVPCのインスタンスを得る
//共通インフラのVPC
const vpcId = ssm.StringParameter.valueFromLookup(this, `${env}-cm-vpc-id`);
const vpc = ec2.Vpc.fromLookup(this, "vpc", {vpcId: vpcId})
他にもCDK Stack間の連携方法はありますが、この方法がStack間を疎結合にでき扱いやすいと思っています。
TypeScriptがかなり書きやすいプログラミング言語です。モダンな文法でありストレスなく書け、かつ型に厳格でありどんな引数を渡せばよいかIDEが教えてくれます。
また、日々のプログラミングで培った頭の使い方をInfra as Codeで活用できます。
そして、何より、インフラエンジニアやサーバサイドエンジニアにとっては普段触れることのないTyepScriptに触れるので、楽しいです。
AWSのメジャーなサービスは使いやすいです。
特にVPCを構築する場合は効果が絶大で、SubnetやNatgatewayなど細々設定しなくても、使いたいIPアドレスレンジとPublic or Privateを指定するだけでVPCを構築できます。
他にも、IAM, EC2, S3, AWS Batch, SQS, CloudWatchなど、みんながよく使ってるメジャーなサービスは、よくメンテナンスされていて快適に使えます。
CDKをデプロイしてなにかエラーが発生した場合に、AWSマネージメントコンソールからデバッグしやすいです。CDKはCloudFormationのStackになりますので、CloudFormationのStackの画面を見れば、どのリソースで問題が発生しているかわかりますし、リンクをクリックすればそのリソースに飛べます。
まず、この話を説明する前の前提知識として、CDKには高レベルAPIと低レベルAPIの2種類があることを説明します。高レベルAPIは上記のVPCのようにリソースを抽象化してくれて簡素な記述だけでリソースを定義できます。一方で低レベルAPIはCloudFormationと同じ粒度で細かく定義しなくてはいけません。
AWSでマイナーなサービスやサービスの設定値だと、高レベルAPIが提供されていなかったり、サービスの高レベルAPIはあっても一部の設定値が設定できないことがあります。例えば、ChatBotのSlackチャンネルパラメータ、EC2からFSx Lustreをマウントするパラメータ、StepFunctionに環境変数を渡すパラメータなどです。これらをデプロイしようと思ったら、低レベルAPIを用いてCloudFormationと同じ粒度で細かく定義する必要があり、面倒です。
ただし、CDKは日々バージョンアップしているため、以前は高レベルAPIがなかったサービスや設定値も、最新のバージョンだと存在するといったことはあります。
CDKは開発のサイクルが早く、一週間の間に3回リリースされることもあります。また、破壊的な変更が入ることもたまにあります。
そのため、おすすめとしてはバージョンを追従するのはある程度諦め、一定期間はバージョンを固定して運用することをおすすめします。古いバージョンでも問題なく動きます。
上記の通りCDKの開発は非常に活発ですので、バグも結構あります。
特に、リソースをデプロイするときは問題なくても、デストロイ(削除) するときにバグを踏むことが多いです。例えば、CDKが先にIAM Roleだけ消してしまい、サービスそのものを消すときに、消す権限がなくて削除に失敗する事がありました。
削除に失敗した場合は、マネージメントコンソールに入り手動でぽちぽち消すことが必要になります。
このブログで説明した内容ですが、以前ほぼ同じ内容を社内勉強会で話し、そこで色々質問が出ましたので、その質問と回答を記載しておきます。
Q: 自由に記述できることが逆にマイナスにならないか?CDKのコード自体のレビューが難しくならないか?
A: 基本インスタンスをNewするだけなので、そこまで複雑にはならない。今まで他人が書いたCDKが読めなかったということはない。
Q: CDKを経由せずに手動でAWSのリソースを変更したらその変更はdiffとしてでるのか?
A: 出ない。CDKはデプロイされたCloudFormationのStackとしか比較しないため、CloudFormationが変わらないとdiffは出ない。
Q: Terrafomでは、Terraformで管理されていないリソースを後から追加するterraform importみたいな機能はあるが、CDKにはあるか?
A: やったことはないができるらしい。まず、CloudFormationのresource imports機能を利用してリソースを取り込みます。その時に取り込んだスタック名とCDKのスタック名を一致させることによりCDKとしてリソースを取り込むことでできるらしい。
Q: terraform planやdiffみたいな差分を見る機能はあるのか?
A: CDK diffというコマンドがありdiffが見れる。
Q: 生成されたCloudFormationのJSONをレビューすることはできるか?
A: ビルドするときに生成されるので見ることはあるが、それをレビューすることはない。レビューはCDKのコードだけ行う。Cloud FormationのJSONを見たくないからCDKを使っている。
Q: CDKで生成されたCloudFormationのJOSNをレポジトリで管理しているか?
A: してない。CDKを信用している。
Q: TerraformのStateファイルみたいなもはあるのか? A: ない。AWSにデプロイされたCloudFormationStackそのものがstateの役割
Q: 依存関係はどうやって表現するのか?
A: 同一stack内であれば依存関係を考慮して作ってくれる。たとえば、role作ってからそれを使うサービスを作ってくれるといったことは自動でやってくれる。dependancyとかを明示的に入れる必要はない。Stackを超える場合は、SSMパラメータなどを経由して使うことが多い。
このブログではCDKの紹介と使った感想を記載しました。アップデートが早く暴れ馬な感じはありますが、Typescriptで書けるため柔軟で書いてて楽しいです。みなさんもぜひ使ってみてはいかがでしょうか?
興味のある方は 採用ページ も見ていただけると嬉しいです。
Twitter @mot_techtalk のフォローもよろしくお願いします!