AWS CDK入門:CloudFormation/Terraformとの違いからS3・Lambdaの実践まで
AWS CDKとは?仕組みと向いているケース
AWS CDKは、インフラを「設定ファイルを書く作業」だけでなく、普段のソフトウェア開発に近い形で扱えるようにする仕組みです。
コードとして設計し、レビューし、再利用しながらAWS環境へ反映できる点が大きな特徴です。
ただし、CDK自体がCloudFormationを置き換えるわけではありません。
CDKで書いた定義は合成され、最終的にはCloudFormationを通じてAWSリソースとしてデプロイされます。
汎用プログラミング言語でインフラを定義する
AWS CDKで公式サポートされる言語にはTypeScript、JavaScript、Python、Java、C#、Goが含まれており、チームが慣れている言語を使ってインフラを表現できます。
YAMLやJSONだけで構成を記述する場合と違い、変数、条件分岐、ループ、関数、クラスといった一般的なプログラミング機能を利用できるため、似たリソースを大量に定義するときでも重複を減らしやすくなります。
たとえば開発・検証・本番で似た構成を作る場合、環境ごとに大きなテンプレートをコピーするのではなく、共通部分をConstructとしてまとめ、差分だけを引数として渡す設計ができます。
この方法の利点は、単に記述量を減らせることだけではありません。
型情報やIDEの補完、リファクタリング、単体テストなど、アプリケーション開発で使っている道具をインフラ定義にも持ち込めます。
一方で、プログラミング言語を使えるからといって複雑なロジックを無制限に書くのはおすすめできません。
インフラコードは最終状態を理解しやすいことが重要なので、条件分岐を増やしすぎるとレビュー時の見通しが悪くなります。
CDKは「インフラをアプリケーションコードのように扱う」ための道具ですが、読みやすさ、再現性、変更影響の把握というIaC本来の目的を優先して使うと効果を発揮します。
型付き言語を使う場合は、プロパティ名の誤りや型の不一致をデプロイ前に検出しやすくなりますが、値の意味まで自動検証されるわけではないため、AWSサービスの制約は公式リファレンスで確認します。
共通化は早すぎると逆効果です。
まず2〜3回同じ構成を作って重複部分を見極め、それからConstructへ抽出すると、将来の変更点まで無理に抽象化するリスクを下げられます。
CDKコードはCloudFormationへ合成される
AWS公式ドキュメントでは、CDKアプリを合成するとStackごとのCloudFormationテンプレートやデプロイ用アーティファクトが作成されると説明されています。
cdk synthを実行すると、Construct treeをたどって必要な情報が合成され、CloudFormationが理解できるテンプレートへ変換されます。
cdk deployでも必要に応じてsynthが実行されるため、毎回手動でcdk synthを打たなければデプロイできないわけではありません。
それでも開発中に明示的にsynthする価値はあります。
生成されたCloudFormationテンプレートを確認すれば、CDKの抽象化の裏側でどのAWSリソースやIAM設定が作られるかを追いやすくなるからです。
CDKを採用してもCloudFormationの基礎知識が不要になるわけではありません。
デプロイエラー、ロールバック、論理ID、Stack間参照などを調べる場面では、CloudFormationの仕組みを知っているほど原因特定が速くなります。
入門時は「CDKで書く→synthでCloudFormationになる→CloudFormationがAWSへ反映する」という三段階を意識すると、ツールの責任範囲を混同しにくくなります。
synth結果はレビュー資料としても役立ちます。
特に高レベルConstructを初めて使うときは、生成リソース数、IAM Policy、Security Group、Outputsなどを確認すると意図しない副作用を見つけやすくなります。
CloudFormationのChange Setやイベントを調べる力は、CDK運用でもそのまま重要です。
CDKは記述を便利にしますが、AWS側で実際に何が起きたかを説明する責任までは隠してくれません。
AWS CDKが向いているケース・向いていないケース
CDKは、AWS中心のシステムを開発者自身が構築し、同じ構成を複数環境へ繰り返し展開したいケースと相性が良いです。
複数のAWSリソースをひとまとまりの部品として再利用したい場合も有効です。
たとえば「API、Lambda、ログ、アラームまでを1つの標準部品として各チームへ配る」といった設計はConstructの考え方に合っています。
アプリケーションとインフラを同じリポジトリや近い開発フローで管理したい組織では、Pull Requestでコードレビューし、テスト後にCI/CDからデプロイする流れを作りやすくなります。
反対に、複数クラウドや多数のSaaSを1つのIaCで横断的に管理したい場合は、Terraformのようなマルチプロバイダー型の選択肢が自然なことがあります。
また、小さな一時検証で数個のリソースを一度だけ作るだけなら、CDKプロジェクトやbootstrapまで準備するコストが目的に対して重い場合があります。
ツール選定では流行よりも、対象クラウド、チームの言語スキル、運用期間、再利用の必要性、状態管理やデプロイ方式を基準に判断することが重要です。
長期運用する基盤ほど、担当者交代後にコードを読めることが重要になります。
チームが普段使う言語で書けるCDKは引き継ぎやすい一方、インフラ固有の知識をコードレビュー基準として残す必要があります。
既存のTerraform資産が大量にある組織で、単に新しいという理由だけでCDKへ全面移行すると二重管理が発生します。
新規領域から小さく採用し、運用コストを比較してから標準を決める方が現実的です。
従来のIaC(CloudFormation/Terraform)との違い
CDK、CloudFormation、TerraformはいずれもIaCを実現する手段ですが、書き方と実行モデルが同じではありません。
どれが優れているかではなく、何を管理し、誰が運用するかで適性が変わります。
特にCDKはCloudFormationの上に構築された開発体験である一方、Terraformは複数プロバイダーを横断できる独立したIaCツールであり、この違いを理解して選ぶ必要があります。
CloudFormationと比べたときのCDKの位置づけ
AWS CDKの公式ガイドが説明するように、CloudFormationはAWSリソースをプロビジョニングする基盤であり、CDKはその上でプログラミング言語による定義を提供します。
CDKはそのCloudFormationへ最終的にテンプレートを渡すため、デプロイ後のAWSリソース管理はCloudFormationの仕組みに乗ります。
違いが大きいのは入力側の開発体験です。
CloudFormationではYAMLやJSONで直接リソースを記述するのに対し、CDKではConstructをプログラミング言語から組み合わせます。
同じ構成を何度も使う場面では、CDKの関数やクラスを使った再利用が分かりやすくなることがあります。
逆に、生成結果を一目で直接確認したい小規模な構成では、CloudFormationテンプレートの方が単純に感じることもあります。
CDKの高レベルConstructには便利な初期値や補助メソッドがありますが、すべての設定が自動的に安全になると考えるのは危険です。
暗号化、公開範囲、削除ポリシー、ログ、バックアップ、IAM権限などは目的に合わせて明示的に確認します。
CloudFormationに慣れている人は、CDKを別物として学ぶより「CloudFormationを生成するプログラミング層」と捉えると、既存知識を活かしやすくなります。
直接CloudFormationを書く利点は、生成後の構造ではなく最初からデプロイ定義そのものを編集できることです。
学習対象が少なく、AWS公式テンプレートや既存資産をそのまま活用しやすい場面もあります。
CDKを選んだ場合でも、チーム内で「生成テンプレートをどこまでレビューするか」を決めておくと品質が安定します。
すべてを毎回読むのではなく、IAM、ネットワーク、データ保持など高リスク部分へ重点を置く方法があります。
Terraformと比べると管理対象の広さが異なる
TerraformはAWSだけでなく、複数のクラウド、SaaS、DNSなど多様なプロバイダーを1つの構成言語とワークフローで扱える点が強みです。
AWSの規範ガイダンスでも、Terraformは単一クラウドプロバイダーの環境に基づかないため、さまざまなプロバイダーを扱える柔軟性があると説明されています。
Terraformではstateが重要な管理要素であり、現在の管理対象と設定を照合しながらplanとapplyを進めます。
チーム利用ではstateの保管場所、ロック、権限、バックアップまで運用設計に含める必要があります。
CDKではCloudFormation StackがAWS側のデプロイ単位となり、CDKコードをsynthしてCloudFormationへ渡す構造です。
このためAWS中心の環境では、AWSネイティブの管理モデルへ自然につなげやすい特徴があります。
一方で、AWSリソースと同時に別クラウドや外部サービスまで統合管理したいなら、CDKだけで統一することが必ずしも最短とは限りません。
比較するときは「プログラミング言語が好きか」だけではなく、管理対象の範囲、状態管理の責任、既存CI/CD、チームの経験、将来のクラウド戦略まで含めて考えます。
TerraformのplanとCDKのdiffはどちらも変更確認に使えますが、内部モデルは同じではありません。
コマンド名の類似だけで運用を置き換えず、削除・置換・依存関係の表示方法を実環境で比較しておくべきです。
マルチクラウドが将来あり得るだけでTerraformを選ぶ必要もありません。
実際の管理対象、採用人材、既存AWSガバナンス、監査要件を整理し、今後数年の運用に最も説明しやすい方式を選ぶことが大切です。
3つのIaCを選ぶ判断軸
第一の判断軸は管理対象です。
AWSだけを深く使うのか、複数クラウドや外部SaaSも同じIaCで管理するのかによって候補が変わります。
第二の判断軸は抽象化の必要性です。
複数リソースからなる標準アーキテクチャを部品化して配布したいならCDKのConstructが便利ですが、直接的なリソース定義を好むならCloudFormationが分かりやすい場合があります。
第三の判断軸はチームスキルです。
TypeScriptやPythonのレビュー文化がある開発チームではCDKへ入りやすく、HCLやTerraform運用の知見があるプラットフォームチームではTerraformを継続する方が合理的なことがあります。
第四の判断軸は変更確認です。
どのツールでもデプロイ前に差分を確認する工程を設け、意図しない削除やIAM拡張がないかをレビューできる運用を作ることが重要です。
第五の判断軸は障害時の切り分けです。
CDKならCloudFormation、Terraformならstateとproviderなど、実行基盤の知識まで含めて保守できる体制が必要です。
短い比較表だけで決めるのではなく、自社の典型的な1システムを小さく実装し、変更、ロールバック、レビュー、CI/CDまで試してから標準化すると失敗を減らせます。
検証では同じ要件を3ツールすべてで大規模に作る必要はありません。
VPC、IAM、Lambdaなど代表的な変更を1つ選び、コード量よりレビューのしやすさと障害調査時間を比べる方が判断材料になります。
標準化後も例外を認める基準を決めておくと、特殊なサービスや既存資産へ無理に同じ道具を押し付けずに済みます。
標準ツールは目的ではなく、変更を安全に再現するための手段です。
AWS CDKの3大コンポーネント
CDKのコードは、Appをルートとして、その下にStack、さらにConstructが並ぶ階層で理解すると整理しやすくなります。
この3つの役割を分けると、どこに何を書くべきかを判断しやすくなります。
公式ドキュメントでもApp、Stack、ConstructはConstruct treeとして関係づけられており、再利用単位とデプロイ単位を混同しないことが設計上のポイントです。
① Construct(コンストラクト)
ConstructはCDKアプリの基本的な構成要素で、1つのAWSリソースだけでなく、複数リソースを組み合わせた再利用可能な部品も表現できます。
L1 ConstructはCloudFormationリソースに直接対応する低レベルの表現で、細かなプロパティを自分で制御したいときに使います。
L2 ConstructはAWSサービスを使いやすく包んだ高レベルAPIで、S3のBucketやLambdaのFunctionのように、便利なメソッドや型付きプロパティを利用できます。
L3 Constructはさらに複数のL2などを組み合わせ、特定のアーキテクチャパターンをまとめた部品として提供されるものです。
入門時はL2から始め、L2で足りない設定だけL1へ降りる考え方が実務で扱いやすいです。
最初からすべてをL1で書くと、CDKの抽象化による生産性を活かしにくくなります。
自作Constructを作るときは、アカウント固有値や環境名を内部へ固定せず、必要な値をPropsとして受け取る設計にすると再利用性が高まります。
Constructの抽象度を上げるほど利用側は簡単になりますが、内部挙動が見えにくくなります。
共通ConstructにはREADME、Propsの説明、セキュリティ上の前提、変更時の互換性方針を用意すると使い回しやすくなります。
社内Constructをパッケージ化する場合は、バージョニングと破壊的変更の扱いを決めます。
1つの変更で複数システムへ影響するため、便利な共通化ほどリリース管理が重要になります。
② Stack(スタック)
StackはCDKにおける最小の単一デプロイ単位で、Stack内に含まれるリソースはCloudFormation Stackとしてまとめてデプロイされます。
そのため、変更頻度、責任範囲、障害影響、デプロイ順序を考えながらStackの境界を決める必要があります。
たとえばネットワーク基盤とアプリケーションを分ける設計は、担当チームや変更頻度が異なる場合に有効ですが、細かく分けすぎるとStack間参照やデプロイ順の管理が増えます。
AWS公式のベストプラクティスでは、再利用する論理単位はConstructとしてモデル化し、Stackは主にデプロイの構成や接続を表すために使う考え方が示されています。
「再利用したいからStackにする」のではなく、「一緒にデプロイしたいからStackにする」と覚えると、Constructとの役割分担が分かりやすくなります。
本番運用ではStack削除時の影響も意識します。
データベースやS3のようなデータ保持リソースは、RemovalPolicyやバックアップ方針を確認してからStack境界へ含めます。
Stack境界はCloudFormationの制限やデプロイ時間にも影響します。
巨大Stackは変更の影響範囲が広くなり、細分化しすぎると依存関係が増えるため、サービス境界や運用責任を基準に中間点を探します。
クロスStack参照を多用すると、片方だけを独立して変更しにくくなることがあります。
共有値が本当に強い依存なのか、SSM Parameter Storeや明示的な設定受け渡しが適切かも比較します。
③ App(アプリ)
Appは1つ以上のStackをまとめるCDKアプリケーションのルートで、Construct treeの最上位に位置します。
一般的なTypeScriptプロジェクトではbin側でnew cdk.App()を作成し、そのAppへ1つ以上のStackを登録する形がよく使われます。
同じAppに開発用Stackと本番用Stackを作ることもできますが、アカウントやリージョン、デプロイ権限をどう分けるかは組織の運用ルールに合わせて設計します。
Appにはcontext値や環境設定を渡せますが、秘密情報をCDK contextやリポジトリへ直接保存しないことが重要です。
認証情報はAWSの認証メカニズムや安全なシークレット管理へ分離します。
複数Stack間でリソースを参照すると、CDKが依存関係を推論できる場合があります。
ただし依存を増やしすぎると独立デプロイが難しくなるため、境界をまたぐ共有値は慎重に設計します。
App、Stack、Constructの関係を「プロジェクト全体→デプロイ単位→再利用部品」と捉えると、規模が大きくなってもコードを整理しやすくなります。
Appのエントリーポイントでは、どのStackをどの環境へ出すかが一目で分かる構造を保つと運用しやすくなります。
環境判定のロジックを複雑にしすぎると、同じコードでも実行条件によって構成が読み取りにくくなります。
複数アカウント展開では、環境ごとに認証情報をコードへ埋め込むのではなく、CI/CDの実行ロールやプロファイルなど外部の認証境界を使い、Appはデプロイ先情報だけを受け取る形が安全です。
コード例:S3バケットとLambda関数を作成する
ここではTypeScriptを前提に、S3バケットとLambda関数を同じStackで定義し、Lambdaへバケット読み取り権限を与える流れを確認します。
重要なのはコードを丸暗記することではなく、Construct同士をどう接続するかを理解することです。
実運用ではデータ保持や削除ポリシー、Lambdaのランタイム、ログ、権限範囲などを環境に合わせて調整する必要があります。
プロジェクト構成とインポート
TypeScriptでcdk init app –language typescriptを実行すると、CDK AppとStackを配置する基本的なプロジェクト構造が作成されます。
Stackファイルではaws-cdk-libからCDK本体を、aws-cdk-lib/aws-s3からS3、aws-cdk-lib/aws-lambdaからLambdaのConstructを読み込み、constructsからConstructを利用します。
典型的なStackクラスはcdk.Stackを継承し、constructorでscope、id、propsを受け取ってsuper(scope, id, props)を呼び出します。
リソースはそのStackの中でnew s3.Bucket(this, ‘MyStorageBucket’, {…})のように生成し、thisをscopeとしてConstruct treeへ追加します。
ConstructのIDはscope内で一意にする必要がありますが、実際の物理リソース名を必ず固定する必要はありません。
固定名を多用すると環境複製やStack再作成で衝突しやすくなります。
まずはCDKに名前生成を任せ、外部連携のために物理名が必要なリソースだけ明示する方が、複数環境へ展開しやすい設計になります。
依存パッケージはpackage.jsonとlockfileで固定し、CIでも同じ解決結果を使えるようにします。
CDK CLIとaws-cdk-libの互換性を意識し、突然のバージョン差でsynth結果が変わらないよう更新手順を決めます。
Stackファイルが肥大化したら、すぐ別Stackへ分けるのではなく、まずConstructへ抽出できないか検討します。
これによりデプロイ単位を変えずにコードの見通しだけ改善できます。
S3バケットを安全側に定義する
S3バケットのL2 Constructではversioned: true、encryption: s3.BucketEncryption.S3_MANAGED、blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALLのように目的に応じた設定を記述できます。
公開を必要としないバケットであれば、パブリックアクセスを明示的にブロックしておくと、意図しない公開設定を避けやすくなります。
暗号化方式は要件に合わせて選びます。
S3管理キーで十分なケースもあれば、キー管理や監査要件からKMSを選ぶケースもあるため、サンプル設定をそのまま本番標準にしないことが大切です。
元記事の例にあるRemovalPolicy.DESTROYは開発環境の後片付けには便利ですが、本番データを保持するバケットへ安易に適用すると削除時の事故につながります。
本番では削除保護、Retain方針、バックアップ、ライフサイクル、バージョニング、アクセスログなどをデータ重要度に合わせて検討します。
CDKの短いコードは設定が少ないことを意味するのではなく、Constructが内部でCloudFormation定義を生成していることを意識し、cdk synthや公式APIリファレンスで実際の構成を確認します。
S3はデータが残るサービスなので、検証時のDESTROYと本番の保持方針を同じコードパスで切り替える場合は、環境判定の誤りが事故へ直結します。
重要環境ではRetainを標準にするなど防御的な設計が有効です。
バケットポリシーやCORS、イベント通知を追加するときは、必要な主体と操作だけに絞ります。
CDKの便利なメソッドを使った後も、synthされたPolicy Documentを確認すると権限の実体を理解できます。
Lambda関数を定義してS3情報を渡す
LambdaのL2 Constructではruntime、handler、codeなどを指定し、関数コードの配置場所や実行環境を定義します。
公式のCDK APIではNode.js 20、22、24などのRuntime定数が提供されていますが、利用するリージョンとLambda側のサポート状況を確認して選ぶ必要があります。
ローカルでCDK CLIを動かすためのNode.js要件と、Lambda関数そのもののNode.jsランタイムは別の話です。
現在のCDK前提条件では開発環境にNode.js 22.x以降が案内されています。
S3バケット名をLambdaへ渡す場合はenvironmentにBUCKET_NAME: myBucket.bucketNameを指定する方法があります。
CDKは参照関係をCloudFormationで解決できる形に変換します。
ただし、環境変数へ機密情報を直接書く設計は避けます。
秘密情報はSecrets ManagerやParameter Storeなど、要件に合った安全な保管先を検討します。
Lambdaを本番利用する場合は、タイムアウト、メモリ、ログ保持、同時実行数、DLQや再試行、VPC接続の要否などもアプリケーション特性に合わせて明示します。
関数コードをfromAssetで配布する場合、アセットはbootstrapで用意されたS3などへアップロードされます。
巨大な依存関係を含めるとデプロイ時間も増えるため、ビルドやバンドル方式を別途設計する価値があります。
Node.js LambdaでTypeScriptを使う場合、CDKのStackコードとLambda実行コードは同じ言語でもビルド対象が異なります。
インフラ定義とアプリケーションの依存関係を分け、どちらのエラーか切り分けやすくします。
grantReadで権限を接続し、差分を確認する
S3のL2 ConstructにはmyBucket.grantRead(myHandler)のような権限付与メソッドがあり、対象Functionへ読み取りに必要なIAM設定を関連付けられます。
この記述はIAMポリシーの詳細を毎回手書きする負担を減らせますが、「常に完全な最小権限が保証される」と受け取るべきではありません。
生成される権限の範囲はConstructや利用方法によって変わるため、セキュリティ要件が厳しいシステムではsynth結果やIAMポリシーを確認します。
変更後はcdk diffで既存Stackとの差分を確認し、想定外のリソース削除、置換、権限拡大がないかレビューしてからデプロイします。
特にS3バケット名など置換に影響しやすいプロパティを変更する場合は、CloudFormation上でUpdateかReplacementかを確認し、データ移行計画と合わせます。
サンプルコードの目的は、BucketとFunctionを作ることよりも、Constructの参照を通じて名前やIAM関係を安全に接続できるCDKの設計感覚をつかむことです。
grantReadのようなメソッドはリソース間の意図をコードで表現できる点が利点です。
「このLambdaはこのBucketを読む」という関係が近い場所に書かれるため、Policy JSONを別ファイルで追うよりレビューしやすい場合があります。
一方で権限が増える変更はセキュリティレビュー対象です。
diffでIAM変更が表示されたら、追加Action、Resource範囲、条件の有無を確認し、不要なワイルドカードがないかチェックします。
基本的なCDKコマンドの流れ
CDKの開発では、初期化してすぐdeployするより、前提条件の確認、bootstrap、synth、diffを挟んでから反映する方が安全です。
コマンドの意味を理解しておくと、CI/CDへ移行するときも工程をそのまま整理できます。
特にbootstrapとdestroyは環境へ実リソースを作成・削除する操作につながるため、アカウント、リージョン、権限、対象Stackを確認して実行します。
事前準備とcdk init
AWS CDKを始めるには、AWSアカウント、利用する認証方式、AWS CLIの設定、Node.js、利用言語の開発環境などを準備します。
現在のAWS CDK v2前提条件では、サポート言語にかかわらずCDKのバックエンドを動かすためNode.js 22.x以降が必要と案内されています。
CDK CLIを利用できる状態にしたら、空のディレクトリを作成し、cdk init app –language typescriptのようにプロジェクトを初期化します。
cdk initはディレクトリ構造だけでなく、App、Stack、依存パッケージ、設定ファイルなどの土台を作るため、既存ファイルが多いディレクトリで無計画に実行しない方が安全です。
初期化後は生成されたbinとlibの役割を確認し、どこでAppを作り、どこでStackやConstructを定義するのかを把握します。
チーム開発ではこの時点からGit管理し、CDKライブラリとCLIのバージョン方針、Node.jsバージョン、フォーマッタやテストコマンドをREADMEや開発環境設定へ固定しておくと差異を減らせます。
認証情報は長期アクセスキーを固定配置するより、組織で採用しているSSOや一時クレデンシャルを優先します。
CDKはAWS SDK経由で認証するため、ローカルとCIで資格情報の取得方法をそろえるとトラブルが減ります。
サンプルを試す前に、請求が発生する可能性のあるリソースを確認します。
S3やLambdaだけでも使用量次第で課金され、NAT GatewayやRDSなどを追加すると検証でも費用が増えるため、予算アラームも有効です。
cdk bootstrapでデプロイ先を準備する
AWS CDKのbootstrappingでは、StackをデプロイするAWS環境を事前に準備します。
AWS環境はアカウントとリージョンの組み合わせとして扱われます。
cdk bootstrapはCDKがデプロイで利用するS3バケット、ECRリポジトリ、IAMロールなどのbootstrap resourcesを作成します。
CDKプロジェクト内から引数なしで実行する場合、CLIはアプリやプロファイルから対象環境を解決できますが、意図したアカウントとリージョンか事前に確認する習慣が重要です。
複数アカウントを使う組織ではaws sts get-caller-identityや使用プロファイルを確認し、本番アカウントへの誤操作を防ぐ手順を用意します。
bootstrapで作られるIAMロールや信頼設定はデプロイ権限に直結します。
–trustやCloudFormation実行ポリシーを使う場合は、誰にどの権限を渡すかを理解して設定します。
環境ごとに一度準備すれば毎デプロイでbootstrapする必要はありませんが、テンプレートの更新や組織ポリシー変更に合わせて再bootstrapが必要になるケースがあります。
bootstrap Stackの名前やQualifierをカスタマイズする高度な構成もありますが、入門段階では既定構成を理解してから変更する方が安全です。
独自化するとsynthesizer側との整合も考える必要があります。
組織のセキュリティポリシーでIAM権限が制限されている場合、bootstrap自体が失敗することがあります。
その場合は権限を広げる前に、必要なロールと実行ポリシーをプラットフォーム管理者と確認します。
cdk synthとcdk diffで変更を検査する
cdk synthはCDKアプリを実行し、StackからCloudFormationテンプレートやデプロイアーティファクトを生成するコマンドです。
アプリの構文エラーや一部の検証エラーをデプロイ前に発見できるため、CIでsynthを必須にする運用は有効です。
生成テンプレートを見ると、短いCDKコードから多数のCloudFormationリソースが作られている場合があるため、抽象化の実体を理解する教材にもなります。
cdk diffは現在デプロイ済みのStackとローカル定義との差分を確認するために使います。
変更内容が予想どおりか、削除や置換が含まれていないかをデプロイ前に確認します。
差分確認ではリソース数だけでなく、IAM権限の拡大、Security Group、公開設定、暗号化、データ保持設定など、セキュリティや可用性へ影響する変更を重点的に見ます。
Pull Requestの段階でsynth結果やdiff結果をレビューできるようにすると、コンソール手作業では見えにくかった変更履歴をチームで共有しやすくなります。
synthをCIで実行して生成物の差分を保存すると、CDKライブラリ更新による意図しない変化も検知しやすくなります。
ただし生成物をGitへ常時コミットするかは、チームのレビュー方式に合わせて決めます。
diffに何も出ないことだけを成功条件にせず、意図した変更が正しく出ていることを確認します。
設定ミスで対象Stackや環境を間違えている場合、差分が小さいこと自体が異常の手掛かりになります。
cdk deployとcdk destroyを安全に使う
cdk deployは合成されたCloudFormationテンプレートと必要なアセットを使い、CloudFormation経由でAWSリソースをプロビジョニングします。
デプロイ前にCDK CLIへ渡される認証情報と対象環境を確認し、本番では個人の強い権限よりCI/CD用ロールや承認フローを使う設計を検討します。
CloudFormation側で失敗した場合はイベントを確認し、どのリソースでどの権限や制約が原因になったかを追います。
CDKだけを見ていても原因が分からないことがあります。
cdk destroyはStackを削除する操作で、開発環境の後片付けには便利ですが、データを持つリソースのRemovalPolicyによっては重要データへ影響します。
削除前には対象Stack、保持ポリシー、スナップショット、共有リソース、他Stackからの依存を確認し、特に本番では手軽なクリーンアップコマンドとして扱わないことが重要です。
開発フローはinit → bootstrap → synth → diff → deployを基本にし、不要になった検証環境だけdestroyするという順序を覚えておくと、操作の意味を整理しやすくなります。
本番deployでは–require-approvalの扱いやCIの承認ステップをチームで統一し、個人ごとに確認粒度が変わらないようにします。
自動化するほど、前段のdiffとテストの品質が重要になります。
destroyは「元に戻す」コマンドではありません。
削除後に同じCDKをdeployしても、保持されていないデータは復元されないため、状態を持つリソースではバックアップと復旧手順を別に用意します。
まとめ:インフラ構築をもっとスピーディかつ安全に
AWS CDKの価値は、YAMLを短くすることではなく、インフラを再利用可能なコードとして設計し、レビュー・テスト・差分確認を含む開発工程へ載せられる点にあります。
CloudFormationの実行基盤を理解しながら使うことで、便利さと安全性を両立しやすくなります。
最初から大規模基盤へ導入するより、小さな検証StackでConstruct、synth、diff、deployの流れを体験し、チームの標準へ段階的に広げるのがおすすめです。
最初の1週間で試したい実践ステップ
最初はS3やLambdaなど、削除しても影響が限定される検証用リソースから始めます。
個人の本番環境を直接触るのではなく、検証用アカウントや明確に分離したSandboxを使うと安全です。
次にL2 Constructで小さなStackを作り、cdk synthで生成されたCloudFormationを確認して、CDKコードと実際のAWSリソース定義の対応を見比べます。
その後、プロパティを1つ変更してcdk diffを実行し、どの変更がUpdate、Replacement、IAM変更として現れるかを観察します。
問題がなければcdk deployで反映し、AWSコンソールやCLIから作成されたリソースを確認します。
手作業で追加変更を加えず、変更は原則としてCDK側へ戻す習慣を作ります。
最後に不要な検証環境をcdk destroyで削除し、どのリソースが消え、どのリソースが保持されたかをRemovalPolicyと合わせて確認します。
この一連の流れを小さく経験してから、テスト、Construct共通化、CI/CD、複数アカウント展開へ進むと、抽象化だけを先に作り込む失敗を避けやすくなります。
検証が終わったら、変更履歴をGitに残し、どのコミットでどのStackが変わったか追えるようにします。
コンソールで行った緊急変更も放置せず、必要ならCDKへ反映して構成の正本を戻します。
次の段階ではassertionsを使ったテンプレートテストや、組織の標準Constructを試すと、単にデプロイできるだけでなく「期待する構成を守れているか」を自動検証しやすくなります。
導入前チェックリスト
管理対象が主にAWSで、アプリケーション開発者とインフラ担当がコードレビューを共有できるなら、CDKは有力な選択肢です。
チームが使う言語、CDKとNode.jsのバージョン、AWS認証方式、bootstrap方針、アカウント・リージョン分離を最初に決めておくと環境差を減らせます。
Constructは再利用単位、Stackはデプロイ単位、Appは全体のルートという役割を守り、何でも1つのStackへ詰め込む設計や、逆に細分化しすぎる設計を避けます。
本番データを扱うS3、データベース、ログなどでは、削除ポリシー、暗号化、バックアップ、アクセス制御をサンプルコード任せにせず要件として確認します。
デプロイ前にはsynthとdiffを実行し、生成CloudFormation、IAM、削除・置換、公開範囲をレビューできる工程を用意します。
CDKを導入すれば自動的に安全になるわけではありませんが、変更をコードとして残し、同じ手順を再現し、レビュー可能にすることで、手作業中心の運用より改善できる余地が大きくなります。
運用責任者を決め、CDKライブラリ更新、Node.js更新、bootstrap更新、脆弱性対応を誰が継続するか明確にします。
IaCは導入時より、数年後まで安全に更新できるかが重要です。
最後に、CDKを使わない場合の代替手段も残して比較します。
CloudFormationやTerraformが既に安定運用されているなら、その強みを壊さずCDKを適用する範囲を限定する判断も十分に合理的です。