なぜCDKはツールキットスタックを要求するのか?
cdk deploy を実行した際、プログレスバーが表示される代わりに大量のテキストが表示されることがあります。エラー内容は以下の通りです:
Error: This stack uses assets, so the toolkit stack must be deployed to the environment (Run "cdk bootstrap aws://123456789012/us-east-1")
これは、CDKコードに「アセット(assets)」が含まれているために発生します。アセットとは、5MBのPython製Lambda関数や200MBのDockerイメージなどのローカルファイルのことで、CloudFormationが直接処理できないものです。CDKは、インフラをデプロイする前にこれらのファイルを一時的に保存するステージング領域を必要とします。
「ツールキットスタック」(名称:CDKToolkit)はこのステージング領域を提供します。これにより、ファイル保存用のS3バケットと、デプロイ権限のためのIAMロールがセットアップされます。AWSアカウントとリージョンの初期化が行われていない場合、CDKはコードを配置する場所を確保できません。
解決策:環境のブートストラップ
1. 標準コマンド
最も手っ取り早い解決策は、ターミナルに表示された推奨コマンドをそのまま実行することです。アカウントIDとリージョンは、ご自身の環境に合わせて置き換えてください:
cdk bootstrap aws://123456789012/us-east-1
2〜3分ほど待ちます。CDKがCloudFormationスタックを作成し、必要なS3バケットと暗号化キーをプロビジョニングします。
2. AWSプロファイルの使用
デプロイ時に --profile フラグを使用している場合は、ブートストラップ時にもそれを使用する必要があります。これを忘れると、誤ったAWSアカウントをブートストラップしてしまう可能性があります。
cdk bootstrap --profile prod-account aws://123456789012/us-east-1
3. 複数リージョンへのデプロイ
ブートストラップはリージョンごとに必要です。アプリケーションが us-east-1(バージニア北部)と us-west-2(オレゴン)の両方にまたがる場合は、両方のリージョンでコマンドを実行する必要があります。CDKは各リージョンに個別の CDKToolkit スタックを作成し、アセットをローカルに保存することでデプロイを高速化します。
4. 「Permission Denied」エラーの解決
ブートストラップはIAMロールやS3バケットを作成するため、高い権限を必要とするアクションです。「Access Denied」エラーが表示される場合、現在のIAMユーザーに AdministratorAccess ポリシーが不足している可能性があります。管理者に一時的な権限昇格を依頼するか、管理者にブートストラップコマンドを実行してもらってください。
解決したか確認する方法
ターミナルの表示を信じるだけでなく、実際にCDKが構築したインフラを以下の場所で確認できます:
- CloudFormation:
CDKToolkitという名前のスタックを探します。ステータスがCREATE_COMPLETEになっているはずです。 - S3コンソール:
cdk-hnb659fds-assets-[account]-[region]という名前の新しいバケットが見つかります。ここにLambdaの.zipファイルが保存されます。 - IAM: ファイルのパブリッシュやCloudFormationの実行を処理するために、
cdk-hnb659fds-で始まる複数のロールが作成されます。
ベストプラクティス
一度限りのセットアップ: アカウントとリージョンのブートストラップは一度だけで十分です。GitHub ActionsやJenkinsのパイプラインスクリプトに cdk bootstrap を含める必要はありません。含めてしまうと、CI/CDの実行時間が不必要に増えるだけです。
CDK v1 vs v2: 最近CDK v1からv2にアップグレードした場合は、再ブートストラップが必要になることがあります。CDK v2は、レガシーバージョンよりもセキュリティが向上し、クロスアカウントデプロイをサポートする「モダン」なブートストラップテンプレートを使用します。
コスト: 作成されたS3バケットは、空であれば実質無料です。課金されるのはアップロードしたアセットのストレージ料金のみです。AWSの請求額が増えていることに気づいたら、バケットを確認し、古いバージョンのLambda関数やDockerイメージを削除してください。

