如何在更新参数时强制更新 CloudFormation 堆栈?

How do I force a CloudFormation stack to update when the parameter is updated?

我是 运行 一个 AWS CloudFormation 堆栈,它接收一些参数并启动 EC2 实例以及其他 AWS 资源。这些参数被输入到 EC2 实例的用户数据中,并基于该参数对驻留在 EC2 实例上的 Web 应用程序进行动态更改。

UserData: 
      Fn::Base64: 
        Fn::Join: 
          - ""
          - 
            - "#!/bin/bash \n"
            - "sh website-conf/website_mysql_config.sh "
            - " -c \""
            - 
              Ref: "CompanyName"

如上例所示,CompanyName 是传递给 userdata 脚本的众多参数之一。问题是,当更新任何一个或多个参数时,CloudFormation 不会检测到,而是抛出此错误。

因此,为了更新堆栈,我必须编辑堆栈并对 ASG 进行更改,以便 CloudFormation 'sees' 更改并执行堆栈更新。

有没有办法在更新参数时强制CFN更新堆栈?

CloudFormation 不会更新堆栈,除非堆栈中已创建的资源属性发生变化

例如: 假设我有一个简单的模板来创建一个数据库,我需要在其中传递 2 个参数:

  1. 数据库名称
  2. 地区

假设我正在使用 db-name 将其作为值传递给 DBInstanceIdentifier

还假设我没有出于任何目的使用输入参数 region 来创建任何堆栈的资源(或其属性) way.It 更像是我保留的虚拟参数出于可读性目的。

我将 (TEST-DB1, us-east-1) 作为输入参数传递给 CloudFormation 模板并成功创建了资源。

Scenario-1: 现在,如果我更新堆栈(仍在使用现有模板)并将输入参数更改为 (TEST-DB2, us-east-1)。即:仅更改数据库名称而不更改区域。然后 CloudFormation 将检测到此参数更新导致堆栈 运行 资源的属性发生变化,并将计算并将修改显示为更改集。

Scenario-2: 假设我进行了另一个更新(仍然使用现有模板)属性 并将输入参数更改为 (TEST-DB1, us-east-2)。即:仅更改区域而不更改数据库名称。然后 CloudFormation 将检测到,此参数更新导致 运行 资源的属性没有变化 堆栈将显示 Error creating change set.

底线: 您对输入参数的更改必须导致堆栈的任何资源(或其属性,如安全组、端口等)update/replacement。然后 AWS CloudFormation 会将它们显示为 Change Sets 以供您查看。此外,AWS CloudFormation 使用的方法(更新或替换)取决于您为给定资源类型更新的属性。

Your parameter "CompanyName" is not making any changes to the running resources of the stack. Hence it is reporting as Error creating change set. You need to use it to create any resource/resource properties of the stack. Then CloudFormation will detect the change-sets when you modify it. The same applies for any other input-parameters which you use.

使用 AWS CLI Update-Stack 命令。如果您使用 AWS CLI,您可以将参数注入堆栈,这样对任何参数的任何更改都会产生一个新堆栈。我自己这样做是为了将 Git/version 提交 ID 注入到 UserData 中,因此只需将堆栈的 JSON/Yaml 更改提交到 Git 即可允许堆栈更新。对参数文件的任何更改都将允许堆栈更新,即使只是注释。我在 UserData 中引用我的 Git 提交 ID 的方式与您引用 Ref:CompanyName 的方式相同,因此当我更改 Git 提交 ID 时,userData 部分会在堆栈更新时更新。

更新堆栈命令

aws cloudformation update-stack --stack-name MyStack --template-body file:///Users/Documents/Git/project/cloudformation/stack.json --parameters file:///Users/Documents/Git/project/cloudformation/parameters/stack-parameters.dev.json --capabilities CAPABILITY_IAM

进程

通过这种方法,您可以将参数更改为参数 json 或 yaml 文件,然后将其签入版本控制。现在,如果您使用构建服务器,您可以通过检查 master 和上面的 运行 一行来更新您的堆栈。使用 AWS CodeBuild 让这一切变得简单,因此您不需要 jenkins。

您的问题的答案已在此状态下得到解答,除非堆栈中已创建的资源的属性发生更改,否则 CloudFormation 不会更新堆栈。

关于您问题的答案,请查看下面的解释。

有一种方法可以强制 Cloudformation 使用 AWS::CloudFormation::Init 更新堆栈。 通过使用 cfn-init,每个实例都可以在检测到 AWS::CloudFormation::Init 在元数据中所做的更改时自行更新。

有一个概念我们首先要明白,那就是UserData和metadata的区别,至少在AWS::CloudFormation::Init情况下是这样。

  • Userdata:只会在实例第一次启动时调用一次(包括需要更换实例的更新)。所以,如果你更新堆栈(而不是创建一个新的),即使你改变了参数值,如果你调用UserData.
  • 下的参数,它也不会改变任何东西
  • Metadata:随时更新。要使其正常工作,您必须确保检测元数据更改的守护进程是 运行(该守护进程称为 cfn-hup)

如果您已经使用了 MetadataAWS::CloudFormation::Init,则不会立即更新数据。据我所知,这是更改 Metadata 值后要更改数据的条件。

  • 重启实例
  • 运行 cfn-init 再次使用参数
  • 命令
  • 等待大约 15 分钟,因为 Metadata 中检查更改的守护程序每 15 分钟检查一次更改。