Terraform:如何在项目之间迁移状态?

Nat*_*han 10 amazon-s3 amazon-web-services terraform

将资源状态从一个项目(即,移动模块调用)迁移到另一个项目的最不痛苦的方法是什么,特别是在使用远程状态存储时?虽然重构在同一个状态文件中相对简单(即,获取此资源并将其移动到子模块,反之亦然),但我没有看到JSON手术的替代方法,用于重构到不同的状态文件,特别是如果我们使用远程(S3)状态(即,取这个子模块并将其移动到另一个项目).

Rub*_*uck 17

我发现最不痛苦的方法是将两个远程状态拉到本地,在两者之间移动模块/资源,然后再向上推.还要记住,如果您要移动模块,请不要移动单个资源; 移动整个模块.

例如:

cd dirA
terraform state pull > ../dirA.tfstate

cd ../dirB
terraform state pull > ../dirB.tfstate

terraform state mv -state=../dirA.tfstate -state-out=../dirB.tfstate module.foo module.foo

terraform state push ../dirB.tfstate

# verify state was moved
terraform state list | grep foo

cd ../dirA
terraform state push ../dirA.state
Run Code Online (Sandbox Code Playgroud)

不幸的是,terraform state mv command不支持指定两个远程后端,所以这是我找到多个遥控器之间移动状态的最简单的方法.

  • 是的,是的,我现在正在运行它,它工作得很好!比手动导入和删除更快,更不容易出错. (2认同)

tra*_*ang 8

我使用这个脚本(从 v0.12 开始不起作用)在重构时迁移状态。请随意根据您的需要采用它。

src=<source dir>
dst=<target dir>
resources=(
    aws_s3_bucket.bucket1
    aws_iam_role.role2
    aws_iam_user.user1
    aws_s3_bucket.bucket2
    aws_iam_policy.policy2
)
cd $src
terraform state pull >/tmp/source.tfstate
cd $dst
terraform state pull >/tmp/target.tfstate
for resource in "${resources[@]}"; do
    terraform state mv -state=/tmp/source.tfstate -state-out=/tmp/target.tfstate "${resource}" "${resource}"
done
terraform state push /tmp/target.tfstate
cd $src
terraform state push /tmp/source.tfstate
Run Code Online (Sandbox Code Playgroud)

请注意,它terraform pull从 v0.12 开始已弃用(但未删除且仍然有效),并且从 v0.12 开始不再terraform push 有效。

重要提示: terraform push 命令已弃用,并且仅适用于旧版本的 Terraform Enterprise。在当前版本的 Terraform Cloud 中,您可以使用API 上传配置。有关更多详细信息,请参阅有关 API 驱动的运行的文档。

=================

以下与OP无关:

如果您要在同一项目中重命名资源。

  • 对于版本 <= 1.0:使用terraform state mv ....
  • 对于版本 >= 1.1,请使用moved描述的语句:herehere

我在博客中列出了其他几个有用的命令


yda*_*coR 6

可能最简单的选择是terraform import在新状态文件位置的资源上使用,然后terraform state rm在旧位置使用.

在复制/移动.terraform文件夹时,Terraform会处理一些自动状态迁移,但我只是在移动整个状态文件而不是部分文件时使用它.


Exe*_*ero 6

正如相关的 Terraform Q ->使用 Terraform 时的最佳实践中提到的

  1. 使用较少数量的资源会更容易、更快捷:
    • Cmdsterraform planterraformapply 都会调用云 API 来验证资源的状态。
    • 如果您将整个基础架构放在一个组合中,这可能需要很多分钟(即使您在同一文件夹中有多个文件)。

因此,如果您最终会得到每个资源的单一目录,那么开始按服务、团队、客户等将它们隔离永远不会太晚。


在项目/服务之间迁移 Terrform 状态的可能程序:

示例场景:

假设我们有一个以某个项目的common所有文件命名的文件夹,并且我们决定将Terraform资源划分(移动)到一个名为 的新项目文件夹。所以我们现在需要将一些资源从项目文件夹移动到..tf.tf securitycommonsecurity

情况1:

如果该security文件夹仍然不存在(这是最好的情况)。

  1. 备份存储在相应 AWS S3 存储桶中的 Terraform 后端状态内容(因为它是版本化的,所以我们应该更安全)。
  2. 将您的控制台放置在原始文件夹中,对于我们的案例,common执行make init以确保您的.terraform本地文件夹与远程状态同步。
  3. 如果该security文件夹仍然不存在(应该是这样),则克隆(复制)common具有目标名称的文件夹security,并更新config.tf此新克隆文件夹内的文件以指向新的 S3 后端路径(考虑一次更新 1 个帐户,从不太重要的一个并用 ) 评估结果terraform state list

例如:

# Backend Config (partial)
terraform {
  required_version = ">= 0.11.14"

  backend "s3" {
    key = "account-name/security/terraform.tfstate"
  }
}
Run Code Online (Sandbox Code Playgroud)
  1. 在我们新创建的security文件夹中,运行terraform-init(无需删除复制的.terraform本地文件夹,该文件夹已在步骤 2 中生成并同步),这将在新的 S3 路径中生成资源状态的新副本(交互式询问)。这是一个安全的操作,因为我们尚未从旧路径文件中删除资源.tfstate
$ make init
terraform init -backend-config=../config/backend.config
Initializing modules...
- module.cloudtrail
- module.cloudtrail.cloudtrail_label

Initializing the backend...
Backend configuration changed!

Terraform has detected that the configuration specified for the backend
has changed. Terraform will now check for existing state in the backends.

Acquiring state lock. This may take a few moments...
Acquiring state lock. This may take a few moments...
Do you want to copy existing state to the new backend?
  Pre-existing state was found while migrating the previous "s3" backend to the
  newly configured "s3" backend. No existing state was found in the newly
  configured "s3" backend. Do you want to copy this state to the new "s3"
  backend? Enter "yes" to copy and "no" to start with an empty state.

  Enter a value: yes
...                                                             

Successfully configured the backend "s3"! Terraform will automatically                                                                        
use this backend unless the backend configuration changes.                                                                                    

Initializing provider plugins...                                                                                                              
...                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             
Terraform has been successfully initialized!                                                                                                                                                                                                                                             
...                                                                                                                                                                                                                                                            
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

  1. 有选择地从每个状态 ( ) 中删除所需的资源terraform state rm module.foo,以便将所需的资源保留在/common/security路径中。此外,必须从每个文件夹中的 .tf 文件中并行执行模块/资源的必要更新(添加/删除),以保持本地代码库声明和远程代码库同步.tfstate。这是一个明智的操作,请首先在不太重要的单一资源中测试该过程。

作为参考,我们可以考虑以下文档和工具:

案例2:

如果该security文件夹已存在并且在其 AWS S3 路径中具有关联的远程 .tfstate,您将需要使用不同的步骤和命令序列,可能是以下链接中引用的步骤和命令: 1. https://www.terraform。 io/docs/commands/state/list.html 2. https://www.terraform.io/docs/commands/state/pull.html 3. https://www.terraform.io/docs/commands/state/ mv.html 4. https://www.terraform.io/docs/commands/state/push.html

参考链接: