将 Terraform 状态存储在 Cloud Storage 存储桶中


在本教程中,您将学习如何在 Cloud Storage 存储桶中存储 Terraform 状态。

默认情况下,Terraform 会将状态存储在名为 terraform.tfstate 的本地文件中。当多个用户同时运行 Terraform 并且每个机器都对当前基础架构有自己的理解时,如果采用此默认配置,则使用 Terraform 对团队而言可能会很困难。

为帮助您避免此类问题,本页介绍了如何配置指向 Cloud Storage 存储桶的远程状态。远程状态是 Terraform 后端的一项功能。

目标

本教程介绍了如何执行以下操作:

  • 使用 Terraform 预配 Cloud Storage 存储桶以存储 Terraform 状态。
  • 在 Terraform 配置文件中添加模板,以将状态从本地后端迁移到 Cloud Storage 存储桶。

费用

在本文档中,您将使用 Google Cloud 的以下收费组件:

您可使用价格计算器根据您的预计使用情况来估算费用。 Google Cloud 新用户可能有资格申请免费试用

完成本文档中描述的任务后,您可以通过删除所创建的资源来避免继续计费。如需了解详情,请参阅清理

Cloud Storage 会产生存储、读写操作、网络出站流量和复制费用。

本教程中的 Cloud Storage 存储桶启用了对象版本控制,以保留部署历史记录。启用“对象版本控制”会增加存储费用,您可以将对象生命周期管理配置为删除旧的状态版本,以缓解存储费用增加问题。

准备工作

  1. 在 Google Cloud 控制台中,激活 Cloud Shell。

    激活 Cloud Shell

    Cloud Shell 已预装 Terraform。

  2. 如果您使用的是本地 Shell,请执行以下步骤:

    • 安装 Terraform
    • 为您的 Google 账号创建本地身份验证凭据:

      gcloud auth application-default login
  3. Create or select a Google Cloud project.

    • Create a Google Cloud project:

      gcloud projects create PROJECT_ID

      Replace PROJECT_ID with a name for the Google Cloud project you are creating.

    • Select the Google Cloud project that you created:

      gcloud config set project PROJECT_ID

      Replace PROJECT_ID with your Google Cloud project name.

  4. 确保您的 Google Cloud 项目已启用结算功能

  5. Enable the Cloud Storage API:

    gcloud services enable storage.googleapis.com
  6. 向您的 Google 账号授予角色。对以下每个 IAM 角色运行以下命令一次: roles/storage.admin

    gcloud projects add-iam-policy-binding PROJECT_ID --member="user:EMAIL_ADDRESS" --role=ROLE
    • PROJECT_ID 替换为您的项目 ID。
    • EMAIL_ADDRESS 替换为您的电子邮件地址。
    • ROLE 替换为每个角色。
  7. 或者,您也可以创建包含以下权限的自定义 IAM 角色

    • storage.buckets.create
    • storage.buckets.list
    • storage.objects.get
    • storage.objects.create
    • storage.objects.delete
    • storage.objects.update

    我们建议的最佳实践是控制对存储桶及其中存储的状态文件的访问权限。只有一小部分用户(例如,主要的云管理员和担任顶替管理员的人员)应具有存储桶的管理员权限。其他开发者应具有仅在存储桶中读写对象的权限。

准备环境

  1. 克隆包含 Terraform 示例的 GitHub 代码库:

    git clone https://github.com/terraform-google-modules/terraform-docs-samples.git --single-branch
    
  2. 切换到工作目录:

    cd terraform-docs-samples/storage/remote_terraform_backend_template
    

查看 Terraform 文件

  1. 查看 main.tf 文件:

    cat main.tf
    

    输出类似于以下内容

    resource "random_id" "default" {
      byte_length = 8
    }
    
    resource "google_storage_bucket" "default" {
      name     = "${random_id.default.hex}-terraform-remote-backend"
      location = "US"
    
      force_destroy               = false
      public_access_prevention    = "enforced"
      uniform_bucket_level_access = true
    
      versioning {
        enabled = true
      }
    }
    
    resource "local_file" "default" {
      file_permission = "0644"
      filename        = "${path.module}/backend.tf"
    
      # You can store the template in a file and use the templatefile function for
      # more modularity, if you prefer, instead of storing the template inline as
      # we do here.
      content = <<-EOT
      terraform {
        backend "gcs" {
          bucket = "${google_storage_bucket.default.name}"
        }
      }
      EOT
    }

    此文件描述了以下资源:

    • erandom_id:附加到 Cloud Storage 存储桶名称,以确保 Cloud Storage 存储桶具有唯一的名称。
    • google_storage_bucket:用于存储状态文件的 Cloud Storage 存储桶。此存储桶配置为具有以下属性:
      • force_destroy 设置为 false,以确保在存储桶中存在对象时不会被删除。这样可以确保存储桶中的状态信息不会被意外删除。
      • public_access_prevention 设置为 enforced,以确保存储桶内容不会被意外公开。
      • uniform_bucket_level_access 设置为 true 以允许使用 IAM 权限而不是访问控制列表来控制对存储桶及其内容的访问。
      • 启用了 versioning,以确保将状态的早期版本保留在存储桶中。
    • local_file:本地文件。此文件的内容指示 Terraform 将 Cloud Storage 存储桶用作远程后端。

预配 Cloud Storage 存储桶

  1. 初始化 Terraform:

    terraform init
    

    首次运行 terraform init 时,您在 main.tf 文件中指定的 Cloud Storage 存储桶尚不存在,因此 Terraform 会初始化本地后端以将状态存储在本地文件系统中。

  2. 应用配置以预配 main.tf 文件中所述的资源:

    terraform apply
    

    出现提示时,输入 yes

    当您首次运行 terraform apply 时,Terraform 会预配 Cloud Storage 存储桶以存储状态。它还会创建一个本地文件:此文件的内容指示 Terraform 将 Cloud Storage 存储桶用作远程后端来存储状态。

将状态迁移到 Cloud Storage 存储桶

  1. 将 Terraform 状态迁移到远程 Cloud Storage 后端:

    terraform init -migrate-state
    

    Terraform 检测到本地已有状态文件,并提示您将状态迁移到新的 Cloud Storage 存储桶。出现提示时,输入 yes

运行此命令后,您的 Terraform 状态将存储在 Cloud Storage 存储桶中。Terraform 在运行命令之前从此存储桶拉取最新状态,并在运行命令后将最新状态推送到存储桶。

清理

为避免因本教程中使用的资源导致您的 Google Cloud 账号产生费用,请删除包含这些资源的项目,或者保留项目但删除各个资源。

删除项目

为避免因本页面中使用的资源导致您的 Google Cloud 账号产生费用,请按照以下步骤操作。

  1. 打开 main.tf 文件。

  2. google_storage_bucket.default 资源中,将 force_destroy 的值更新为 true

  3. 应用更新后的配置:

    terraform apply
    

    出现提示时,输入 yes

  4. 删除状态文件:

    rm backend.tf
    
  5. 将后端重新配置为本地:

    terraform init -migrate-state
    

    出现提示时,输入 yes

  6. 运行以下命令以删除 Terraform 资源:

    terraform destroy
    

    出现提示时,输入 yes

后续步骤