AWSインフラの深淵:CloudFormationとCDKの「戦術的」使い分け、その極致へ
インフラの構築を「コード」にするという概念が普及して久しい。だが、AWS CDKという抽象度の高い抽象化レイヤーが標準となった今、あえて生のCloudFormation(以下、CFn)を語ることは時代錯誤だろうか?
否。真のSREは、抽象化されたライブラリが生成する「実体」を制御できなければならない。 抽象化の裏側で何が起きているかを知ることは、トラブルシューティングの最終防衛線であり、パフォーマンスチューニングの源泉だ。
本稿では、CDKという甘美な抽象化と、CFnという冷徹な実体との間で、我々エンジニアがどう立ち回るべきかを解き明かす。
—
1. 抽象化の代償とCloudFormationの本質
AWS CDKは、TypeScriptやPythonなどの汎用言語でインフラを定義できる強力なツールだ。しかし、CDKはあくまで「CFnテンプレートを合成するジェネレーター」に過ぎない。
- CDKの内部構造: あなたが書いたCDKコードは、`cdk synth`を経て巨大なJSON/YAMLファイルへと変換される。
- CFnの絶対性: 最終的にAWSリソースを管理するエンジンはCFnだ。スタックの更新履歴、ロールバックの挙動、リソース間の依存関係解決は、すべてCFnのエンジンが司る。
極限の知見: CDKの抽象化(Constructs)が生成するテンプレートは、時に冗長で、AWSの制限(テンプレートサイズ上限など)に抵触しやすい。大規模なマイクロサービス構成では、CDKが生成したテンプレートを一度「分解」し、CFnのNested StacksやCross-Stack Referenceを最適化して再構築する技術が必要になる。
—
2. 生のCloudFormationを「あえて」書くべき瞬間
なぜ、あえて手書きのCFnを選ぶのか。それは「決定論的な制御」が必要な時だ。
メリット:完全な制御と移植性
- 依存関係の透明性: `DependsOn`を明示的に制御できるため、複雑な順序依存を抱えるレガシー移行環境では、CDKの抽象化よりも生のCFnの方がデバッグが容易だ。
- ツール依存の排除: CDKのバージョンアップによる破壊的変更を気にする必要がない。AWSのAPI仕様が変わらない限り、CFnは永続的に動作する。
デメリット:保守性の死
- DRY原則の欠如: 似たようなリソースの繰り返しを記述する場合、テンプレートが肥大化し、修正漏れが多発する。
- 計算ロジックの欠如: 条件分岐やループ処理は`Fn::If`や`Fn::Select`等で書く必要があるが、これらは読みづらく、保守の悪夢になり得る。
最適化ハック: CFnを直接書く際は、`Cfn-lint`と`TaskCat`をCIパイプラインに組み込むことが必須だ。特にTaskCatは、複数リージョンでのスタック作成と削除を自動化し、テンプレートが環境非依存であることを証明する唯一の手段となる。
—
3. スキルセットと戦略:チームの「武装」を変える
チームの成熟度によって、採用する武器は変わるべきだ。
| チーム状況 | 推奨戦略 | 理由 |
| :— | :— | :— |
| アプリ開発主体 | AWS CDK | 抽象化による認知負荷の低減。ビジネスロジックに集中させる。 |
| SRE・プラットフォームチーム | CFn + カスタムツール | AWS SDK (boto3/aws-sdk-js) との組み合わせで、CI/CDパイプラインからCFnを動的に生成・注入する。 |
エキスパートの提言:
インフラの「型」が決まっているなら、CDKの`Aspects`機能を使って、全リソースにセキュリティタグやバックアップ設定を強制注入する仕組みを作れ。逆に、多様なリソースが複雑に絡み合う疎結合なシステムでは、CFnのモジュール化(Nested Stacks)を極める方が、CDKの巨大な依存関係グラフを解読するより遥かに健全だ。
—
4. ロードマップ:インフラエンジニアの深淵へ
Stage 1: CFnの「構造」を理解する
まずは、`AWS::CloudFormation::Stack`リソースを使い、スタックを階層化する設計を学べ。これができないままCDKに逃げるのは、泥沼を歩くようなものだ。
Stage 2: AWS SDKとの連携(自動化の極み)
CFnを単体で使わず、AWS CLIやSDKを用いて、動的にパラメータを注入する独自のデプロイ・スクリプトを書け。
現場で使える「冪等性を担保したデプロイ」の断片
import boto3
def deploy_stack(stack_name, template_body, parameters):
cfn = boto3.client(‘cloudformation’)
try:
# 既存スタックの更新を試みる
cfn.update_stack(StackName=stack_name, TemplateBody=template_body, Parameters=parameters)
except cfn.exceptions.ClientError as e:
if ‘No updates are to be performed’ in str(e):
print(“No changes required. Idempotency maintained.”)
else:
raise e
Stage 3: メモリとパフォーマンスの最適化
CFnのスタックサイズ上限(5MB)に達したとき、どう分割し、どう値を渡すか。`Export/ImportValue`を使いすぎると、スタック間の「密結合」が発生し、削除不能なスタックが爆誕する。これを回避する設計思想(DynamoDBを状態管理のバックエンドに使う等)を身につけることが、君を真のインフラアーキテクトへと変える。
—
最後に:ツールは魂を写す鏡である
CDKは「生産性」を、CFnは「確実性」を体現している。
どちらか一方に固執するのは、片目をつぶって戦場を歩くようなものだ。
CDKで高速にプロトタイプし、CFnの深淵で堅牢に守る。
この二刀流こそが、クラウド時代のエンジニアがたどり着くべき、最も美しく、最も効率的な解である。
さあ、コードを開け。あなたのインフラは、まだ最適化の余地を残しているはずだ。