CloudFormationをずっと書いてきた自分が、AWS CDKに乗り換えた理由
はじめに
AWSインフラをコードで管理するなら、まず思い浮かぶのはCloudFormation(以下Cfn)だろう。
YAMLやJSONで書いて、スタックを作って、デプロイする。
それで十分じゃないか——と思っていた時期が自分にもあった。
でも、CDKを使い始めてから考えが変わった。
「インフラをプログラミングする」という感覚が、ここまで違うとは思っていなかった。
この記事では、Cfnとの比較を軸に「CDKを使うと何が変わるか」を具体的にまとめる。
CloudFormationの何が辛いか
まず正直に言う。
Cfnには慣れれば使える。
でも、規模が大きくなると辛くなってくる。
辛さ1:YAMLが膨大になる
リソースが増えるほどファイルが長くなる。
500行・1000行のYAMLは珍しくない。
同じような記述が繰り返され、どこを直せばいいかわからなくなる。
辛さ2:繰り返しを吸収できない
「dev環境とprod環境でほぼ同じ構成を作りたい」というとき、CfnではParametersやConditionsで対応するが、書き方が煩雑でミスが起きやすい。
結果、コピペしたYAMLが複数存在する、という状況になりがちだ。
辛さ3:型チェックがない
YAMLを書いている間はエラーがわからない。
デプロイして初めて「プロパティ名が間違っていた」と気づく。
この往復が地味に時間を食う。
辛さ4:ロジックが書けない
「このリソースはフラグがtrueのときだけ作りたい」「リソース名に環境名を動的に付けたい」——CfnのConditionsや!Subで頑張れないこともないが、複雑な条件分岐は限界がある。
AWS CDKとは何か
AWS CDK(Cloud Development Kit)は、TypeScript・Python・Javaなどのプログラミング言語でAWSインフラを定義できるフレームワークだ。
最終的にCfnのテンプレートを生成してデプロイするため、裏側はCfnと同じ。
ただし、書くのはプログラムコードになる。
// CDKでVPCを作る例(TypeScript)
const vpc = new ec2.Vpc(this, 'MyVpc', {
maxAzs: 2,
natGateways: 1,
});
同等のCfnを書くと、これだけで数十行のYAMLになる。
CfnとCDKの比較
記述言語
CloudFormation:YAML / JSON
AWS CDK:TypeScript / Python など
記述量
CloudFormation:多い
AWS CDK:少ない(抽象化されている)
繰り返し処理
CloudFormation:困難(コピペになりがち)
AWS CDK:ループ・関数で簡単に対応
型チェック
CloudFormation:なし(デプロイ時に判明)
AWS CDK:あり(エディタでリアルタイム)
条件分岐
CloudFormation:Conditions構文(複雑)
AWS CDK:if文で自然に書ける
再利用性
CloudFormation:スタック単位
AWS CDK:Constructとして部品化できる
学習コスト
CloudFormation:AWSの記法を覚える
AWS CDK:プログラミングの知識が必要
既存資産
CloudFormation:豊富
AWS CDK:急速に拡大中
デプロイ先
CloudFormation:CFnスタック
AWS CDK:CFnスタック(同じ)
CDKを使うと何が変わるか:具体例で見る
① 繰り返しをループで書ける
複数のS3バケットを環境ごとに作りたい場合。
Cfnの場合:
DevBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: myapp-dev-bucket
StageBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: myapp-stage-bucket
ProdBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: myapp-prod-bucket
CDKの場合:
const envs = ['dev', 'stage', 'prod'];
for (const env of envs) {
new s3.Bucket(this, `${env}Bucket`, {
bucketName: `myapp-${env}-bucket`,
});
}
同じことをやっているが、追加・変更・削除がひとつの行で済む。
② Constructで部品化できる
CDKの最大の強みが「Construct(コンストラクト)」という概念だ。
よく使うリソースの組み合わせを、再利用可能な部品として定義できる。
たとえば「ECSクラスター+ALB+セキュリティグループ」のセットを1つのConstructにまとめると、別のプロジェクトや別のスタックでも1行で呼び出せる。
// 自作ConstructをStackで使う例
const api = new MyEcsApiConstruct(this, 'Api', {
vpc,
environment: 'prod',
containerPort: 8080,
});
CfnでもNestedStackで似たことはできるが、型の恩恵がないため、渡せるパラメータの把握が難しくなる。
③ エディタでリアルタイムに補完・型チェックが効く
TypeScriptでCDKを書くと、VSCodeなどのエディタが以下をリアルタイムでサポートしてくれる。
プロパティ名の補完(何が設定できるかをその場で確認)
型エラーの即時検出(デプロイ前に間違いに気づける)
cdk synthでCfnテンプレートに変換して確認
Cfnでは「デプロイしてみてから気づく」ことが多かったミスが、書いている段階で防げるようになる。
④ 条件分岐が自然に書ける
本番環境だけDeletion Protectionを有効にする、といった条件も普通のif文で書ける。
const isProd = props.environment === 'prod';
new rds.DatabaseInstance(this, 'DB', {
// ...
deletionProtection: isProd,
removalPolicy: isProd
? cdk.RemovalPolicy.RETAIN
: cdk.RemovalPolicy.DESTROY,
});
CfnのConditionsを使うより、はるかに読みやすく管理しやすい。
⑤ L1 / L2 / L3の抽象度を選べる
CDKにはリソース定義に3つのレベルがある。
L1
通称:Cfnリソース
内容:CloudFormationと1:1対応。Cfnプレフィックスのクラス
L2
通称:高レベルConstruct
内容:セキュリティグループなどのデフォルト設定が自動で入る
L3
通称:パターン
内容:複数リソースのセットをまとめた定番構成
基本はL2を使えば、IAMポリシーのデフォルト設定など「ベストプラクティス」が自動で適用される。
細かく制御したいときだけL1に降りればいい。
Cfnは常にL1相当なので、IAMポリシーの設定漏れなどをすべて自分で意識する必要がある。
CDKを使うべきシーン・使わなくていいシーン
CDKが向いている場合
複数環境(dev/stage/prod)で似た構成を使い回したい
リソース数が多く、再利用できる部品を作りたい
チームでインフラを管理していて、レビューしやすいコードが必要
TypeScript・Pythonなどに慣れている
Cfnのままでいい場合
既存のCfnテンプレートが安定して動いており、変更の必要がない
リソース数が少なく、シンプルな構成で完結する
YAMLのみで管理するルールがチームで決まっている
CDKへの移行は「全部一気に」じゃなくていい。
新規リソースからCDKで書き始め、既存はCfnのまま並存させることもできる。
CDKを始めるときの注意点
TypeScriptを選ぶのがおすすめ
CDKはPython・Java・C#なども使えるが、ドキュメントやサンプルの充実度からTypeScriptが一番扱いやすい。
JavaScriptに慣れていなくても、型のおかげで補完が効くため、意外と書きやすい。
cdk synthで生成されるYAMLを読む習慣をつける
CDKが自動生成するCfnテンプレートは、慣れないうちは「何が作られているかわからない」という状態になりやすい。
cdk synthの出力を定期的に確認することで、意図しないリソースが生成されていないかチェックできる。
cdk-nagでセキュリティチェックを自動化できる
cdk-nagというライブラリを使うと、IAMの最小権限・暗号化設定漏れなどをコード段階で検出できる。
セキュリティレビューのコストを下げるのに有効だ。
まとめ
CloudFormationは今も現役の強力なツールだ。
ただ、規模が大きくなるほど「繰り返し」「条件分岐」「部品化」の限界が見えてくる。
CDKはその限界を、プログラミングの力で超えるアプローチだ。
裏側はCfnと同じなので、既存の知識を活かしながら移行できる。
「Cfnは書けるけど、CDKはまだ」という人は、新しいリソースを1つCDKで書いてみるところから始めてほしい。
慣れてくると、Cfnには戻れなくなる。
この記事が参考になったら、スキ・フォローをもらえると励みになります。
