Nested stacks are a great way to organize your CloudFormation. However, in order to reduce stress, lower cloud costs and improve time to market, you must modularize your templates.
Nesting highlights the importance and agility of modularized templates. Imagine having a nested stack that referenced the same template for three separate stack resources. If you changed one parameter across these three it would cause the configuration management to boot an entirely different application server with similar infrastructure.
Modularizing speeds up your infrastructure development tenfold and eliminates the copy and paste of CloudFormation. Modularizing templates is the first step in truly treating your Infrastructure as Code (IaC)!
Think of your templates as functions and your nested stack as mainly calling your functions and applying the parameters.
Nesting and CloudFormation Basics
CloudFormation is an AWS service and JSON template language that allows for programmatic creation of, and interaction with, AWS resources. The collection of one or more resources created by CloudFormation is called a stack. CloudFormation allows us to achieve IaC practices, a programmatic approach to describe, create, update and delete infrastructure.
CloudFormation templates have hard limits of 200 resources, 60 parameters, 100 mappings and 60 outputs. To build large networks (and keep your sanity) you’ll need to break up your templates to work within these limitations. This is especially important to note because VPC networks can become lengthy.
A CloudFormation nested stack is a stack containing one or more CloudFormation stacks as resources. Nesting your stacks allows you to break up your CloudFormation into logical pieces. It also allows you to map outputs to parameters between templates.
Nesting is very important when working with multiple stacks that interact and depend on each other. Nested stacks will recognize changes that affect child stacks and update their parameters accordingly.
CloudFormation workflow can be represented as in the following diagram:
A nested stack is a normal CloudFormation template that defines a resource of type AWS::CloudFormation::Stack. Order of operations still holds true in nested stacks. If a stack uses a depends on or a GetAtt of another stack resource, those resources will be created before the dependent. CloudFormation will sort the dependencies and boot in the most efficient way, parallelizing what it can.
Stack Resource documentation can be found here: AWS Stack Resource Documentation
The following is a depiction of a nested stack using the diagram above.
Breaking Up Your CloudFormation
Modularization is key for refactoring large, unwieldy templates. Find portions of your template that are common and repeated, and break them out into their own template.
Use parameters as your variable values.
Use conditions where applicable for Boolean logic, such as determining if an Auto Scaling group and coupled Elastic Load Balancer should span multiple availability zones.
Mappings are a good way to get longevity out of your parameters. For example, say you commonly use the same number for max and min instances in an Auto Scaling group dependent on the environment. Use the environment parameter as a key in your find in map function.
Outputs are very important in nesting your stacks. Outputs are the only section of a child template available to the nested template. Typically you want to only output information from the template about the living resources it returns such as Physical IDs, ARNs, IPs and URL Endpoints.
Accessing Your Outputs
The ability to map outputs to parameters between child stacks is a huge incentive to nest.
To access outputs from a stack resource you must use the intrinsic function Fn::GetAtt. Unlike most other GetAtt attributes, the stack resource has a namespace of ‘Outputs.’ followed by the OutputName. We see the namespace as a foreshadow that AWS will expand on these features in the future.
This example would return the output named ProdAppSubnetAz1 from your network stack and map it to a parameter named SubnetAz1 to an application stack using a parameter for a TemplateURL.
Each time you update the nested stack it will look for changes in all of its child stacks. An update to a child stack would occur if the template in S3 has changed or if a parameter value of that template has changed. Stacks will not be updated unless there is a change to the resources requested. Adding an output to a template will not create an update as the resources in that stack did not change. You should plan ahead and output everything you might need before you deploy.
Typically you’ll only update the nested stack. It’s worth noting that if an update rollback fails on a child stack, the nested stack will inherit the UPDATE_ROLLBACK_FAILED state. You cannot update from this state. You have two options: contact AWS support to request a manual change to the state or deletion of your nested stack.
Infrastructure as Code becomes a reality with nested stacks and modularized templates. Remember to keep your templates in version control. The sooner you start treating your infrastructure as a real project, the sooner you will reach a state of heightened awareness and architectural enlightenment.