如何将手动更改导入 Terraform 远程状态

本文介绍了如何将手动更改导入 Terraform 远程状态的处理方法,对大家解决问题具有一定的参考价值

问题描述

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

I am new to terraform - I have created remote tfstate in s3, and now there are some manual changes too that are done in my AWS infrastructure. I need to import those manual changes into tfstate.

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

I used the import command for some resources, but for some resources such as IAM policy etc, there is no such import command.

还有一些资源,比如DB,随着新参数的增加而改变,我也需要导入它们.当我尝试导入这些更改时,它会说:

Also some resources such as DB are changed with new parameters added, and I need to import them as well. When I try to import those changes it says:

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.

任何帮助将不胜感激.谢谢.

Any help would be appreciated. Thanks.

推荐答案

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

Before directly answering this question I think some context would help:

在幕后,Terraform 维护一个状态文件,其中包含从配置中的资源到底层提供程序 API 中的对象的映射.当您使用 Terraform 创建新对象时,创建的对象的 id 会自动保存在状态中,以便将来的命令可以定位引用的对象进行读取、更新和删除操作.

Behind the scenes, Terraform maintains a state file that contains a mapping from the resources in your configuration to the objects in the underlying provider API. When you create a new object with Terraform, the id of the object that was created is automatically saved in the state so that future commands can locate the referenced object for read, update, and delete operations.

terraform import 是在状态文件中创建条目的另一种方式.用户不是创建一个新对象并记录其 id,而是在命令行上提供一个 id.Terraform 读取具有该 id 的对象并将结果添加到状态文件中,之后在状态中它与 Terraform 自己创建的资源无法区分.

terraform import, then, is a different way to create an entry in the state file. Rather than creating a new object and recording its id, instead the user provides an id on the command line. Terraform reads the object with that id and adds the result to the state file, after which it is indistinguishable in the state from a resource that Terraform created itself.

说了这么多,让我们一一解答您的问题.

So with all of that said, let's address your questions one-by-one.

由于每个资源都需要少量验证和数据提取代码来进行导入,因此目前并非所有资源都支持导入.

Since each resource requires a small amount of validation and data-fetching code to do an import, not all resources are supported for import at this time.

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

Given what we know about what terraform import does from the above, in theory it's possible to skip Terraform's validation of the provided id and instead manually add the resource to the state. This is an advanced operation and must be done with care to avoid corrupting the state.

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

First, retrieve the state into a local file that you'll use for your local work:

terraform state pull >manual-import.tfstate

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

This will create a file manual-import.tfstate that you can open in a text editor. It uses JSON syntax, so though its internal structure is not documented as a stable format we can carefully edit it as long as we remain consistent with the expected structure.

最简单的方法是找到与您要导入、复制和编辑的模块位于同一模块中的现有资源.假设我们有一个像这样的 resources 对象:

It's simplest to locate an existing resource that is in the same module as where you want to import and duplicate and edit it. Let's assume we have a resources object like this:

"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 的内容.

Each attribute within this resources object corresponds to a resource in your configuration. The attribute name is the type and name of the resource. In this case, the resource type is null_resource and the attribute name is foo. In your case you might see something like aws_instance.server here.

id 属性对于许多资源(但不是全部!)来说是需要填充的主要内容.因此,我们可以为假设的 IAM 策略复制此结构:

The id attributes are, for many resources (but not all!), the main thing that needs to be populated. So we can duplicate this structure for a hypothetical IAM policy:

"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.知道这一点的唯一可靠方法是 阅读代码,它告诉我这个资源期望 id 是策略的完整 ARN.

The challenge at this step is to figure out what sort of id this resource requires. The only sure-fire way to know this is to read the code, which tells me that this resource expects the id to be the full ARN of the policy.

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

With that knowledge, we replace the two ????? sequences in the above example with the ARN of the policy we want to import.

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

After making manual changes to the state it's necessary to update the serial number at the top-level of the file. Terraform expects that any new change will have a higher serial number, so we can increment this number.

完成更新后,我们必须将更新后的状态文件上传回 Terraform:

After completing the updates, we must upload the updated state file back into Terraform:

terraform state push manual-import.tfstate

最后我们可以让 Terraform 刷新状态以确保它正常工作:

Finally we can ask Terraform to refresh the state to make sure it worked:

terraform refresh

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

Again, this is a pretty risky process since the state file is Terraform's record of its relationship with the underlying system and it can be hard to recover if the content of this file is lost. It's often easier to simply replace a resource than to go to all of this effort, unless it's already serving a critical role in your infrastructure and there is no graceful migration strategy available.

您的问题中给出的错误消息是关于与现有资源冲突"的导入:

The error message given in your question is talking about an import "colliding" with an existing resource:

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 本身已经创建了一个新的安全组.

The meaning of this message is that when Terraform tried to write the new resource to the state file it found a resource entry already present for the name aws_security_group.Q8SgProdAdminSshInt. This suggests that either it was already imported or that a new security group was already created by Terraform itself.

您可以检查状态中现有资源的属性:

You can inspect the attributes of the existing resource in state:

terraform state show aws_security_group.Q8SgProdAdminSshInt

将返回的数据与您尝试导入的安全组进行比较.如果 id 匹配,则无需执行任何操作,因为资源已经导入.

Compare the data returned with the security group you were trying to import. If the ids match then there's nothing left to do, since the resource was already imported.

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

If the ids don't match then you need to figure out which of the two objects is the one you want to keep. If you'd like to keep the one that Terraform already has, you can manually delete the one you were trying to import.

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

If you'd like to keep the one you were trying to import instead, you can drop the unwanted one from the Terraform state to make way for the import to succeed:

terraform state rm aws_security_group.Q8SgProdAdminSshInt

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

Note that this just makes Terraform "forget" the resource; it will still exist in EC2, and will need to be deleted manually via the console, command line tools, or API. Be sure to note down its id before deleting it to ensure that you can find it in order to to clean it up.

这篇关于如何将手动更改导入 Terraform 远程状态的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,WP2

admin_action_{$_REQUEST[‘action’]}

do_action( "admin_action_{$_REQUEST[‘action’]}" )动作钩子::在发送“Action”请求变量时激发。Action Hook: Fires when an ‘action’ request variable is sent.目录锚点:#说明#源码说明(Description)钩子名称的动态部分$_REQUEST['action']引用从GET或POST请求派生的操作。源码(Source)更新版本源码位置使用被使用2.6.0 wp-admin/admin.php:...

日期:2020-09-02 17:44:16 浏览:1127

admin_footer-{$GLOBALS[‘hook_suffix’]}

do_action( "admin_footer-{$GLOBALS[‘hook_suffix’]}", string $hook_suffix )操作挂钩:在默认页脚脚本之后打印脚本或数据。Action Hook: Print scripts or data after the default footer scripts.目录锚点:#说明#参数#源码说明(Description)钩子名的动态部分,$GLOBALS['hook_suffix']引用当前页的全局钩子后缀。参数(Parameters)参数类...

日期:2020-09-02 17:44:20 浏览:1032

customize_save_{$this->id_data[‘base’]}

do_action( "customize_save_{$this->id_data[‘base’]}", WP_Customize_Setting $this )动作钩子::在调用WP_Customize_Setting::save()方法时激发。Action Hook: Fires when the WP_Customize_Setting::save() method is called.目录锚点:#说明#参数#源码说明(Description)钩子名称的动态部分,$this->id_data...

日期:2020-08-15 15:47:24 浏览:775

customize_value_{$this->id_data[‘base’]}

apply_filters( "customize_value_{$this->id_data[‘base’]}", mixed $default )过滤器::过滤未作为主题模式或选项处理的自定义设置值。Filter Hook: Filter a Customize setting value not handled as a theme_mod or option.目录锚点:#说明#参数#源码说明(Description)钩子名称的动态部分,$this->id_date['base'],指的是设置...

日期:2020-08-15 15:47:24 浏览:866

get_comment_author_url

过滤钩子:过滤评论作者的URL。Filter Hook: Filters the comment author’s URL.目录锚点:#源码源码(Source)更新版本源码位置使用被使用 wp-includes/comment-template.php:32610...

日期:2020-08-10 23:06:14 浏览:903

network_admin_edit_{$_GET[‘action’]}

do_action( "network_admin_edit_{$_GET[‘action’]}" )操作挂钩:启动请求的处理程序操作。Action Hook: Fires the requested handler action.目录锚点:#说明#源码说明(Description)钩子名称的动态部分$u GET['action']引用请求的操作的名称。源码(Source)更新版本源码位置使用被使用3.1.0 wp-admin/network/edit.php:3600...

日期:2020-08-02 09:56:09 浏览:848

network_sites_updated_message_{$_GET[‘updated’]}

apply_filters( "network_sites_updated_message_{$_GET[‘updated’]}", string $msg )筛选器挂钩:在网络管理中筛选特定的非默认站点更新消息。Filter Hook: Filters a specific, non-default site-updated message in the Network admin.目录锚点:#说明#参数#源码说明(Description)钩子名称的动态部分$_GET['updated']引用了非默认的...

日期:2020-08-02 09:56:03 浏览:834

pre_wp_is_site_initialized

过滤器::过滤在访问数据库之前是否初始化站点的检查。Filter Hook: Filters the check for whether a site is initialized before the database is accessed.目录锚点:#源码源码(Source)更新版本源码位置使用被使用 wp-includes/ms-site.php:93910...

日期:2020-07-29 10:15:38 浏览:809

WordPress 的SEO 教学:如何在网站中加入关键字(Meta Keywords)与Meta 描述(Meta Description)?

你想在WordPress 中添加关键字和meta 描述吗?关键字和meta 描述使你能够提高网站的SEO。在本文中,我们将向你展示如何在WordPress 中正确添加关键字和meta 描述。为什么要在WordPress 中添加关键字和Meta 描述?关键字和说明让搜寻引擎更了解您的帖子和页面的内容。关键词是人们寻找您发布的内容时,可能会搜索的重要词语或片语。而Meta Description则是对你的页面和文章的简要描述。如果你想要了解更多关于中继标签的资讯,可以参考Google的说明。Meta 关键字和描...

日期:2020-10-03 21:18:25 浏览:1620

谷歌的SEO是什么

SEO (Search Engine Optimization)中文是搜寻引擎最佳化,意思近于「关键字自然排序」、「网站排名优化」。简言之,SEO是以搜索引擎(如Google、Bing)为曝光媒体的行销手法。例如搜寻「wordpress教学」,会看到本站的「WordPress教学:12个课程…」排行Google第一:关键字:wordpress教学、wordpress课程…若搜寻「网站架设」,则会看到另一个网页排名第1:关键字:网站架设、架站…以上两个网页,每月从搜寻引擎导入自然流量,达2万4千:每月「有机搜...

日期:2020-10-30 17:23:57 浏览:1264