CloudFormation 更改集显示替换,尽管没有更改
CloudFormation Change Set Showing Replacement Despite no change
AWS::RDS::DBInstance 类型的资源已经部署。尽管我没有在模板中指定它,但数据库会自动使用标准端口 3306。这很好,符合预期。
但是,现在我想明确地指定模板中的端口号,通过添加that property:Port: "3306"
.
问题是,当我将其添加到模板时,CloudFormation 更改集告诉我这是一个将导致 替换 数据库的修改。这是更改集:
[
{
"resourceChange": {
"logicalResourceId": "RDSDBInstanceA",
"action": "Modify",
"physicalResourceId": "awesome-db",
"resourceType": "AWS::RDS::DBInstance",
"replacement": "True",
"moduleInfo": null,
"details": [
{
"target": {
"name": "Port",
"requiresRecreation": "Always",
"attribute": "Properties"
},
"causingEntity": null,
"evaluation": "Static",
"changeSource": "DirectModification"
}
],
"changeSetId": null,
"scope": [
"Properties"
]
},
"hookInvocationCount": null,
"type": "Resource"
}
]
预期行为
我希望 CloudFormation 会说:未检测到任何更改。因为数据库已经在使用3306端口,所以有效没有变化。
如果它已经在使用我想要的端口,为什么我要尝试解决这个问题?
这样我就可以为 Postgres 重新使用我的 MySQL 模板,有条件地将端口号更改为标准的 5432。奇怪的是,当我部署 Postgres 数据库时没有指定端口号,它使用了 3306 -- 这对我来说是个问题,因为我想要标准端口 5432。
我尝试过的事情:
- 当 MySQL 部署时,通过使用
AWS::NoValue
作为 Port
属性 的值来欺骗 CloudFormation 认为没有变化:
Port: !If [IsMySQL, AWS::NoValue, "5432"]
结果相同。
如果这是 Terraform...
它会检查状态,看到端口已经是 3306,然后说“没有变化”。
我的问题
如何在将 属性 添加到模板的同时避免替换数据库?
CloudFormation 不会查看已部署的资源来识别更改,它只是将当前部署的堆栈与新堆栈进行比较。因此,在这种情况下,您有一个堆栈,该堆栈以前不包含值,现在包含它,CF 将其视为更改。我有点惊讶 AWS::NoValue
选项不起作用。
解决这个问题的一个方法是利用堆栈导入。步骤将是这样的:
- 通过将当前 RDS 实例的
DeletionPolicy
设置为 RETAIN
来更新当前堆栈(如果尚未设置)。
- 更新当前堆栈,删除 RDS 实例。 RDS 实例仍然存在,但不再受 CF 控制。
- 将 RDS 添加回您的模板,按照您想要的方式进行配置,然后使用 CF 中的“将资源导入堆栈”选项。这应该允许您将 RDS 实例添加回您的堆栈,并按照您想要的方式进行配置。
请记住,当您将某些内容导入堆栈时,CF 只是假定模板中的配置与导入的资源相匹配。
AWS::RDS::DBInstance 类型的资源已经部署。尽管我没有在模板中指定它,但数据库会自动使用标准端口 3306。这很好,符合预期。
但是,现在我想明确地指定模板中的端口号,通过添加that property:Port: "3306"
.
问题是,当我将其添加到模板时,CloudFormation 更改集告诉我这是一个将导致 替换 数据库的修改。这是更改集:
[
{
"resourceChange": {
"logicalResourceId": "RDSDBInstanceA",
"action": "Modify",
"physicalResourceId": "awesome-db",
"resourceType": "AWS::RDS::DBInstance",
"replacement": "True",
"moduleInfo": null,
"details": [
{
"target": {
"name": "Port",
"requiresRecreation": "Always",
"attribute": "Properties"
},
"causingEntity": null,
"evaluation": "Static",
"changeSource": "DirectModification"
}
],
"changeSetId": null,
"scope": [
"Properties"
]
},
"hookInvocationCount": null,
"type": "Resource"
}
]
预期行为
我希望 CloudFormation 会说:未检测到任何更改。因为数据库已经在使用3306端口,所以有效没有变化。
如果它已经在使用我想要的端口,为什么我要尝试解决这个问题?
这样我就可以为 Postgres 重新使用我的 MySQL 模板,有条件地将端口号更改为标准的 5432。奇怪的是,当我部署 Postgres 数据库时没有指定端口号,它使用了 3306 -- 这对我来说是个问题,因为我想要标准端口 5432。
我尝试过的事情:
- 当 MySQL 部署时,通过使用
AWS::NoValue
作为Port
属性 的值来欺骗 CloudFormation 认为没有变化:
Port: !If [IsMySQL, AWS::NoValue, "5432"]
结果相同。
如果这是 Terraform...
它会检查状态,看到端口已经是 3306,然后说“没有变化”。
我的问题
如何在将 属性 添加到模板的同时避免替换数据库?
CloudFormation 不会查看已部署的资源来识别更改,它只是将当前部署的堆栈与新堆栈进行比较。因此,在这种情况下,您有一个堆栈,该堆栈以前不包含值,现在包含它,CF 将其视为更改。我有点惊讶 AWS::NoValue
选项不起作用。
解决这个问题的一个方法是利用堆栈导入。步骤将是这样的:
- 通过将当前 RDS 实例的
DeletionPolicy
设置为RETAIN
来更新当前堆栈(如果尚未设置)。 - 更新当前堆栈,删除 RDS 实例。 RDS 实例仍然存在,但不再受 CF 控制。
- 将 RDS 添加回您的模板,按照您想要的方式进行配置,然后使用 CF 中的“将资源导入堆栈”选项。这应该允许您将 RDS 实例添加回您的堆栈,并按照您想要的方式进行配置。
请记住,当您将某些内容导入堆栈时,CF 只是假定模板中的配置与导入的资源相匹配。