Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CloudFormation cross-stack vs nested-stack

I'm facing a decision to Use Cross-Stack References to Export Shared Resources or to Use Nested Stacks to Reuse Common Template Patterns following AWS CloudFormation best practices.

However, they seem the same to me apart from a few differences:

  • cross-stack uses Fn::ImportValue, templates are in one folder.
  • nested-stack must be in S3, uses type AWS::CloudFormation::Stack and TemplateURL.

There's no clear pros and cons between them as far as I could search.

My goal is to create a parent stack that passes some core variables like stackName to the child stacks, then the child stacks create the resources sharing some variables between them like ARN or Policies, using the stackName to name their resources like stackNameDynamoDBTable.

like image 675
Viet Avatar asked May 15 '19 20:05

Viet


People also ask

What is nested stack in CloudFormation?

Nested stacks are stacks created as part of other stacks. You create a nested stack within another stack by using the AWS::CloudFormation::Stack resource. As your infrastructure grows, common patterns can emerge in which you declare the same components in multiple templates.

What is the difference between stack and Stackset CloudFormation?

A stack set lets you create stacks in AWS accounts across AWS Regions by using a single AWS CloudFormation template. A stack instance refers to a stack in a target account within an AWS Region and is associated with only one stack set. For more information, see StackSets Concepts.

What is cross-stack in CloudFormation?

Cross-stack references let you use a layered or service-oriented architecture. Instead of including all resources in a single stack, you create related AWS resources in separate stacks; then you can refer to required resource outputs from other stacks.

Should I use nested stacks?

In addition to being more efficient, nested stacks make assigning ownership to stack resources easier. Because nested stacks are separate templates, you can have separate owners maintain each template.


3 Answers

You should use cross-stack references as it was created for your use case of passing between stacks.

Whereas nested stacks would work, it’s primary purpose is for reuse of modular components, like a template of a resource you use in lots of stacks to save copy pasting and updating the stacks independently.

like image 115
NHol Avatar answered Nov 07 '22 11:11

NHol


There is a way to get the best of both worlds. The trick is to use cross-stack resource sharing but make it depend on a parameter that is passed using Nested stack.

Here's an example from how I used this, consider two stacks IAMRoleStack and ComputeStack. The former contains all the necessary IAM roles and the latter contains a bunch of Lambda functions that those roles are applied to.

Resources:
  IAMCustomAdminRoleForLambda:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
      Policies:

Output:
  IAMRoleArnForLambda:
    Description: Returns the Amazon Resource Name for the newly created IAM Custom
      Role for Lambda function
    Value: !GetAtt 'IAMCustomAdminRoleForLambda.Arn'
    Export:
      Name: !Sub '${AWS::StackName}-IAMRoleArnForLambda'

  StackName:
    Description: Returns name of stack after deployment
    Value: !Sub ${AWS::StackName}

As you can see I've exported the IAM role but it's Name depends on the stack name that is calculated once the stack is deployed. You can read more about exporting outputs in the docs.

In the ComputeStack, I use this role by importing it.

Resources:
  LambdaForCompute:
    Type: AWS::Lambda::Function
    Properties:
      Role: !ImportValue
        Fn::Sub: ${StackNameOfIAMRole}-IAMRoleArnForLambda

The parent stack that "nests" both ComputeStack and IAMRoleStack orchestrates passing the stack name parameter.

Resources:

  IAMRoleStack:
    Type: AWS::CloudFormation::Stack
    Properties:
      TemplateURL: !Ref IAMRoleStackURL

  ComputeStack:
    Type: AWS::CloudFormation::Stack
    Properties:
      TemplateURL: !Ref ComputeStackURL
      Parameters:
        StackNameOfIAMRole: !GetAtt IAMRoleStack.Outputs.StackName

I can't attest to best practice but this style allows me to pick and choose where I want orchestrated deployment and where I want to do the deployments individually.

I also want to point out that this kind of modularization based on type of resources is not very feasible for nested stacks. For e.g. in this scenario, if I had 10 different roles for 10 different Lambda functions, I would have to pass each of those 10 roles through parameters. Using this hybrid style, I only need to pass one parameter the stack name.

like image 37
twitu Avatar answered Nov 07 '22 12:11

twitu


Nested stacks: if you need to manage your stacks from a single point, you should use nested stacks. example: assume that you have load balancer configuration that you use for most of your stacks. Instead of copying and pasting the same configurations into your templates you can create a dedicated template for load balancer.

cross-stack : Alternatively, if you need to manage your stacks as separate entities, you should use cross-stack references.(AWS limits the number of VPCs you can create in an AWS region to five.) example : You might have a network stack that includes a VPC, a security group, and a subnet. You want all public web apps to use these resources. By exporting the resources, you allow all stacks with public web applications to use them.

like image 26
rohith Avatar answered Nov 07 '22 13:11

rohith