如何编写我的云结构更可重用而不是重命名资源

Posted

技术标签:

【中文标题】如何编写我的云结构更可重用而不是重命名资源【英文标题】:How to write my cloud formation more reusable instead of renaming resources 【发布时间】:2018-02-20 05:12:57 【问题描述】:

我是 cloudformation 的新手,我正在为我的项目的基础架构编写一些 cfn 代码。但是在我写代码的时候,有个问题一直困扰着我。假设我有以下资源要创建:

Resources: 
MyEC2Instance: 
  Type: "AWS::EC2::Instance"
  Properties: 
    ImageId: "ami-79fd7eee"
    KeyName: "testkey"
    BlockDeviceMappings: 
      - DeviceName: "/dev/sdm"
        Ebs: 
          VolumeType: "io1"
          Iops: "200"
          DeleteOnTermination: "false"
          VolumeSize: "20"
      - DeviceName: "/dev/sdk"
        NoDevice: 

如您所见,我正在创建一个名为 MyEC2Instance 的资源。现在假设我有另一个名为 stg 的环境,它与上面完全相同,因此一种简单的方法是使用具有不同堆栈名称的上述代码,但我被告知我需要重命名我的资源名称,如下所示:

Resources: 
MyEC2InstanceStg1: 
  Type: "AWS::EC2::Instance"
  Properties: 
    ImageId: "ami-79fd7eee"
    KeyName: "testkey"
    BlockDeviceMappings: 
      - DeviceName: "/dev/sdm"
        Ebs: 
          VolumeType: "io1"
          Iops: "200"
          DeleteOnTermination: "false"
          VolumeSize: "20"
      - DeviceName: "/dev/sdk"
        NoDevice: 

但对我来说,这看起来并不专业,因为如果我有 10 个环境,这是否意味着我需要复制我的代码 10 次并重命名资源。有没有更好的办法?

【问题讨论】:

Is there a way to parameterize cloud formation resource names?的可能重复 @Kannaiyan 谢谢,但我认为这不会完全涵盖这个问题,因为它没有提到我们是否使用 name 属性,那么如果我们使用相同的逻辑资源名称更新资源会发生什么?映射是否仍然正确进行? 不同环境是否拥有相同的资源集,只是名称不同? @JamieStarke 我的担忧在于这部分:MyEC2InstanceStg1 如果我不更改此设置,映射 btw 资源和逻辑 ID 是否正确发生?专门针对更新的情况 在我的团队中,我们有一个 Dev、Staging 和 Production 设置,以及一个由所有三个共享的 CloudFormation 模板,并为每个模板创建单独的堆栈。所有逻辑 ID 都相同,但生成的物理 ID 不同。 【参考方案1】:

让我尝试扩大情况以更好地理解。就云部署而言,10 个资源不算什么。即使您设法为您的资源起一个很酷的唯一名称,但在尝试管理这些大量资源时也无济于事。

此外,逻辑名称很敏感,并且受字符和长度的限制,因此您很快就会发现无法正确命名它们来满足您的需要。当您使用少量资源时,这种方式是有意义的,但在适当的时候,资源往往会扩大,因为这样做很容易。

正如@jamie-starke 建议的那样,您需要找到其他方法来帮助您跟踪这些资源。在我的团队中,我们使用很多模板参数来驱动堆栈应该做什么。这就是我们试图帮助跟踪资源的方式,只要值是正确的。这很重要,因为我们最近不得不重命名标签值以确保在搜索期间没有重叠。例如,我们有像 Fe-MultiFEMulti-BESingleFEMulti-BESingle-BEMulti 这样的名称。当搜索FE-Multi 时,所有三个值都被命中,因为控制台执行了StartsWith 条件过滤。

如果可能的话,使用例如为资源建立一个名称。 !Sub "$AWS::StackName-SlackBotLambda"!Join 或其他等效词。 如果可能,我们会使用标签对资源进行注释,同时始终提供名称标签。

我们以有助于模板更具可读性的方式命名模板中的资源。通常一些逻辑名称会出现在 aws 控制台中,因为它们不接受名称或标签,这是我们目前接受的。对于其余的资源,名称大多是装饰性的。资源名称也很敏感,并且受限于字符和长度,因此它们无法表达。出于这个原因,我们选择主要通过标签来管理资源。标签没有限制,它们提供了一种用于查询的隐式语言。

了解 CloudFormation 模板有点笨拙,并且最终它们依赖于其余的 AWS 资源,因此需要复制和试验一些代码片段,尤其是在使用条件时。如果您需要有关此过程的更多信息,请告诉我。

因为我们不想将标签分配复制到每个资源,所以我们确保在堆栈创建期间提供正确的标签。为避免任何错误,我们不希望人们从控制台初始化堆栈,而只能从完全控制重要内容的 PowerShell 脚本初始化。

【讨论】:

非常感谢您的回答【参考方案2】:

我的团队处理此问题的方式是我们有一个共享模板,用于为我们的每个环境生成堆栈:devstagingproduction。每个环境之间的逻辑 ID 将相同,但生成的物理 ID 将不同。

对此有一点需要注意的是,如果您在同一个帐户中有不同的环境堆栈,则必须确保任何 Name 属性都是唯一的。如果不需要,请不要设置它们,CloudFormation 将为您生成它们。在需要它们的情况下,我发现 "Fn::Sub": "$AWS::StackName-SomeName" 对此很有帮助,因为它使每个物理资源的名称都与其环境堆栈相关。例如,对于 CodeBuild,项目名称是必需的,因此我们执行以下操作:

Resources:
  Project:
    Type: AWS::CodeBuild::Project
    Properties:
      Name: !Sub "$AWS::StackName-SlackBotLambda"
      ...

因此,如果我在我的 dev 堆栈上,这会使 CodeBuild 项目名为 dev-SlackBotLambda

我们采用的另一种策略是传入一个EnvironmentName 参数,这样我们就可以拥有在一个环境而不是另一个环境上创建的资源。例如,我通常希望在 Dev 中创建构建工件,然后与 Staging 和 Production 共享,所以我有这样创建的存储桶:

Parameters:
  EnvironmentName:
    Type: String
    AllowedValues:
      - dev
      - staging
      - production

  Conditions:
    ShouldGenerateArtifactBucket: !Equals [!Ref EnvironemntName, dev]

  Resources:
    ArtifactBucket:
      Type: AWS::S3::Bucket
      Condition: ShouldGenerateArtifactBucket

只要您的堆栈名称足够独特,您甚至可以使用第一个策略和第二个策略来创建一个具有足够可预测名称的存储桶,以便一个堆栈可以从第一个引用存储桶工件。

【讨论】:

所以这意味着我可以为我的所有环境使用相同的代码,但是在每个资源的属性中我选择不同的名称以使其唯一?对吗? 正确。对于大多数服务,如果您不指定名称,则 CloudFormation 将根据堆栈为其分配一个名称,以及一个随机值。 非常感谢您的帮助

以上是关于如何编写我的云结构更可重用而不是重命名资源的主要内容,如果未能解决你的问题,请参考以下文章

重命名而不是删除资源?

Visual Studio 2010:如何重新映射 F2 以重命名文件而不是打开对象浏览器

如何使用 Typescript 而不是 Javascript 在解析服务器中编写云代码?

如何编写可重用的组件/模块?

React 让组件更可重用

重命名后如何检查火花列的相等性