CDKで作成したNestedStackの差分を確認したい

こんにちは、SREチームの成田です。 今回もCDKネタで、CDKでNestedStackを使用した際にcdk diffで差分が確認できないという問題に対してのハックを紹介します。

CDKについてはこちらの記事にて紹介してますので、よろしければご覧ください。 techblog.kiramex.com

NestedStackについて

NestedStackは名前の通りスタックを入れ子にして定義出来るCloudFormationの機能です。 こちらのイメージのようにスタックを階層的に定義することができます。

f:id:nrt-krmx:20210816212306p:plain

ネストされたスタックの操作 - AWS CloudFormation

CDKでNestedStackを使用する場合は、class NestedStackを使用して子スタックを定義すると、親スタックで参照出来るようになります。

docs.aws.amazon.com

CDKでNestedStackを使用する際の問題点

CDKでNestedStackを使用したスタックを作成すると、cdk diffでの差分確認で、親スタックの差分は確認できますが子スタックの差分は確認することができません。

こちらのイメージでは、子スタックでECSを更新していますが、差分表示では親スタックのCloudFormationの差分(子スタックのCloudFormationテンプレートの更新)のみしか出てきません。

f:id:nrt-krmx:20210816214810p:plain

この問題に対してCDKでissueが上がっているものの、どうやら対応される見込みはなさそうです。

github.com

CloudFormation ChangeSetでNestedStackの差分確認

そこで、cdk diffで差分を確認するのではなく、CloudFormationのChangeSetを使用して子スタックの差分確認をしてみます。

ChangeSetはスタックの更新前に変更箇所の確認をすることが出来るCloudFormationの機能です。 下記のイメージのように、更新の実行前にChangeSetを作成して変更箇所を確認することで安心してスタックの更新が行なえます。

f:id:nrt-krmx:20210817210023p:plain

docs.aws.amazon.com

まずはCDKでCloudFormationテンプレートを出力し、ChangeSetを作成します。 cdk deploy--no-executeをつけて実行すると、ChangeSetの作成のみが行われ実行はされません。

$ npx cdk synth
$ npx cdk deploy --no-execute

これで作成されたルートスタックのChangeSetには子スタックの差分は含まれない(子スタックのCloudFormationテンプレートの更新のみ表示される)ので、このChangeSetをベースに子スタックの差分を含むChangeSetを手動で作成します。

f:id:nrt-krmx:20210817112217p:plain

CloudFormationのコンソール画面で、ルートスタックのスタックアクションから、既存スタックの変更セットを作成を実行します。 指定するテンプレートは、CDK作業ディレクトリのcdk.out/に出力されている親スタックのテンプレートをアップロードして使用します。

f:id:nrt-krmx:20210817112921p:plain

CDKで作成したChangeSetを参考にパラメータを設定します。

f:id:nrt-krmx:20210817113420p:plain

最後に、ネストされたスタックの変更セットが有効になっていることを確認し、ChangeSetを作成します。

f:id:nrt-krmx:20210817113647p:plain

こうして作成したChangeSetでは子スタックのChangeSetも同時に作成され、子スタックでの変更内容も確認することができます。

f:id:nrt-krmx:20210817114228p:plain

注意点

ChangeSetの実行はCDKで作成されたChangeSetで行う

手動で作成したChangeSetはあくまで差分確認用です。 差分確認が済んだら手動で作成したChangeSetを削除し、変更の適応はCDKで作成したChangeSetを実行するのが安全です。

そもそもNestedStackのChangeSetには不具合がありそう

子スタック間、または子スタックと孫スタック間での参照の際に変更箇所が不適切に検出されたり、ChangeSetの作成に失敗する模様です。(下記issue参照) ただ、親子スタック間での参照であれば大丈夫そうな感じでした。

github.com

github.com

最後に

cdk diffで表示される差分は、ローカルで作成したルートスタックのテンプレート差分のみしか表示されないので、子スタックの差分が表示されません。 そこで、CloudFormationのChangeSetを使用して子スタックの差分を確認するというアプローチを行いました。

ちなみに、ChangeSet作成に使用されるAPIの、CreateChangeSetでIncludeNestedStacksパラメータがTrueの場合(デフォルトはFalse)子スタックを含めた差分表示が行われます。 cdk deploy --no-executeで実行されるCreateChangeSetではこのパラメータがFalseのため子スタックの差分が表示されず、再度コンソール画面から手動で作成する際にネストされたスタックの変更セットを有効にすることでこのパラメータをTrueでCreateChangeSetを実行できるので、子スタックの差分が表示されるようになったわけです。

docs.aws.amazon.com

このように少し癖のあるNestedStackですが、スタックの分割に便利な機能なのでうまく使いこなしていきたいですね。