在 Terraform 中是否可以将状态从一个工作空间移动到另一个工作空间

In Terraform is it possible to move to state from one workspace to another

开始时我使用的是默认工作区。由于复杂性增加,我想使用多个工作区。我想将默认工作区中的内容移动到它自己的工作区或将默认工作区重命名为另一个工作区。我该怎么做?

是的,可以在工作区之间迁移状态。

假设您正在使用 S3 远程 backend 和 terraform 版本 >= 0.13 让我们看看这个状态手术是怎样的:

需要在工作区之间迁移的示例资源配置:

provider "local" {
  version = "2.1.0"
}

resource "local_file" "foo" {
  content  = "foo!"
  filename = "foo.bar"
}

terraform {
  backend "s3" {
    bucket         = ""
    region         = ""
    kms_key_id     = ""
    encrypt        = ""
    key            = ""
    dynamodb_table = ""
  }
}

让我们初始化 default 工作区和 apply 的后端:

terraform init
<Initialize the backend>

terraform workspace list
* default

terraform apply
local_file.foo: Refreshing state... [id=<>]

Apply complete! Resources: 0 added, 0 changed, 0 destroyed

因此,如您所见,已经创建了一个本地文件,并且状态存储在默认工作区中。 Terraform apply 没有改变任何东西。

现在,我们要迁移到新工作区:

在您仍在默认工作区时拉取状态

terraform state pull > default.tfstate

创建一个新的工作区;我们称它为 test

terraform workspace new test
Created and switched to workspace "test"!

如果您尝试 运行 terraform state list,您应该看不到任何状态。 让我们将状态推送到新创建的工作区并查看状态中的内容;还有当我们 apply.

时会发生什么
terraform state push default.tfstate

terraform state list
local_file.foo

terraform apply
local_file.foo: Refreshing state... [id=<>]

Apply complete! Resources: 0 added, 0 changed, 0 destroyed.

砰!您的 local_file.foo 已迁移到 test 工作区。

不要忘记切换回 default 工作区并删除此文件的状态引用。

terraform workspace select default
terraform state rm local_file.foo
Removed local_file.foo
Successfully removed 1 resource instance(s).

PS:我强烈建议阅读更多有关 managing Terraform state 的内容。

根据后端,Terraform 可能能够自行执行迁移。

为此,只需更新 terraform 块中的后端配置,然后 运行 以下命令自动迁移状态:

terraform init -migrate-state

这样做会将所有定义的工作区的状态从旧复制到新。

我可以确认这适用于 Terraform Cloud,即使使用前缀定义了多个工作区。

这里有一个逐步的方法,与默认答案略有不同。

首先,我们有一个默认的 s3 后端。

terraform {
  backend "s3" {
    encrypt        = true
    bucket         = "cool-bucket-name"
    key            = "production/terraform.tfstate"
    region         = "us-east-1"
    dynamodb_table = "cool-dynamo-db-lock-name"
  }
}

现在,检查我们的工作区。

terraform workspace list

  default  
* weird-workspace-name

通过首先注释掉 terraform 后端来拉低状态。

#terraform {
#  backend "s3" {
#    encrypt        = true
#    bucket         = "cool-bucket-name"
#    key            = "production/terraform.tfstate"
#    region         = "us-east-1"
#    dynamodb_table = "cool-dynamo-db-lock-name"
#  }
#}

运行本地迁移状态的命令。

terraform init -migrate-state

您可以查看状态,看看是否还可以继续使用。

terraform apply

Apply complete! Resources: 0 added, 0 changed, 0 destroyed.

接下来拉状态。状态文件的名称由您最初作为密钥提供的名称决定。

terraform state pull > terraform.tfstate

terraform workspace new cool-workspace-name

terraform state push terraform.tfstate

terraform apply

Apply complete! Resources: 0 added, 0 changed, 0 destroyed.

好的,现在去清理你的旧状态。

terraform workspace select weird-workspace-name

terraform state list | cut -f 1 -d '[' | xargs -L 0 terraform state rm

terraform workspace select cool-workspace-name

terraform workspace delete weird-workspace-name

运行再次应用 terraform 命令。

terraform apply

Apply complete! Resources: 0 added, 0 changed, 0 destroyed.

现在将您的状态移回 S3,取消对 terraform backend.tf 文件的注释。

terraform {
  backend "s3" {
    encrypt        = true
    bucket         = "cool-bucket-name"
    key            = "production/terraform.tfstate"
    region         = "us-east-1"
    dynamodb_table = "cool-dynamo-db-lock-name"
  }
}

运行:

terraform init -migrate-state

非常感谢 bhalothia 的回答,我只是想一步一步地添加另一个案例。

None 的预览答案对我有用,每次新工作区都应该是空的。为了填充它,您需要根据文档使用 -statehttps://www.terraform.io/cli/commands/workspace/new

那么什么有效:

  • 创建本地备份 terraform state pull > default.tfstate
  • 通过评论后端块然后切换到本地 terraform init -migrate-state
  • 使用 terraform workspace new -state=default.tfstate newspace 创建新工作区这会将 default 复制到 newspace
  • 做一个terraform plan检查
  • 取消注释后端块以切换回云端,然后 运行 terraform init -migrate-state 将您的新工作区迁移到云端
  • 执行 terraform planterraform workspace list 检查。