将资源状态从一个项目(即,移动模块调用)迁移到另一个项目的最不痛苦的方法是什么,特别是在使用远程状态存储时?虽然重构在同一个状态文件中相对简单(即,获取此资源并将其移动到子模块或反之亦然),但我没有看到JSON手术的替代方法,用于重构到不同的状态文件,特别是如果我们使用远程(S3)状态(即,获取此子模块并将其移动到另一个项目)。
答案 0 :(得分:13)
The least painful way I’ve found is to pull both remote states local, move the modules/resources between the two, then push back up. Also remember, if you’re moving a module, don’t move the individual resources; move the whole module.
For example:
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
Unfortunately, the terraform state mv command
doesn’t support specifying two remote backends,因此这是我发现在多个遥控器之间移动状态的最简单方法。
答案 1 :(得分:5)
最简单的选择可能是在新状态文件位置的资源上使用terraform import
,然后在旧位置使用terraform state rm
。
Terraform在复制/移动.terraform文件夹时会处理一些自动状态迁移,但我只是在移动整个状态文件而不是部分文件时使用它。
答案 2 :(得分:0)
如相关Terraform Q-> Best practices when using Terraform
中所述
- 使用更少的资源可以更轻松,更快捷地工作:
- Cmds
terraform plan
和terraform
都应用make Cloud API调用来验证资源状态。- 如果您将整个基础架构包含在一个组合中,则可能要花费几分钟(即使同一文件中有多个文件) 文件夹)。
因此,如果您最终对每个资源都拥有一个mono-dir,那么就永远不晚要开始按服务,团队,客户等对它们进行隔离。
假设我们有一个名为common
的文件夹,其中包含某个项目的所有.tf
文件,我们决定划分(移动)我们的.tf
Terraform 资源到名为security
的新项目文件夹。因此我们现在需要将一些资源从common
项目文件夹移动到security
。
如果security
文件夹仍然不存在(这是最佳方案)。
common
执行make init
,以确保您的.terraform
本地文件夹已与您的远程状态同步。security
文件夹仍然不存在(应该为真),请克隆(复制)目标名称为common
的{{1}}文件夹并更新security
文件在这个新的克隆文件夹中指向新的S3后端路径(考虑从不太重要的帐户开始一次更新1个帐户,并使用config.tf
评估结果)。例如:
terraform state list
# Backend Config (partial)
terraform {
required_version = ">= 0.11.14"
backend "s3" {
key = "account-name/security/terraform.tfstate"
}
}
文件夹中,运行security
(不删除已复制的terraform-init
本地文件夹,该文件夹已经在步骤2中生成并同步了),因此,将在新的S3路径中生成资源状态的新副本(交互询问)。这是安全的操作,因为我们尚未从旧的.terraform
路径文件中删除资源。.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!
...
)中删除所需的资源,以便将所需的资源保留在terraform state rm module.foo
和/common
路径中。此外,必须并行执行每个文件夹中.tf文件中模块/资源的必要更新(添加/删除),以使本地代码库声明和远程/security
保持同步。这是明智的操作,请首先在不太关键的单一资源中测试该过程。 作为参考,我们可以考虑以下文档和工具:
如果.tfstate
文件夹已经存在并且在其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
引用链接:
答案 3 :(得分:0)
我使用此脚本在重构时迁移状态。随意采用它以满足您的需要。
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