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

时间:2018-05-17 20:27:32

标签: amazon-web-services amazon-s3 terraform

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

4 个答案:

答案 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

中所述
  
      
  1. 使用更少的资源可以更轻松,更快捷地工作:      
        
    • Cmds terraform planterraform都应用make Cloud API调用来验证资源状态。
    •   
    • 如果您将整个基础架构包含在一个组合中,则可能要花费几分钟(即使同一文件中有多个文件)   文件夹)。
    •   
  2.   

因此,如果您最终对每个资源都拥有一个mono-dir,那么就永远不晚要开始按服务,团队,客户等对它们进行隔离。


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

示例方案:

假设我们有一个名为common的文件夹,其中包含某个项目的所有.tf文件,我们决定划分(移动)我们的.tf Terraform 资源到名为security的新项目文件夹。因此我们现在需要将一些资源从common项目文件夹移动到security

情况1:

如果security文件夹仍然不存在(这是最佳方案)。

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

例如:

terraform state list
  1. 在我们新创建的# Backend Config (partial) terraform { required_version = ">= 0.11.14" backend "s3" { key = "account-name/security/terraform.tfstate" } } 文件夹中,运行security(不删除已复制的terraform-init本地文件夹,该文件夹已经在步骤2中生成并同步了),因此,将在新的S3路径中生成资源状态的新副本(交互询问)。这是安全的操作,因为我们尚未从旧的.terraform路径文件中删除资源。
.tfstate

enter image description here

  1. 有选择地从每个状态($ 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保持同步。这是明智的操作,请首先在不太关键的单一资源中测试该过程。

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

情况2:

如果.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