AWS: CloudFormation – Nested Stacks and stacks parameters Import/Export
Tags: aws, tutorial, todayilearned
Published: 2020-02-29 12:57:32

---
title: AWS: CloudFormation – Nested Stacks and stacks parameters Import/Export
published: true
date: 2020-02-29 12:15:54 UTC
tags: AWS,tutorial,todayilearned
canonical_url: https://rtfm.co.ua/en/aws-cloudformation-nested-stacks-and-stacks-parameters-import-export/
---

![](https://rtfm.co.ua/wp-content/uploads/2014/11/aws-logo-square-02-e1417012834176-1.png)[Nested Stacks](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-nested-stacks.html) in AWS CloudFormation are stacks, created from another, a “parent”, stack using [`AWS::CloudFormation::Stack`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-stack.html).

The main idea behind the Nested Stacks is to avoid writing superfluous code and to make templates reusable.

Instead, a template is created only once, stored in an S3 bucket, and during stacks creation – you just refer to it.

For example, you can use the same template file to create two Load Balancers with different parameters and/or listeners using [Conditions](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/conditions-section-structure.html).

Documentation is available [here>>>](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-nested-stacks.html), and a good post is [here>>>](https://aws.amazon.com/ru/blogs/devops/use-nested-stacks-to-create-reusable-templates-and-support-role-specialization/).

In this post we will:

1. create a root stack – it will describe our other stacks, it will like a skeleton
2. will add another stack with a VPC as a child stack to the root stack
3. and one more child stack with AWS SecurityGroups

Also, our nested stack must be able to share their parameters between them to make it possible to use the same template for various environments – Dev/Stage/Prod.

In the end – we will take a brief overview of AWS CloudFormation parameters Import/Export feature between independent stacks.

Resulted templates are available on the [Github](https://github.com/setevoy2/setevoy-aws-templates/tree/master/nested-stacks-example).

### Pitfalls

1. do not delete nested stack manually – only via a “root” stack
2. use AWS S3 Versioning for templates

### The Root stack

Let’s start from writing a root stack’s template – `root-stack.json`:

```
{
  "AWSTemplateFormatVersion" : "2010-09-09",
  "Description" : "AWS CloudFormation Root stack",
  "Resources" : {
    "VPCStack": {
      "Type": "AWS::CloudFormation::Stack",
      "Properties": {
        "TemplateURL": "network-stack.yml"
      }
    }
  }
}
```

Here we are creating the only one resource – [`AWS::CloudFormation::Stack`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-stack.html) passing a child’s stack template file `network-stack.yml` via the root’s `Properties`.

In the `TemplateURL` will have to set an S3 bucket URL – will update it shortly.

Now, create the `network-stack.yml` file:

```
{
  "AWSTemplateFormatVersion" : "2010-09-09",
  "Description" : "AWS CloudFormation Nested Network Stack",
  "Resources" : {
    "VPC" : {
      "Type" : "AWS::EC2::VPC",
      "Properties" : {
        "CidrBlock" : "11.0.0.0/16"
      }
    }
  }
}
```

Create an S3 bucket to store our templates:

```
$ aws s3api create-bucket --bucket eks-cloudformation --region eu-west-3 --create-bucket-configuration LocationConstraint=eu-west-3 --profile arseniy --region eu-west-3
{
  "Location": "http://eks-cloudformation.s3.amazonaws.com/"
}
```

Remember the _«Location»: «http://eks-cloudformation.s3.amazonaws.com/»_ – will need it now.

For such a bucket will be a really good idea to enable versioning.

Enable it:

```
$ aws --region eu-west-3 --profile arseniy s3api put-bucket-versioning --bucket bttrm-eks-cloudformation --versioning-configuration Status=Enabled
```

Upload your  `network-stack.yml` to the bucket:

```
$ aws --profile arseniy --region eu-west-3 s3 cp network-stack.yml s3://bttrm-eks-cloudformationnn
upload: ./network-stack.yml to s3://bttrm-eks-cloudformation/network-stack.yml
```

Go back to the `root-stack.json`, update its `TemplateURL` – now set it as an URL to the bucket:

```
{
  "AWSTemplateFormatVersion" : "2010-09-09",
  "Description" : "AWS CloudFormation Root stack",
  "Resources" : {
    "VPCStack": {
      "Type": "AWS::CloudFormation::Stack",
      "Properties": {
        "TemplateURL": "https://bttrm-eks-cloudformation.s3.amazonaws.com/network-stack.yml"
      }
    }
  }
}
```

Create the root stack:

```
$ aws cloudformation create-stack --stack-name nested-stacks-root --template-body file://root-stack.json --profile arseniy --region eu-west-3
{
  "StackId": "arn:aws:cloudformation:eu-west-3:534****385:stack/nested-stacks-root/6450c320-57ab-11ea-be30-0a9cc8c39c1c"
}
```

Check it:

[![](https://rtfm.co.ua/wp-content/uploads/2020/02/Screenshot_20200225_104916.png "AWS: CloudFormation - вложенные стеки и Import/export параметров")](https://rtfm.co.ua/wp-content/uploads/2020/02/Screenshot_20200225_104916.png)

CloudFormation created a _nested-stacks-root_ stack and its child stack named _nested-stacks-root-VPCStack-1FTY8TI2PR2D2_ with VPC, as described in the `network-stack.yml` template:

[![](https://rtfm.co.ua/wp-content/uploads/2020/02/Screenshot_20200225_105004.png "AWS: CloudFormation - вложенные стеки и Import/export параметров")](https://rtfm.co.ua/wp-content/uploads/2020/02/Screenshot_20200225_105004.png)

#### AWS CloudFormation package && deploy

To avoid uploading templates manually we can use AWS CLI CloudFormation [`package`](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/package.html) and [`deploy`](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/deploy/index.html) options.

#### `package`

`package` will copy specified files or a whole directory in an S3 bucket.

Update your `root-stack.json` — replace the `TemplateURL` of the `VPCStack` Resouce to a local path – full or relative to the root stack’s file:

```
{
  "AWSTemplateFormatVersion" : "2010-09-09",
  "Description" : "AWS CloudFormation Root stack",
  "Resources" : {
    "VPCStack": {
      "Type": "AWS::CloudFormation::Stack",
      "Properties": {
        "TemplateURL": "network-stack.yml"
      }
    }
  }
}
```

Pack templates and upload them to the S3:

```
$ aws cloudformation package --template-file root-stack.json --output-template packed-nested-stacks.json --s3-bucket bttrm-eks-cloudformation --profile arseniy --region eu-west-3 --use-json

Uploading to ce12898553365980827b9aa59a99426d.template  187 / 187.0  (100.00%)

Successfully packaged artifacts and wrote output template to file packed-nested-stacks.json.

Execute the following command to deploy the packaged template

aws cloudformation deploy --template-file /home/setevoy/Work/devops/projects/EKS/roles/cloudformation/files/packed-nested-stacks.json --stack-name <YOUR STACK NAME>
```

Here:

1. CLI uploads all files (artifacts)  found in the `root-stack.json` to the AWS S3
2. will update `TemplateURL` to set the S3 URL instead of the local paths
3. will return a newly generated template which can be used with the `deploy` option

The template returned by the `package` will be saved in the `packed-nested-stacks.json` (I’m using the `--use-json` as by default YAML will be used, check the [What is: YAML – its overview, basic data types, YAML vs JSON, and PyYAML](https://rtfm.co.ua/en/what-is-yaml-its-overview-basic-data-types-yaml-vs-json-and-pyyaml/) post).

Check its content:

```
{
    "AWSTemplateFormatVersion": "2010-09-09",
    "Description": "AWS CloudFormation Root stack",
    "Resources": {
        "VPCStack": {
            "Type": "AWS::CloudFormation::Stack",
            "Properties": {
                "TemplateURL": "https://s3.eu-west-3.amazonaws.com/eks-cloudformation/ce12898553365980827b9aa59a99426d.template"
            }
        }
    }
}
```

And let’s see the _https://s3.eu-west-3.amazonaws.com/eks-cloudformation/ce12898553365980827b9aa59a99426d.template_ file content:

```
$ aws --profile arseniy --region eu-west-3 s3 cp --quiet s3://eks-cloudformation/ce12898553365980827b9aa59a99426d.template /dev/stdout

AWSTemplateFormatVersion: '2010-09-09'
Description: AWS CloudFormation Nested Network Stack
Resources:
  VPC:
  Type: AWS::EC2::VPC
  Properties:
    CidrBlock: 11.0.0.0/16
```

#### `deploy`

After we performed the `package` command – CLI displayed a tip about the following step:


```
...
Execute the following command to deploy the packaged template

aws cloudformation deploy --template-file /home/setevoy/Work/devops/projects/EKS/roles/cloudformation/files/packed-nested-stacks.json --stack-name <YOUR STACK NAME>
```

Apply it to the stack created a few steps ago:

```
$ aws --profile arseniy --region eu-west-3 cloudformation deploy --template-file packed-nested-stacks.json --stack-name nested-stacks-root
Waiting for changeset to be created..
Waiting for stack create/update to complete
Successfully created/updated stack - nested-stacks-root
```

`deploy` created a [ChangeSet](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks-changesets.html) and applied it to the root stack:

[![](https://rtfm.co.ua/wp-content/uploads/2020/02/Screenshot_20200225_110456.png "AWS: CloudFormation - вложенные стеки и Import/export параметров")](https://rtfm.co.ua/wp-content/uploads/2020/02/Screenshot_20200225_110456.png)

### Nested stack – passing parameters

At this moment we have no any Parameters in the templates.

For example, in the root stack, we can set some global values.

Let’s add a VPC’s CIDR, which will be used by the network-stack then.

Update the `root-stack.json` and add the `Parameters` block with one parameter `VPCCIDRBlock` and its default value:

```
{
  "AWSTemplateFormatVersion" : "2010-09-09",
  "Description" : "AWS CloudFormation Root stack",
  "Parameters": {
    "VPCCIDRBlock": {
      "Description": "VPC CidrBlock",
      "Type": "String",
      "Default": "11.0.0.0/16"
    }
  },  
...
```

In the `Resources` block for the `VPCStack` resource add `Parameters` section with `VPCCIDRBlock` parameter where we will pass our `VPCCIDRBlock` value from the “global” parameters:

```
{
  "AWSTemplateFormatVersion" : "2010-09-09",
  "Description" : "AWS CloudFormation Root stack",
  "Parameters": {
    "VPCCIDRBlock": {
      "Description": "VPC CidrBlock",
      "Type": "String",
      "Default": "11.0.0.0/16"
    }
  },
  "Resources" : {
    "VPCStack": {
      "Type": "AWS::CloudFormation::Stack",
      "Properties": {
        "TemplateURL": "network-stack.yml",
        "Parameters": {
          "VPCCIDRBlock" : { "Ref": "VPCCIDRBlock" }
        }
      }
    }
  }
}
```

In the `network-stack.yml` template add it to the VPC resource:

```
{
  "AWSTemplateFormatVersion" : "2010-09-09",
  "Description" : "AWS CloudFormation Nested Network Stack",
  "Parameters": {
    "VPCCIDRBlock": {
      "Description": "VPC CidrBlock",
      "Type": "String"
    }
  },
  "Resources" : {
    "VPC" : {
      "Type" : "AWS::EC2::VPC",
      "Properties" : {
        "CidrBlock" : { "Ref": "VPCCIDRBlock" }
      }
    }
  }
}
```

Pack it to the S3:

```
$ !518
aws cloudformation package --template-file root-stack.json --output-template packed-nested-stacks.json --s3-bucket bttrm-eks-cloudformation --profile arseniy --region eu-west-3 --use-json
```

Deploy:

```
$ aws --profile arseniy --region eu-west-3 cloudformation deploy --template-file packed-nested-stacks.json --stack-name nested-stacks-root --profile arseniy --region eu-west-3 --use-json
```

Check the nested stack’s `Parameters`:

[![](https://rtfm.co.ua/wp-content/uploads/2020/02/Screenshot_20200225_111719.png "AWS: CloudFormation - вложенные стеки и Import/export параметров")](https://rtfm.co.ua/wp-content/uploads/2020/02/Screenshot_20200225_111719.png)

`VPCCIDRBlock` was added.

### Nested stack Outputs

Also, Nested Stack allows using other stacks `Outputs` via the [`Fn::GetAtt`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-getatt.html) function.

Let’s add a third stack named _SecurityGroupStack_ where our SecurityGroup will be described.

We will pass the VPC ID to this SecurotyGroup using `Outputs` of the `network-stack.yml` stack.

Remember, that such parameters can be passed only from the “bottom” to “top” and back.

I.e. you can not pass a parameter directly from the _VPCStack_ to the _SecurityGroupStack_, but you can return a value to the root stack and then use it as a parameter for a child stack.

To do so:

1. in the _VPCStack_ (`network-stack.yml`) stack we will add `Outputs` to return  an ID of the VPC crated
2. in the root stack `root-stack.json` we will describe a new stack with the _SecurityGroupStack_ name, which `Parameters` will accept a vlue from the _VPCStack_ `Outputs` (`network-stack.yml`)
3. will create a new stack _SecurityGroupStack_, which template will use `Parameters` > `VPCID`

#### `network-stack.yml` Stack Outputs

Add output for the VPC:

```
...
  "Resources" : {
    "VPC" : {
      "Type" : "AWS::EC2::VPC",
      "Properties" : {
        "CidrBlock" : { "Ref": "VPCCIDRBlock" }
      }
    }
  },
  "Outputs" : {
    "VPCID" : {
      "Description" : "EKS VPC ID",
      "Value" : { "Ref" : "VPC" }
    }
  }
}
```

#### `root-stack.json` Stack

In the root stack add a new stack _SecurityGroupStack_ and add the  `VPCID` from the `Outputs` of the _VPCStack_ stack to  `Parameters` of the _SecurityGroupStack_:

```
...
  "Resources" : {
    "VPCStack": {
      "Type": "AWS::CloudFormation::Stack",
      "Properties": {
        "TemplateURL": "network-stack.yml",
        "Parameters": {
          "VPCCIDRBlock" : { "Ref": "VPCCIDRBlock" }
        }
      }
    },
    "SecurityGroupStack": {
      "Type": "AWS::CloudFormation::Stack",
      "Properties": {
        "TemplateURL": "sg-stack.yml",
        "Parameters": {
          "VPCID" : { "Fn::GetAtt": ["VPCStack", "Outputs.VPCID"] }
        }
      }
    }
  }
...
```

Create a new template file for the SecurityGroups — `sg-stack.yml`:

```
{
  "AWSTemplateFormatVersion" : "2010-09-09",
  "Description" : "AWS CloudFormation SecurityGroups stack",
  "Parameters" : {
    "VPCID": {
      "Description": "Network Stack VPC ID",
      "Type": "String",
    }
  },
  "Resources" : {
    "SecurityGroup": {
      "Type": "AWS::EC2::SecurityGroup",
      "Properties" : {
        "GroupDescription" : "Example SecurityGroup",
        "VpcId"            : { "Ref": "VPCID" },
        "SecurityGroupIngress" : [
          {
            "Description": "Allow HTTP",
            "IpProtocol" : "tcp",
            "FromPort"   : 80,
            "ToPort"     : 80,
            "CidrIp"     : "0.0.0.0/0"
          },
          {
            "Description": "Allow HTTPS",
            "IpProtocol" : "tcp",
            "FromPort"   : 443,
            "ToPort"     : 443,
            "CidrIp"     : "0.0.0.0/0"
          }
        ]
      }
    },
  }
}
```

Here, in the `"VpcId" : { "Ref": "VPCID" }`, we are using a VPC ID value to add this SecirtyGroup to the same VPC.

Pack, deploy, check stacks:

[![](https://rtfm.co.ua/wp-content/uploads/2020/02/Screenshot_20200225_112817.png "AWS: CloudFormation - вложенные стеки и Import/export параметров")](https://rtfm.co.ua/wp-content/uploads/2020/02/Screenshot_20200225_112817.png)

A new stack was created.

Check its Parameters:

[![](https://rtfm.co.ua/wp-content/uploads/2020/02/Screenshot_20200225_112855.png "AWS: CloudFormation - вложенные стеки и Import/export параметров")](https://rtfm.co.ua/wp-content/uploads/2020/02/Screenshot_20200225_112855.png)

All good.

### Template reuse

As already mentioned at the beginning, the main idea is modularity, when we can use the same template file to create similar resources.

Let’s say, we’d like to have two VPC with a different CIDRs.

We can use CloudFormation `Mappins` and set two various network blocs there.

In the root template `root-stack.json` remove the `"Parameters": "VPCCIDRBlock"` and add `Mappings` instead:

```
{
  "AWSTemplateFormatVersion" : "2010-09-09",
  "Description" : "AWS CloudFormation Root stack",
  "Mappings": {
    "VPCCIDRBlock": {
      "vpc1": {
        "cidr": "11.0.0.0/16"
      },
      "vpc2": {
        "cidr": "12.0.0.0/16"
      }
    }
  },
...
```

In the `Resources` add another stack with a VPC using the same template file, but now in its `Parameters` use the `Fn::FindInMap` function to get a value for the `Property VPCCIDRBlock`:

```
...
  "Resources" : {
    "VPCStack1": {
      "Type": "AWS::CloudFormation::Stack",
      "Properties": {
        "TemplateURL": "network-stack.yml",
        "Parameters": {
          "VPCCIDRBlock" : { "Fn::FindInMap" : [ "VPCCIDRBlock", "vpc1", "cidr" ] }
        }
      }
    },
    "VPCStack2": {
      "Type": "AWS::CloudFormation::Stack",
      "Properties": {
        "TemplateURL": "network-stack.yml",
        "Parameters": {
          "VPCCIDRBlock" : { "Fn::FindInMap" : [ "VPCCIDRBlock", "vpc2", "cidr" ] }
        }
      }
    },
...
```

Do not forget about SecurityGroup – add another one – again, using the same SG’s template `sg-stack.yml`, and attach this second SecurityGroup to the second VPC:

```
...
    "SecurityGroupStack1": {
      "Type": "AWS::CloudFormation::Stack",
      "Properties": {
        "TemplateURL": "sg-stack.yml",
        "Parameters": {
          "VPCID" : { "Fn::GetAtt": ["VPCStack1", "Outputs.VPCID"] }
        }
      }
    },
    "SecurityGroupStack2": {
      "Type": "AWS::CloudFormation::Stack",
      "Properties": {
        "TemplateURL": "sg-stack.yml",
        "Parameters": {
          "VPCID" : { "Fn::GetAtt": ["VPCStack2", "Outputs.VPCID"] }
        }
      }
    }
...
```

Deploy, check:

[![](https://rtfm.co.ua/wp-content/uploads/2020/02/Screenshot_20200225_132126.png "AWS: CloudFormation - вложенные стеки и Import/export параметров")](https://rtfm.co.ua/wp-content/uploads/2020/02/Screenshot_20200225_132126.png)

CloudFormation removed the _VPCStack_ and instead created two new stacks – _VPCStack1_ и _VPCStack2_, and in the same way – for the _SecurityGroup_.

### Import/export values vs Nested Stacks

The `Outputs` in nested stacks is good to share parameters between affined stacks, but it will work only for current stacks “tree” and can not be shared with a not related stack in this AWS account.

Here we can use another AWS CLoudFormatiuon feature called [cross-stack reference](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/walkthrough-crossstackref.html) – in a first stack you’ll create an [`Export`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-stack-exports.html), and in an another – their [`Import`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-importvalue.html).

#### Pitfalls

- exported values are accessible within the same AWS region only
- you can’t delete a stack if it importing values used by any other stack

Add an Export for the ID of the SecurityGroups crated to make it available to use later in other, independent, stacks.

To do so, update the SecurityGroup `sg-stack.yml` template and add its ID to the `Outputs`:

```
...
            "ToPort"     : 443,
            "CidrIp"     : "0.0.0.0/0"
          }
        ]
      }
    },
  },
  "Outputs" : {
    "SecurityGroupID" : {
      "Description" : "The SecurityGroup ID",
      "Value" :  { "Ref" : "SecurityGroup" }
    }
  }
}
```

In the root template – update its `Outputs` and add the `Export` for both _SecurityGroupStack_-stacks:

```
...
  "Outputs" : {
    "SecurityGroup1" : {
      "Description" : "The SecurityGroup-1 ID",
      "Value" :  { "Fn::GetAtt": [ "SecurityGroupStack1", "Outputs.SecurityGroupID" ] },
      "Export": { "Name": { "Fn::Sub": "${AWS::StackName}-SecurityGroupStack1" } }
    },
    "SecurityGroup2" : {
      "Description" : "The SecurityGroup-2 ID",
      "Value" :  { "Fn::GetAtt": [ "SecurityGroupStack2", "Outputs.SecurityGroupID" ] },
      "Export": { "Name": { "Fn::Sub": "${AWS::StackName}-SecurityGroupStack2" } }
    }
  }
}
```

Here:

- in the `Value` we are getting a SecurityGroup ID from its `Outputs`
- in the `Export: Name` with the [`Fn::Sub`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-sub.html) we are generating an uniq name.

Deploy, check the _SecurityGroup_‘s stack `Outputs`:

[![](https://rtfm.co.ua/wp-content/uploads/2020/02/Screenshot_20200225_152230.png "AWS: CloudFormation - вложенные стеки и Import/export параметров")](https://rtfm.co.ua/wp-content/uploads/2020/02/Screenshot_20200225_152230.png)

And `Outputs` of the root stack – find the Exported values:

[![](https://rtfm.co.ua/wp-content/uploads/2020/02/Screenshot_20200225_152315.png "AWS: CloudFormation - вложенные стеки и Import/export параметров")](https://rtfm.co.ua/wp-content/uploads/2020/02/Screenshot_20200225_152315.png)

Also, they are available now in the Exports of the whole CloudFormation for this account:

[![](https://rtfm.co.ua/wp-content/uploads/2020/02/Screenshot_20200225_152406.png "AWS: CloudFormation - вложенные стеки и Import/export параметров")](https://rtfm.co.ua/wp-content/uploads/2020/02/Screenshot_20200225_152406.png)

Now, we can use it for other stacks.

To check it, let’s add a stack with the only VPC resource (just because a CloudFormation stack has to have at least one Resource type), and in its `Outputs` using [`Fn::ImportValue`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-importvalue.html) we will display SecurityGroups IDs from the _nested-stacks-root_ stack:

```
{
  "AWSTemplateFormatVersion" : "2010-09-09",
  "Description" : "AWS CloudFormation Nested Network stack",
  "Parameters": {
    "VPCCIDRBlock": {
      "Description": "VPC CidrBlock",
      "Type": "String",
      "Default": "13.0.0.0/16"
    }
  },
  "Resources" : {
    "VPC" : {
      "Type" : "AWS::EC2::VPC",
      "Properties" : {
        "CidrBlock" : { "Ref": "VPCCIDRBlock" }
      }
    }
  },
  "Outputs" : {
    "SecurityGroup1ID" : {
      "Description" : "The SecurityGroup ID",
      "Value" :  { "Fn::ImportValue" : "nested-stacks-root-SecurityGroupStack1" }
    },
    "SecurityGroup2ID" : {
      "Description" : "The SecurityGroup ID",
      "Value" :  { "Fn::ImportValue" : "nested-stacks-root-SecurityGroupStack2" }
    }
  }
}
```

Deploy it (better was to call the new stack like an “_independent-_” or “_external-_” instead of the _nested-_), and check its `Outputs`:

[![](https://rtfm.co.ua/wp-content/uploads/2020/02/Screenshot_20200228_093808.png "AWS: CloudFormation - вложенные стеки и Import/export параметров")](https://rtfm.co.ua/wp-content/uploads/2020/02/Screenshot_20200228_093808.png)

Done.

### Useful links

- [Working with Nested Stacks](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-nested-stacks.html)
- [AWS CloudFormation Best Practices](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/best-practices.html#nested)
- [CloudFormation Nested Stacks Primer](https://www.trek10.com/blog/cloudformation-nested-stacks-primer/)
- [Walkthrough with Nested CloudFormation Stacks](https://medium.com/@janethavishka/walkthrough-with-nested-cloudformation-stacks-d7709b568162)
- [Understanding Nested CloudFormation Stacks](https://cloudacademy.com/blog/understanding-nested-cloudformation-stacks/)
- [Use Nested Stacks to Create Reusable Templates and Support Role Specialization](https://aws.amazon.com/ru/blogs/devops/use-nested-stacks-to-create-reusable-templates-and-support-role-specialization/)
- [CloudFormation Best-Practices](https://sbstjn.com/cloudformation.html#nested-stacks)
- [CloudFormation package & deploy](https://aws.nz/best-practice/cloudformation-package-deploy/)
- [7 Awesome CloudFormation Hacks](https://garbe.io/blog/2017/07/17/cloudformation-hacks/)
- [Using CloudFormation Cross-Stack References](https://www.1strategy.com/blog/2017/03/14/using-cloudformation-cross-stack-references/)
- [How can I reference a resource in another stack from an AWS CloudFormation template?](https://aws.amazon.com/ru/premiumsupport/knowledge-center/cloudformation-reference-resource/)
- [How do I use multiple values for individual parameters in an AWS CloudFormation template?](https://aws.amazon.com/ru/premiumsupport/knowledge-center/multiple-values-list-parameter-cli/)
- [How do I pass CommaDelimitedList parameters to nested stacks in AWS CloudFormation?](https://aws.amazon.com/ru/premiumsupport/knowledge-center/cloudformation-parameters-nested-stacks/)
- [Two years with CloudFormation: lessons learned](https://sanderknape.com/2018/08/two-years-with-cloudformation-lessons-learned/)

### Similar posts

- <small>10/18/2019</small> [AWS: Redshift – quick start and SQL-workbench connection config](https://rtfm.co.ua/en/aws-redshift-quick-start-and-sql-workbench-connection-config/)>  
- <small>03/07/2018</small> [AWS: CloudFormation – пример создания S3 корзины, IAM пользователя, Glacier Lifecycle и SNS Notification](https://rtfm.co.ua/aws-cloudformation-primer-sozdaniya-s3-korziny-iam-polzovatelya-glacier-lifecycle-i-sns-notification/)<small> (0)</small>  
- <small>02/01/2018</small> [BASH: скрипт создания AWS CloudFormation стека](https://rtfm.co.ua/bash-skript-sozdaniya-aws-cloudformation-steka/)  
- <small>11/27/2018</small> [AWS: CloudFormation – S3 корзина для логов Application Load Balancer](https://rtfm.co.ua/aws-cloudformation-s3-korzina-dlya-logov-application-load-balancer/) 
- <small>09/06/2018</small> [AWS: CloudFormation – ‘templateBody’ failed to satisfy constraint: Member must have length less than or equal to 51200](https://rtfm.co.ua/aws-cloudformation-templatebody-failed-to-satisfy-constraint-member-must-have-length-less-than-or-equal-to-51200/)