Gri*_*cat 3 amazon-web-services terraform
我是terraform的新手 - 我已经在s3中创建了远程tfstate,现在我的AWS基础架构中也进行了一些手动更改.我需要将这些手动更改导入到tfstate中.
我对某些资源使用了import命令,但是对于某些资源,例如IAM策略等,没有这样的import命令.
此外,一些资源(如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.
Run Code Online (Sandbox Code Playgroud)
任何帮助,将不胜感激.谢谢.
Mar*_*ins 28
在直接回答这个问题之前,我认为一些背景会有所帮助:
在幕后,Terraform维护一个状态文件,其中包含从配置中的资源到底层提供程序API中的对象的映射.使用Terraform创建新对象时,创建的对象的ID将自动保存在状态中,以便将来的命令可以找到引用的对象以进行读取,更新和删除操作.
terraform import然后,是在状态文件中创建条目的另一种方法.而不是创建新对象并记录其id,而是用户在命令行上提供id.Terraform 使用该id 读取对象并将结果添加到状态文件中,之后它在状态上与Terraform自己创建的资源无法区分.
所以尽管如此,让我们一个一个地解决你的问题.
terraform import由于每个资源都需要少量验证和数据获取代码才能进行导入,因此此时并不支持导入所有资源.
鉴于我们terraform import对上述内容的了解,理论上可以跳过Terraform对提供的id的验证,而是手动将资源添加到状态.这是一项高级操作,必须小心谨慎,以免破坏状态.
首先,将状态检索到您将用于本地工作的本地文件中:
terraform state pull >manual-import.tfstate
Run Code Online (Sandbox Code Playgroud)
这将创建一个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": ""
}
},
Run Code Online (Sandbox Code Playgroud)
此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": ""
}
},
Run Code Online (Sandbox Code Playgroud)
这一步的挑战是弄清楚这种资源需要什么样的id.知道这一点的唯一可靠方法是阅读代码,该代码告诉我该资源期望id是策略的完整ARN.
有了这些知识,我们将?????上面示例中的两个序列替换为我们要导入的策略的ARN.
手动更改状态后,需要更新serial文件顶层的编号.Terraform预计任何新的更改都会有更高的序列号,因此我们可以增加这个数字.
完成更新后,我们必须将更新后的状态文件上传回Terraform:
terraform state push manual-import.tfstate
Run Code Online (Sandbox Code Playgroud)
最后,我们可以要求Terraform刷新状态以确保它有效:
terraform refresh
Run Code Online (Sandbox Code Playgroud)
同样,这是一个非常危险的过程,因为状态文件是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.
Run Code Online (Sandbox Code Playgroud)
此消息的含义是,当Terraform尝试将新资源写入状态文件时,它发现该名称已存在资源条目aws_security_group.Q8SgProdAdminSshInt.这表明它已经被导入或者Terraform已经创建了一个新的安全组.
您可以检查状态中现有资源的属性:
terraform state show aws_security_group.Q8SgProdAdminSshInt
Run Code Online (Sandbox Code Playgroud)
将返回的数据与您尝试导入的安全组进行比较.如果id匹配,则没有什么可做的,因为资源已经导入.
如果id 不匹配,那么你需要确定两个对象中的哪一个是你想要保留的对象.如果您想保留Terraform已有的那个,您可以手动删除您尝试导入的那个.
如果您想保留您尝试导入的那个,可以从Terraform状态中删除不需要的那个,以便导入成功:
terraform state rm aws_security_group.Q8SgProdAdminSshInt
Run Code Online (Sandbox Code Playgroud)
请注意,这只会使Terraform"忘记"资源; 它仍然存在于EC2中,需要通过控制台,命令行工具或API手动删除.请务必id在删除之前记下它,以确保您可以找到它以便清理它.
| 归档时间: |
|
| 查看次数: |
6069 次 |
| 最近记录: |