CloudFormation跨栈和嵌套栈

18

我面临一个决策,是要按照AWS CloudFormation最佳实践使用跨栈引用导出共享资源还是使用嵌套堆栈重复使用常见模板样式

然而,它们对我来说似乎是相同的,除了一些差异:

  • 跨栈使用Fn::ImportValue,模板在一个文件夹中。
  • 嵌套堆栈必须在S3中,使用类型为AWS::CloudFormation::StackTemplateURL

就我所知,它们之间没有明显的优缺点。

我的目标是创建一个父栈,将一些核心变量(如stackName)传递给子栈,然后子栈使用这些变量来共享资源(如ARNPolicies),并使用stackName来命名它们的资源,例如stackNameDynamoDBTable

4个回答

10

您应该使用跨栈引用,因为它是专门为在堆栈之间传递信息而创建的。

而嵌套堆栈可以工作,但其主要目的是为了重用模块化组件,例如资源模板,您可以在许多堆栈中使用它来节省复制粘贴和独立更新堆栈的时间。


2
我很难相信嵌套堆栈与重用有关。CloudFormation尽其所能使模块化变得困难,包括嵌套堆栈表现为运行时资源而不仅仅是作为包含/导入机制。跨堆栈和嵌套堆栈的唯一标准是您是否想要一次性部署所有内容还是单独部署,但即使如此,这也很令人沮丧,因为有时您希望能够同时执行两者,而目前没有好的CloudFormation解决方案。 - weberc2
1
这是一个非常好的问题,因为我也遇到了类似的问题,但使用嵌套堆栈的价值在于可以将堆栈模块化,以使其保持在文件大小限制以下,但将作为一个完整的堆栈进行处理。至少这就是我从这次讨论中得出的结论。 - Louis Preston Thornton III

3

嵌套栈:如果您需要从单一点管理堆栈,您应该使用嵌套堆栈。 示例:假设您具有负载均衡器配置可在大多数堆栈中使用。 您可以创建一个专用模板来处理负载均衡器,而不是将相同的配置复制并粘贴到模板中。

跨堆栈:或者,如果您需要将堆栈作为单独的实体进行管理,则应使用跨堆栈引用。(AWS限制您在AWS地区创建的VPC数量最多为五个。) 示例:您可能拥有包含VPC、安全组和子网的网络堆栈。 您希望所有公共Web应用程序都使用这些资源。 通过导出资源,您允许所有具有公共Web应用程序的堆栈使用它们。


1

使用交叉堆栈时,当您希望A和B重用这些现有组件X时,您将引用一堆现有组件X并传递给堆栈A和B。而在嵌套堆栈中,当您将嵌套堆栈Y嵌套在堆栈C和D中时,Y将为C和D分别创建描述的一组新组件

这类似于编程中的“按引用传递”和“按值传递”的概念。


1
有一种方法可以兼顾两者的优势。诀窍是使用交叉堆栈资源共享,但使其依赖于使用嵌套堆栈传递的参数。
以下是我如何使用此方法的示例,请考虑两个堆栈IAMRoleStack和ComputeStack。前者包含所有必要的IAM角色,而后者包含一堆Lambda函数,这些角色应用于这些函数。
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}

正如您所见,我已经导出了IAM角色,但它的Name取决于一旦部署堆栈就计算出的堆栈名称。您可以在文档中阅读有关导出输出的更多信息。
ComputeStack中,我通过导入该角色来使用它。
Resources:
  LambdaForCompute:
    Type: AWS::Lambda::Function
    Properties:
      Role: !ImportValue
        Fn::Sub: ${StackNameOfIAMRole}-IAMRoleArnForLambda

“嵌套”了ComputeStackIAMRoleStack的父堆栈,协调传递堆栈名称参数。
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

我不能证明这是最佳实践,但这种风格使我能够选择在哪里进行编排部署,在哪里进行单独的部署。
我还想指出,基于资源类型的这种模块化对于嵌套堆栈来说并不是很可行。例如,在这种情况下,如果我有10个不同角色的10个不同Lambda函数,我将不得不通过参数传递这10个角色中的每一个。使用这种混合风格,我只需要传递一个参数——堆栈名称。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接