Table of contents
Welcome back to the IAC and CloudFormation Series; this will be the last article for the series.
As our CloudFormation Template increases based on the defined infrastructure, there is a need for a strategy to manage this complexity effectively and to break down the architecture into smaller, more manageable components. AWS provides two powerful approaches for this: Nested Stacks and Cross-Stack References.
We also have the Layered Stack which is an approach to improving the organizational structure of our templates.
In this article, we'll delve into the concepts and explore how they can be leveraged to handle the complexity of your infrastructure in AWS CloudFormation. Let's dive in.
NESTED STACKS
Nested Stacks in AWS CloudFormation can be likened to custom functions in programming but with a unique twist. They serve as powerful tools for reducing repetition in your CloudFormation templates, just as functions in code help avoid redundancy.
In programming, functions allow us to group sections of code so that we don't have to rewrite them every time we need their functionality. Similarly, nested stacks enable us to modularize and manage different parts of our infrastructure within a single template or across multiple templates. So, think of nested stacks as your infrastructure's building blocks, where multiple nested stacks**(Child Stack)** collectively form a Parent/Root stack.
For example, consider a scenario where you need to create multiple EC2 instances, each requiring Systems Manager Session Manager access. Instead of duplicating and pasting the same IAM role configuration for every EC2 instance, you can create a dedicated template containing the IAM role configuration. This dedicated template becomes our CHILD STACK. Then, you can easily reference that template from within another template, which becomes our PARENT STACK.
To use nested stacks, two crucial components are required: the
TemplateURL
and theAWS::CloudFormation::Stack
.
TemplateURL
The TemplateURL is used in the Parent Stack to reference the Child Stack. It serves as the link between the Parent and Child Stacks, allowing the Parent Stack to incorporate the resources defined in the Child Stack seamlessly.
TemplateURL are usually URL links that could either be an S3 bucket link or HTTPS URLs but using S3 buckets for this purpose is a common and recommended practice in AWS CloudFormation.
AWS::CloudFormation::Stack
Specifying the above type in your template tells CloudFormation that the template will be using a nested stack which will be specified by the TemplateURL.
In essence, you're telling AWS CloudFormation, "Hey, I've got a specialized task to handle, and I'm going to rely on another template to do it. Get ready!" This specialized task is represented by what we call a nested stack, and its definition lies in the
TemplateURL
parameter.
LAYERED STACK
Imagine you have a complex application composed of multiple components, such as web servers, application servers, and databases. Managing all of these components in a single CloudFormation template can quickly become unwieldy and challenging to maintain. This is where the concept of layered stacks comes into play.
Layered stacks are like organizing your infrastructure into different layers or tiers, similar to how you might structure an application with different layers for presentation, logic, and data. Each layer represents a distinct level of your infrastructure.
This makes it easy to organize our infrastructure into different layers within a single CloudFormation Template.
CROSS-STACK REFERENCE
This allows the sharing of information between CloudFormation stacks, This is similar to Nested stacks. but unlike nested stacks which involve embedding the child stack into the parent stack. This child stack is wholly used by the parent stack and the parent stack can reference outputs from child stacks, and it's typically responsible for orchestrating the creation, update, and deletion of the child stacks. There's a clear hierarchy, with the parent stack being the top-level stack.
In contrast, cross-stack references allow for communication between stacks that are at the same level, and they don't imply a hierarchy. Stacks can reference outputs from other stacks without being directly related as parent or child stacks. This is useful for creating loosely coupled, reusable components and for breaking down complex infrastructure into manageable pieces.
Note: Their is no Parent-Child relationship between Cross Stack Reference because multiple stacks can communicate with each other all at the same time.
For example, we have two separate CloudFormation stacks: one for creating a VPC (Virtual Private Cloud) and another for deploying an EC2 instance into that VPC.
Stack 1: VPC Stack
AWSTemplateFormatVersion: '2010-09-09'
Description: AWS CloudFormation Stack for VPC
Resources:
MyVPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 10.0.0.0/16
Outputs:
VpcId:
Description: VPC ID
Value: !Ref MyVPC
- In this cloudformation template, the VPC ID is being exposed and outputted and can be used across multiple stacks.
Stack 2: EC2 Stack
AWSTemplateFormatVersion: '2010-09-09'
Description: AWS CloudFormation Stack for EC2 Instance
Parameters:
VpcId:
Type: String
Resources:
MyEC2Instance:
Type: AWS::EC2::Instance
Properties:
InstanceType: t2.micro
SecurityGroups:
- !Ref MySecurityGroup
SubnetId: !Ref MySubnet
MySecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Allow HTTP and SSH access
VpcId: !Ref VpcId
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: '22'
ToPort: '22'
CidrIp: 0.0.0.0/0
- IpProtocol: tcp
FromPort: '80'
ToPort: '80'
CidrIp: 0.0.0.0/0
MySubnet:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VpcId
CidrBlock: 10.0.0.0/24
- In the EC2 Stack, we're creating an EC2 instance, a security group, and a subnet. Notice the
Parameters
section, where we defineVpcId
as a parameter. This parameter will allow us to pass the VPC ID from the VPC Stack (Parent Stack) to the EC2 Stack (Child Stack) when we create the stacks.
THEIR DIFFERENCES
Nested Stacks | Layered Stacks | Cross Stack | |
Reference Scope | Within the same stack (parent and child stacks). The child stack is wholly embedded into the parent stack | Typically within a single stack; organization is more of a conceptual approach. | Across separate CloudFormation stacks. |
Purpose | Breaking down complex infrastructure into smaller, more manageable components. | Organizing infrastructure into distinct layers or tiers | Referencing values between different CloudFormation stacks. |
Resource Sharing | Sharing resources between a parent and child stack. | Promoting logical organization; no specific resource sharing. | Sharing values (like outputs) across stacks, promoting reusability. |
AWS Feature | Yes | No | Yes |
Resource Sharing | Sharing resources between a parent and child stack. | Promoting logical organization; no specific resource sharing. | Sharing values (like outputs) across stacks, promoting reusability. |
Ease of Use | Suitable for breaking down complex stacks but adds complexity. | Requires manual organization and naming conventions. | Straightforward for sharing values between stacks. |
In conclusion, it is important to understand these concepts when writing our CloudFormation template because they make our templates more reusable, readable, and efficient.