【问题标题】:Terraform: How to migrate state between projects?Terraform:如何在项目之间迁移状态?
【发布时间】:2018-10-28 05:27:24
【问题描述】:

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

【问题讨论】:

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


    【解决方案1】:

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

    例如:

    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.tfstate
    

    不幸的是,the terraform state mv command doesn’t support specifying two remote backends,所以这是我发现在多个遥控器之间移动状态的最简单方法。

    【讨论】:

    • 如果您使用 grep 搜索整个资源地址 module.foo 则可以使用 sed -e 's/[]\/$*.^[]/\\&/g' 转义特殊字符
    【解决方案2】:

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

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

    【讨论】:

      【解决方案3】:

      我使用这个脚本(不适用于 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
      

      请注意,terraform pull 从 v0.12 已弃用(但未删除且仍然有效),terraform push does not work 从 v0.12 不再支持。

      重要提示:terraform push 命令已弃用,仅适用 使用旧版 Terraform Enterprise。在当前 Terraform Cloud 版本,您可以使用the API. See the docs about API-driven runs 上传配置以获取更多详细信息。

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

      以下与OP无关:

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

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

      我在my blog中列出了其他几个有用的命令

      【讨论】:

        【解决方案4】:

        如相关 Terraform Q 中所述 -> Best practices when using Terraform

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

        因此,如果您最终对每个资源都有一个单一目录,那么开始按服务、团队、客户等进行隔离,永远不会太晚。


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

        示例场景:

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

        案例一:

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

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

        例如:

        # Backend Config (partial)
        terraform {
          required_version = ">= 0.11.14"
        
          backend "s3" {
            key = "account-name/security/terraform.tfstate"
          }
        }
        
        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!                                                                                                                                                                                                                                             
        ...                                                                                                                                                                                                                                                            
        

        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

        参考链接:

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-06-01
          • 2020-03-07
          • 1970-01-01
          • 2017-08-10
          • 1970-01-01
          • 2016-02-21
          • 2019-07-05
          • 1970-01-01
          相关资源
          最近更新 更多