AWS CDKでStackをネスト (入れ子) にしてデプロイする方法を記します。
はじめに
おはよう。@bioerrorlogです。
AWS CDKでStackをネスト(入れ子)にしようとしたところ、単純に入れ子にしたのでは上手くデプロイできないことに気が付きました。
Stackを入れ子にするにはひと工夫必要だったので、そのやり方の備忘録を残します。
なお、本記事で使用するコードは以下のGitHubにも置いてあります。
github.com
作業環境
今回の作業環境は以下の通りです。
CDKバージョン:
$ cdk --version 1.31.0 (build 8f3ac79)
言語はPythonを使用しました。
Pythonバージョン:
$ python --version Python 3.6.10
Amazon LiunxのCloud9で作業を行いました。
$ cat /etc/system-release Amazon Linux AMI release 2018.03
CDKでStackをネストにする
問題: Stackが入れ子にできない
さて、今回の問題はStackが入れ子にできない、という点にあります。
例えば、以下のように単純に入れ子状のStackを作ったとします。
from aws_cdk import core import aws_cdk.aws_s3 as s3 class ParentStack(core.Stack): def __init__(self, scope: core.Construct, id: str, **kwargs) -> None: super().__init__(scope, id, **kwargs) ChildStack01(self, "ChildStack01") ChildStack02(self, "ChildStack02") class ChildStack01(core.Stack): def __init__(self, scope: core.Construct, id: str, **kwargs) -> None: super().__init__(scope, id, **kwargs) s3.Bucket(self, "ChildBucket01", bucket_name="child-bucket-01") class ChildStack02(core.Stack): def __init__(self, scope: core.Construct, id: str, **kwargs) -> None: super().__init__(scope, id, **kwargs) s3.Bucket(self, "ChildBucket02", bucket_name="child-bucket-02") app = core.App() ParentStack(app, "ParentStack") app.synth()
このCDKコードを絵に描き表すと、次のような親子関係になっています。
ここで期待する動作は、親Stackである ParentStack
をデプロイすることで、子Stackたちも同時にデプロイされる、というものです。
しかし、この状態で親Stackをデプロイしても、子StackならびにS3リソースはデプロイされませんでした。
まず、CDKコマンドから cdk synth
と cdk deploy
を行うと、一見うまくいっているように見えます。
$ cdk synth Successfully synthesized to /home/ec2-user/environment/cdk-test/cdk.out Supply a stack id (ParentStack, ParentStackChildStack01796333D2, ParentStackChildStack0287B3CF12) to display its template. $ cdk deploy ParentStack ParentStack: deploying... ParentStack: creating CloudFormation changeset... 0/2 | 11:49:11 PM | CREATE_IN_PROGRESS | AWS::CDK::Metadata | CDKMetadata 0/2 | 11:49:13 PM | CREATE_IN_PROGRESS | AWS::CDK::Metadata | CDKMetadata Resource creation Initiated 1/2 | 11:49:13 PM | CREATE_COMPLETE | AWS::CDK::Metadata | CDKMetadata 2/2 | 11:49:15 PM | CREATE_COMPLETE | AWS::CloudFormation::Stack | ParentStack ParentStack
しかし、作成されたCloudFormation Stack ParentStack
の中身を見てみると、リソースが何もデプロイされていないことが分かります。
このように、単純にStackを入れ子状にしても、期待する動作はしてくれないことが判明しました。
解決策: NestedStackを使う
この問題についての解決策は、思ったより単純でした。
子Stackに core.Stack
を継承させる代わりに、aws_cloudformation
の NestedStack
を継承させれば良いのです。
必要な変更は、以下の2点です。
import aws_cdk.aws_cloudformation as cfn
を追加- 子Stackの継承を
core.Stack
からcfn.NestedStack
に変更
※CDKのcloudformationパッケージをまだインストールしていない場合は、
pip install aws-cdk.aws-cloudformation
でインストールします。
先ほどのCDKコードを書きなおすと、次のようになります。
from aws_cdk import core import aws_cdk.aws_s3 as s3 import aws_cdk.aws_cloudformation as cfn # cloudformationのインポート class ParentStack(core.Stack): def __init__(self, scope: core.Construct, id: str, **kwargs) -> None: super().__init__(scope, id, **kwargs) ChildStack01(self, "ChildStack01") ChildStack02(self, "ChildStack02") class ChildStack01(cfn.NestedStack): # NestedStackの継承 def __init__(self, scope: core.Construct, id: str, **kwargs) -> None: super().__init__(scope, id, **kwargs) s3.Bucket(self, "ChildBucket01", bucket_name="child-bucket-01") class ChildStack02(cfn.NestedStack): # NestedStackの継承 def __init__(self, scope: core.Construct, id: str, **kwargs) -> None: super().__init__(scope, id, **kwargs) s3.Bucket(self, "ChildBucket02", bucket_name="child-bucket-02") app = core.App() ParentStack(app, "ParentStack") app.synth()
それでは、書き直したCDKコードを cdk deploy
でデプロイし、再びCloudFormationコンソールを確認します。
するとこのように、親Stackに加えて、子StackがNested Stackとしてデプロイされました。
これら二つの子Stackは、親Stackのリソースとしてデプロイされていることがわかります。
このようにして、CDK Stackを入れ子にしてデプロイすることに成功しました。
おわりに
今回は、CDK Stackを入れ子にする方法を記しました。
シンプルに解決できたので、この NestedStack
はなかなかに有用だと感じました。
CDKのことを知れば知るほど、その便利さを噛みしめています。
[関連記事]
参考
Nested stack support · Issue #239 · aws/aws-cdk · GitHub
NestedStack — AWS Cloud Development Kit 1.94.1 documentation