👬

[CDK] -e オプションで依存関係を解消

2024/04/25に公開

スタックの再デプロイ時に、他スタックとの依存関係により正常にデプロイができず、解決までに時間がかかってしまったため、備忘録として残しておきます。

では、初めて行きます。

CDKとは

CDK(Cloud Development Kit)は、クラウドインフラストラクチャをコードで管理するためのツール。
昨今では当たり前となってきましたが、従来はコンソール画面からリソースを手動で設定、構築していましたが、CDKを使用することで、プログラミング言語(TypeScript、Python、Java など)を使ってクラウドリソースを記述し、コードとして管理できるようになります。

そのため、毎回コンソール画面に入り、各リソースを順を追って確認しなくても、コードさえ読めれば、配置されているリソースやインフラの構成が理解できるようになります。

また、CDKはスタックという単位で複数のまとめたリソースをデプロイしていくため、スタックの削除や、更新(厳密に言えば、スタック内の各リソースの削除や更新)といった操作がコード上で行えるため、開発者にとって利便性が高いのもポイントです。

引用元:https://docs.aws.amazon.com/ja_jp/cdk/v2/guide/home.html

基本的なコマンド

コマンド 機能
cdk init 新しいCDKプロジェクトを作成
cdk synth 指定した1つ以上のスタックのCFnテンプレートを合成して印刷
cdk diff ローカルのCDKアプリケーションとデプロイされたスタックの差分を表示
cdk deploy 指定した1つ以上のスタックをデプロイ
cdk destroy 指定した1つ以上のスタックを削除
cdk list アプリ内のスタックを一覧表示
cdk bootstrap AWSアカウント内のCDKリソースをセットアップ(初回のみ実行)
  • synthは、想定通りのリソースが定義されていることを確認する際に使用します。
  • bootstrapは、デプロイのための環境を準備するプロセスであり、各環境毎(開発・検証・本番等)異なるアカウントを利用する場合、初回デプロイ前に必ず実行するコマンドとなります。

今回困ったこと

本題を理解する前の最低限の知識として、前置きが長くなりましたが、一言でまとめると、
あれ、前はデプロイできたのに、今回はデプロイできないぞ」です。

背景

日次で動かすバッチをStep Functionsで構築し、2回目にデプロイを実行したところ、

別のスタックで使われているものを削除できないぞ!

といったエラーが吐かれました。
(以前に出会したエラーのため、エラーログを記載できず申し訳ないです)

原因

CDKは、CFnを利用してデプロイ作業を行います。

CFnは「中断を行わない更新」「一時的な中断を伴う更新」「置換」の3つがあり、すでにデプロイ済みのスタックと依存関係のあるスタックをデプロイすると、既存のリソースに影響を及ぼしてしまいます。
https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks-update-behaviors.html

例えば、今回のケースでいえば、以下の操作手順でエラーとなります。

  • スタックA(対象スタック)を初回デプロイ
  • 次にスタックBでスタックAのリソースをどれかしら使用してデプロイ → ここで依存関係が生まれる
  • 次にスタックAの仕様変更に伴い一部リソースを変更後、デプロイ → ERROR!!!!

つまり、「スタックBで使われているものにスタックAで変更を加えると、スタックBがエラーになる恐れがあるからデプロイできません」ということになります。

解決策

結論、「-e」を使いましょう。
こんな感じ

cdk deploy -e TargetStack --profile profileName

-eとは

コマンドで確認してみましょう。

% cdk deploy --help
cdk deploy [STACKS..]

Deploys the stack(s) named STACKS into your AWS account

Options:
  -a, --app                  REQUIRED WHEN RUNNING APP: command-line for
                             executing your app or a cloud assembly directory
                             (e.g. "node bin/my-app.js"). Can also be specified
                             in cdk.json or ~/.cdk.json                 [string]
      --build                Command-line for a pre-synth build         [string]
  -c, --context              Add contextual string parameter (KEY=VALUE) [array]
  -p, --plugin               Name or path of a node package that extend the CDK
                             features. Can be specified multiple times   [array]
      --trace                Print trace for stack warnings            [boolean]
      --strict               Do not construct stacks with warnings     [boolean]
      --lookups              Perform context lookups (synthesis fails if this is
                             disabled and context lookups need to be performed)
                                                       [boolean] [default: true]
      --ignore-errors        Ignores synthesis errors, which will likely produce
                             an invalid output        [boolean] [default: false]
  -j, --json                 Use JSON output instead of YAML when templates are
                             printed to STDOUT        [boolean] [default: false]
  -v, --verbose              Show debug logs (specify multiple times to increase
                             verbosity)                 [count] [default: false]
      --debug                Enable emission of additional debugging
                             information, such as creation stack traces of
                             tokens                   [boolean] [default: false]
      --profile              Use the indicated AWS profile as the default
                             environment                                [string]
      --proxy                Use the indicated proxy. Will read from HTTPS_PROXY
                             environment variable if not specified      [string]
      --ca-bundle-path       Path to CA certificate to use when validating HTTPS
                             requests. Will read from AWS_CA_BUNDLE environment
                             variable if not specified                  [string]
  -i, --ec2creds             Force trying to fetch EC2 instance credentials.
                             Default: guess EC2 instance status        [boolean]
      --version-reporting    Include the "AWS::CDK::Metadata" resource in
                             synthesized templates (enabled by default)[boolean]
      --path-metadata        Include "aws:cdk:path" CloudFormation metadata for
                             each resource (enabled by default)        [boolean]
      --asset-metadata       Include "aws:asset:*" CloudFormation metadata for
                             resources that uses assets (enabled by default)
                                                                       [boolean]
  -r, --role-arn             ARN of Role to use when invoking CloudFormation
                                                                        [string]
      --staging              Copy assets to the output directory (use
                             --no-staging to disable the copy of assets which
                             allows local debugging via the SAM CLI to reference
                             the original source files)[boolean] [default: true]
  -o, --output               Emits the synthesized cloud assembly into a
                             directory (default: cdk.out)               [string]
      --notices              Show relevant notices                     [boolean]
      --no-color             Removes colors and other style from console output
                                                      [boolean] [default: false]
      --ci                   Force CI detection. If CI=true then logs will be
                             sent to stdout instead of stderr
                                                      [boolean] [default: false]
      --version              Show version number                       [boolean]
      --all                  Deploy all available stacks
                                                      [boolean] [default: false]
  -E, --build-exclude        Do not rebuild asset with the given ID. Can be
                             specified multiple times      [array]

===================ここですね!====================
[default: []]
  -e, --exclusively          Only deploy requested stacks, don't include
                             dependencies
===================ここですね!====================                           [boolean]
      --require-approval     What security-sensitive changes need manual
                             approval
                         [string] [choices: "never", "any-change", "broadening"]
      --notification-arns    ARNs of SNS topics that CloudFormation will notify
                             with stack related events                   [array]
  -t, --tags                 Tags to add to the stack (KEY=VALUE), overrides
                             tags from Cloud Assembly (deprecated)       [array]
      --execute              Whether to execute ChangeSet (--no-execute will NOT
                             execute the ChangeSet) (deprecated)
                                                          [deprecated] [boolean]
      --change-set-name      Name of the CloudFormation change set to create
                             (only if method is not direct)             [string]
  -m, --method               How to perform the deployment. Direct is a bit
                             faster but lacks progress information
                [string] [choices: "direct", "change-set", "prepare-change-set"]
  -f, --force                Always deploy stack even if templates are identical
                                                      [boolean] [default: false]
      --parameters           Additional parameters passed to CloudFormation at
                             deploy time (STACK:KEY=VALUE) [array] [default: {}]
  -O, --outputs-file         Path to file where stack outputs will be written as
                             JSON                                       [string]
      --previous-parameters  Use previous values for existing parameters (you
                             must specify all parameters on every deployment if
                             this is disabled)         [boolean] [default: true]
      --toolkit-stack-name   The name of the existing CDK toolkit stack (only
                             used for app using legacy synthesis)       [string]
      --progress             Display mode for stack activity events
                                             [string] [choices: "bar", "events"]
      --rollback             Rollback stack to stable state on failure. Defaults
                             to 'true', iterate more rapidly with --no-rollback
                             or -R. Note: do **not** disable this flag for
                             deployments with resource replacements, as that
                             will always fail                          [boolean]
      --hotswap              Attempts to perform a 'hotswap' deployment, but
                             does not fall back to a full deployment if that is
                             not possible. Instead, changes to any
                             non-hotswappable properties are ignored.Do not use
                             this in production environments           [boolean]
      --hotswap-fallback     Attempts to perform a 'hotswap' deployment, which
                             skips CloudFormation and updates the resources
                             directly, and falls back to a full deployment if
                             that is not possible. Do not use this in production
                             environments                              [boolean]
      --watch                Continuously observe the project files, and deploy
                             the given stack(s) automatically when changes are
                             detected. Implies --hotswap by default    [boolean]
      --logs                 Show CloudWatch log events from all resources in
                             the selected Stacks in the terminal. 'true' by
                             default, use --no-logs to turn off. Only in effect
                             if specified alongside the '--watch' option
                                                       [boolean] [default: true]
      --concurrency          Maximum number of simultaneous deployments
                             (dependency permitting) to execute.
                                                           [number] [default: 1]
      --asset-parallelism    Whether to build/publish assets in parallel
                                                                       [boolean]
      --asset-prebuild       Whether to build all assets before deploying the
                             first stack (useful for failing Docker builds)
                                                       [boolean] [default: true]
      --ignore-no-stacks     Whether to deploy if the app contains no stacks
                                                      [boolean] [default: false]
  -h, --help                 Show help                                 [boolean]

何やらたくさん出てきましたが、-eに関する説明は以下です。

Only deploy requested stacks, don't include dependencies

「要求されたスタックのみをデプロイし、依存関係は含めない。」とのことです。

つまり、先の例で見ると、スタックBとの依存関係は含めず、スタックA(対象のスタック)のみをデプロイすることで、依存関係のあるリソース及びスタックに影響を与えることなく、デプロイすることが可能となります。

無事解決!

まとめ

CDKは便利な反面、CFnテンプレートによるインフラ構築を行うが故のエラーが発生することがあるため、注意が必要で、エラーが出たらまずCDKのオプションから解決できることかを探る必要があると感じました。

今回の記事が誰かのお役に立てれば幸いです。

NCDCエンジニアブログ

Discussion