gpt4 book ai didi

amazon-web-services - 如何将手动更改导入 Terraform 远程状态

转载 作者:行者123 更新时间:2023-12-04 00:14:02 25 4
gpt4 key购买 nike

我是 terraform 的新手 - 我在 s3 中创建了远程 tfstate,现在我的 AWS 基础设施中也进行了一些手动更改。我需要将这些手动更改导入 tfstate。

我对一些资源使用了导入命令,但对于一些资源,如 IAM 策略等,没有这样的导入命令。

此外,一些资源(例如 DB)随着添加的新参数而更改,我也需要导入它们。当我尝试导入这些更改时,它说:

Error importing: 1 error(s) occurred:

* Can't import aws_security_group.Q8SgProdAdminSshInt, would collide
with an existing resource.

Please remove or rename this resource before continuing.

任何帮助,将不胜感激。谢谢。

最佳答案

在直接回答这个问题之前,我认为一些上下文会有所帮助:

在幕后,Terraform 维护一个状态文件,其中包含从配置中的资源到底层提供程序 API 中的对象的映射。当您使用 Terraform 创建新对象时,创建的对象的 id 会自动保存在状态中,以便以后的命令可以定位引用的对象以进行读取、更新和删除操作。
terraform import ,然后,是在状态文件中创建条目的不同方式。不是创建一个新对象并记录它的 id,而是用户在命令行上提供一个 id。 Terraform 读取具有该 id 的对象并将结果添加到状态文件中,之后它在状态中与 Terraform 自己创建的资源无法区分。

综上所述,让我们一一解决您的问题。

导入不支持的资源 terraform import
由于每个资源都需要少量验证和数据获取代码来执行导入,因此此时并非所有资源都支持导入。

鉴于我们对什么的了解 terraform import从上面做起,理论上可以跳过 Terraform 对提供的 id 的验证,而是手动将资源添加到状态。 这是一项高级操作,必须小心完成以避免破坏状态 .

首先,将状态检索到您将用于本地工作的本地文件中:

terraform state pull >manual-import.tfstate

这将创建一个文件 manual-import.tfstate可以在文本编辑器中打开。它使用 JSON 语法,因此虽然它的内部结构没有记录为稳定格式,但只要我们与预期结构保持一致,我们就可以仔细编辑它。

最简单的方法是找到与您要导入和复制并编辑它的模块位于同一模块中的现有资源。假设我们有一个 resources像这样的对象:
"resources": {
"null_resource.foo": {
"type": "null_resource",
"depends_on": [],
"primary": {
"id": "5897853859325638329",
"attributes": {
"id": "5897853859325638329"
},
"meta": {},
"tainted": false
},
"deposed": [],
"provider": ""
}
},

resources 中的每个属性对象对应于您的配置中的资源。属性名称是资源的类型和名称。在本例中,资源类型为 null_resource并且属性名称是 foo .在您的情况下,您可能会看到类似 aws_instance.server 的内容。这里。
id对于许多资源(但不是全部!),属性是需要填充的主要内容。因此,我们可以为假设的 IAM 策略复制此结构:
"resources": {
"null_resource.foo": {
"type": "null_resource",
"depends_on": [],
"primary": {
"id": "5897853859325638329",
"attributes": {
"id": "5897853859325638329"
},
"meta": {},
"tainted": false
},
"deposed": [],
"provider": ""
},
"aws_iam_policy.example": {
"type": "aws_iam_policy",
"depends_on": [],
"primary": {
"id": "?????",
"attributes": {
"id": "?????"
},
"meta": {},
"tainted": false
},
"deposed": [],
"provider": ""
}
},

这一步的挑战是弄清楚这个资源需要什么样的 id。知道这一点的唯一可靠方法是 read the code ,这告诉我该资源期望 id 是策略的完整 ARN。

有了这些知识,我们替换了两个 ?????上面示例中的序列与我们要导入的策略的 ARN。

对状态进行手动更改后,有必要更新 serial文件顶层的编号。 Terraform 预计任何新的变化都会有一个更高的序列号,所以我们可以增加这个数字。

完成更新后,我们必须将更新后的状态文件上传回 Terraform:
terraform state push manual-import.tfstate

最后,我们可以要求 Terraform 刷新状态以确保其正常工作:
terraform refresh

同样,这是一个非常危险的过程,因为状态文件是 Terraform 与底层系统关系的记录,如果该文件的内容丢失,则很难恢复。简单地替换资源通常比进行所有这些工作更容易,除非它已经在您的基础架构中发挥着关键作用,并且没有可用的优雅迁移策略。

导入与现有资源冲突

您的问题中给出的错误消息是关于导入与现有资源“冲突”:
Error importing: 1 error(s) occurred:

* Can't import aws_security_group.Q8SgProdAdminSshInt, would collide with an existing resource.

Please remove or rename this resource before continuing.

此消息的含义是,当 Terraform 尝试将新资源写入状态文件时,它发现名称 aws_security_group.Q8SgProdAdminSshInt 的资源条目已经存在。 .这表明它已经被导入,或者 Terraform 本身已经创建了一个新的安全组。

您可以在 state 中检查现有资源的属性:
terraform state show aws_security_group.Q8SgProdAdminSshInt

将返回的数据与您尝试导入的安全组进行比较。如果 ids 匹配,那么就没有什么可做的了,因为资源已经被导入了。

如果 id 不匹配,那么您需要确定两个对象中的哪一个是您想要保留的对象。如果您想保留 Terraform 已有的那个,您可以手动删除您尝试导入的那个。

如果您想保留您尝试导入的那个,您可以从 Terraform 状态中删除不需要的那个,以便导入成功:
terraform state rm aws_security_group.Q8SgProdAdminSshInt

请注意,这只会让 Terraform “忘记”资源;它仍将存在于 EC2 中,需要通过控制台、命令行工具或 API 手动删除。一定要记下它的 id在删除它之前,以确保您可以找到它以便清理它。

关于amazon-web-services - 如何将手动更改导入 Terraform 远程状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43950097/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com