服务
关于
CloudProse博客
云原生

CloudFormation堆栈拆分和共享

在CloudFormation堆栈之间共享和管理资源
瑞安·布朗(Ryan Brown)Trek10
瑞安·斯科特·布朗 | 2019年9月20日

最终,您会发现模板太大,太笨拙或模板太多 分散的资源。以相同的方式将变量和函数分开 命名空间随着应用程序的增长而变化,您应该期待同样的事情 最终会发生在您的基础架构上。

发生这种情况时,通常最好开始将模板拆分为 服务式的线条。在服务中,还有与生命周期相关的其他内容 可能成为进一步分裂的良好界限的部门。通常堆栈可以 在网络和数据存储区,功能和事件源之间进行划分。

如果您有一个紧密绑定的系统,则嵌套堆栈非常有用。嵌套堆栈让 您需要几个相关的CloudFormation堆栈并将它们作为一个单元进行部署。对于 在多个服务之间共享事物,通常建议 部署基础系统(例如VPC或对等连接) 分别是因为它们具有不同的生命周期,并且不能很好地适应 single service.

不同的团队可以拥有这些堆栈,或者可能需要将它们分开才能 其他原因。对于这些功能上分开的堆栈,请避免嵌套,并参见 下面的“为多堆栈共享值”。

即使将堆栈分成嵌套堆栈,也要了解 共享大量输出时固有的复杂性。你要记住 从堆栈A获取输出并将其插入堆栈B中的江苏体彩,并 删除创建输出的项目将成为多步骤过程,因为 you'll need:

  1. 删除客户端堆栈中输出的用法
  2. 部署
  3. 删除输出本身(可以选择创建新替换)
  4. 部署

对于容器类型的资源(如安全组),此过程通常是一个问题。 通常,子堆栈在该组中具有一个实体,这会导致 清除该资源失败。有涉及此的解决方法 RetentionPolicy,但这意味着您需要添加要删除的流程 那些孤儿们最终。所有这些解决方法 无法让CFN完全清除已删除的资源,以便下一个堆栈可以移动 从旧资源到新资源。

共享多堆栈的价值

一旦确定了分配资源的正确位置,那就是 是时候决定如何处理您需要共享的价值了。最经常 这些是VPC子网,安全组,DynamoDB表或 负载均衡器的主机名。

分享价值的方式有很多,每种方式都提供了一种在 可变性,可重用性,隔离性和灵活性。

选项1:无所事事

与AWS的其他每个部分一样,最直接的策略是 一。根据需要将值复制并粘贴到单个堆栈江苏体彩中。 缺乏策略会带来任何手册的所有开销和错误 基于复制粘贴的过程。价值观过时,人们忘记了价值观在哪里 来源,提供商不知道其值在哪里使用。

当然,这不是最新技术!

选项2:输出和江苏体彩编排

此方法依赖于使用标准堆栈江苏体彩/输出并传输 通过更高级的编排系统(如Ansible)来确定值。此选项已添加 还可以让您跨堆栈开发有序依赖性的好处,或者 仅部署一部分堆栈并在检查点停止。

如果要为此目的使用CloudFormation,则可以使用子堆栈和 将子堆栈A的输出传递到子堆栈B的江苏体彩。

# parent.yml

Resources:
  SubstackA:
    Type: 'AWS::CloudFormation::Stack'
    Properties:
      TemplateURL: substacks/a.yml
  SubstackB:
    Type: 'AWS::CloudFormation::Stack'
    Properties:
      TemplateURL: substacks/b.yml
      Parameters:
        DataGoesHere: !GetAtt SubstackA.Outputs.MyDataStore

# substacks/a.yml
Resources:
  Bucket:
    Type: 'AWS::S3::Bucket'
Outputs:
  MyDataStore:
    Value: !Ref Bucket

# substacks/b.yml
Resources: {}
Parameters:
  DataGoesHere:
    Description: where to store the query output from the FrobKnobulator

The same thing is possible using Ansible's 云形成 module, with the 在堆栈部署之间暂停执行某事的可能性的增加 其他。对于CloudFormation父/子堆栈,当 创建子堆栈B也会导致子堆栈A的回滚。这个方法不是 一定是错误的,但这确实需要您能够回滚 严格在CloudFormation中进行部署。本示例使用 云形成 .

-  云形成 :
    stack_name: StackA
    state: present
    template: "files/substacks/a.yml"
  register: stack_a
- debug:
    msg: "Other tasks can go here, enabling more complex deploys"
-  云形成 :
    stack_name: StackB
    state: present
    template: "files/substacks/b.yml"
    template_parameters:
      DataGoesHere: '{{ stack_a.outputs.MyDataStore }}'
  register: stack_b

选项3:堆栈导出

Stack exports use a CloudFromation intrinsic called !ImportValue to use the 值,然后在您选择的任何堆栈中的任何位置添加导入。的 名称是区域范围的,如果没有这些名称,就无法在整个区域之间轻松复制 复制整个结构(基本上是所有堆栈)。

# parent.yml

Resources:
  SubstackA:
    Type: 'AWS::CloudFormation::Stack'
    Properties:
      TemplateURL: substacks/a.yml
  SubstackB:
    Type: 'AWS::CloudFormation::Stack'
    Properties:
      TemplateURL: substacks/b.yml

# substacks/a.yml
Resources:
  Bucket:
    Type: 'AWS::S3::Bucket'
Outputs:
  MyDataStore:
    Value: !Ref Bucket
    Export: MyDataStore

# substacks/b.yml
Resources:
  InsightVm:
    Type: AWS::IAM::ManagedPolicy
    Properties:
      ManagedPolicyName: SomethingS3Read
      Policies:
        PolicyDocument:
          Version: '2012-10-17'
          Statement:
          - Action:
            - s3:List*
            - s3:GetObject
            Resource:
              'Fn::Sub':
               - 'arn:aws:s3:::${TheBucketName}/*'
               - TheBucketName:
                   "Fn::ImportValue": MyDataStore
            Effect: Allow

出口的问题或特征是它们是不可变的。如果你出口东西 and it is used 任何地方 您无法可靠地更改该值或删除 它从堆栈中。该规则使堆叠出口变得僵化,因此对 在经常变化的环境中使用。

选项4:SSM江苏体彩存储

顾名思义,Systems Manager江苏体彩存储非常擅长存储 堆栈和所有其他方式的江苏体彩。在任何模板中,您都可以 设置一个新的SSM江苏体彩:

VPC1IDSSM:
  Type: AWS::SSM::Parameter
  Properties:
    Description: !Sub 'VPC ID from stack ${AWS::StackName}'
    Name: '/network/main/vpc-id'
    Type: String
    Value: !Ref VPC

然后,在任何其他模板中,将该值用作江苏体彩

Parameters:
  TargetVpc:
    Type: AWS::SSM::Parameter::Value<AWS::EC2::VPC::Id>
    Default: /network/main/vpc-id

这样,您就可以使用来自其他堆栈中的SSM江苏体彩 相同的区域,还可以选择从其他系统添加SSM江苏体彩 例如Ansible。仅使用江苏体彩的路径(不使用实际值) 不需要您实际进行值检索, 提供它们作为堆栈江苏体彩。缺点是,如果您有 SecureString 江苏体彩,您不能以这种方式使用它。

除了将江苏体彩存储值用作堆栈之外,还有其他方法可以共享江苏体彩存储值 江苏体彩。您可以使用 动态解析器 而是获取价值 从Secrets Manager或SSM江苏体彩存储(包括SecureString)中获取。这个 method uses a special {{reslove:ssm:/my/value:1}} syntax. Note the last field 您必须在其中指定版本。这意味着您可以像Stack Exports一样 在高度动态的环境中会遇到问题。如果值更改,则位置 您解决的地方还必须更改其版本以获取新的价值。

最重要的是,江苏体彩存储可让您在团队中进行讨论 关于命名的事情。这些命名很像自行车棚的颜色 惯例很少引起争议。

选择什么?

关于如何构建“基础结构即代码”,没有“一条正确的道路”。 每种方式都需要在集中管理之间进行权衡(通常由 CumuloNimbus团队)和可定制性。以相同的方式不同 组织通常对如何拆分服务有自己的约定 在各个存储库之间,每家商店都趋于达到平衡的目的。

还不确定吗?最灵活的启动方式是通过SSM江苏体彩存储。 江苏体彩可以在单独的堆栈中,而无需部署堆栈 一起。也可以将江苏体彩用于(或创建)除 CloudFormation,如果您团队的某些成员更喜欢Terraform,Ansible, or bash scripts.

作者
瑞安·布朗(Ryan Brown)Trek10
瑞安·斯科特·布朗