将 Google Cloud 资源导入 Terraform 状态

Terraform 可以导入现有基础设施。这样,您就可以采用某种其他方式创建的资源,并将这些资源置于 Terraform 管理下。

您可以导入任何 Google Cloud 资源的状态。

Terraform 支持多种导入资源的方法:

一次导入一个资源

import 命令采用两个参数:资源地址和 ID。资源地址是指向配置中的资源实例的标识符。ID 是标识 Google Cloud 中要导入的资源的标识符。ID 的格式因资源类型而异,并针对提供商支持的每种资源进行记录。我们建议使用完整的标识符,其中包含项目 ID(如果支持)。

  • 确定要导入的资源的地址。

    resource "google_storage_bucket" "sample" {
     name          = "my-bucket"
     project       = "sample-project"
     location      = "US"
     force_destroy = true
    }
    

    对于示例资源(例如先前定义的 Cloud Storage 存储桶),这是 google_storage_bucket.sample

  • 如需确定资源 ID 格式,请参阅 google_storage_bucket 资源的提供商导入文档。在本例中,采用 project/name 格式,因此上面示例的资源 ID 为 sample-project/my-bucket

  • 使用资源地址和 ID 构建 import 语句,如下所示:

    terraform import google_storage_bucket.sample sample-project/my-bucket
    

    输出:

    terraform import google_storage_bucket.sample sample-project/my-bucket
    google_storage_bucket.sample: Importing from ID "sample-project/my-bucket"...
    google_storage_bucket.sample: Import prepared!
    Prepared google_storage_bucket for import
    google_storage_bucket.sample: Refreshing state... [id=sample-project/my-bucket]
    Import successful!
    The resources that were imported are shown above. These resources are now in
    your Terraform state and will henceforth be managed by Terraform.
    

导入模块中的资源

模块在 Terraform 配置中封装一个或多个资源。由于导入操作需要资源地址,因此必须单独导入模块中的每个资源。

  • 确定要导入的模块中的资源。

    module "gcs_bucket" {
     source  = "terraform-google-modules/cloud-storage/google//modules/simple_bucket"
     version = "~> 3.4"
    
     name       = "my-bucket"
     project_id = "sample-project"
     location   = "us-east1"
    }
    

    如需确定资源地址,您可以检查模块内容。或者,应用配置并使用提供商显示的错误。例如:

    terraform apply
    module.gcs_bucket.google_storage_bucket.bucket: Creating...
    ╷
    │ Error: googleapi: Error 409: Your previous request to create the named bucket succeeded and you already own it., conflict
    │
    │   with module.gcs_bucket.google_storage_bucket.bucket,
    

    通过使用上面的日志,您可以确定需要作为 module.gcs_bucket.google_storage_bucket.bucket 导入的资源的地址。

  • 如需确定资源 ID 格式,请参阅 google_storage_bucket 资源的提供商导入文档。在本例中,采用 project/name 格式。可以通过计划输出确定该名称。

    输出:

    module.gcs_bucket.google_storage_bucket.bucket will be created
    + resource "google_storage_bucket" "bucket" {
        + name                        = "my-bucket"
        + project                     = "sample-project"
        ...
      }
    

    对于上面的示例,资源 ID 为 sample-project/my-bucket

  • 使用资源地址和 ID 构建 import 语句,如下所示:

    terraform import module.gcs_bucket.google_storage_bucket.bucket sample-project/my-bucket
    

    输出:

    terraform import module.gcs_bucket.google_storage_bucket.bucket sample-project/my-bucket
    module.gcs_bucket.google_storage_bucket.bucket: Importing from ID "sample-project/my-bucket"...
    module.gcs_bucket.google_storage_bucket.bucket: Import prepared!
    Prepared google_storage_bucket for import
    module.gcs_bucket.google_storage_bucket.bucket: Refreshing state... [id=sample-project/my-bucket]
    Import successful!
    The resources that were imported are shown above. These resources are now in
    your Terraform state and will henceforth be managed by Terraform.
    

使用配置驱动的 import 块来批量导入资源

Terraform 1.5 版允许您将 import 块添加到 Terraform 配置。这样,您就可以在 plan 操作期间预览导入操作,并使用 apply 操作执行。

您也可以为导入的资源自动生成代码,而不必手动编写代码。

import 块采用两个参数:

  • id:要导入的云资源的提供商定义资源 ID。

    如需了解可接受的提供商定义的资源 ID,请参阅 Hashicorp 的 Google 提供商文档中该资源的导入部分。例如,projects/{project}/global/networks/{name} 是 VPC 网络的资源 ID,如 google_compute_network 参考页面中所示。

  • to:要创建的 Terraform 资源地址。通常采用 RESOURCE TYPE.NAME 格式。

以下是 Virtual Private Cloud 网络的 import 块的示例:

import {
  # Provider-defined resource ID of the cloud resource to be imported
  id = "projects/PROJECT_ID/global/networks/my-network"

  # Terraform resource address to be created
  to = google_compute_network.my_network
}

如果您已手动创建资源块,请执行 terraform plan 来预览导入操作。

如果您希望 Terraform 为您生成资源块,请使用 -generate-config-out 标志指定要生成配置的文件。

例如:

 terraform plan -generate-config-out=generated_resources.tf

查看生成的代码后,请运行 terraform apply 操作以将配置导入 Terraform 状态。

导入执行批量导出后创建的资源

借助批量导出功能,您可以将 Google Cloud 资源导出为 Terraform 配置,并导入这些资源的 Terraform 状态,以便在 Terraform 中管理您的部署。

准备工作

  • 准备 Cloud Shell。

    启动 Cloud Shell,并设置一个默认 Google Cloud 项目,您将在该项目中为已部署的资源生成 Terraform 代码。

    您只需为每个项目运行一次以下命令,即可在任何目录中运行它。

    export GOOGLE_CLOUD_PROJECT=PROJECT_ID

    如果您在 Terraform 配置文件中设置显式值,则环境变量会被替换。

  • 在 Cloud Shell 中,安装 Config Connector 的命令行界面 (CLI)。

    gcloud components install config-connector
    

    借助 Config Connector,您可以使用 Google Cloud 的 Terraform 批量导出工具。

    如果看到 ERROR: (gcloud.components.install) You cannot perform this action because the Google Cloud CLI component manager is disabled for this installation,请改为运行以下命令:

    sudo apt-get install google-cloud-sdk-config-connector
    
  • 启用 Cloud Asset API。

    gcloud services enable cloudasset.googleapis.com
    

为您的资源生成 Terraform 代码

  1. 创建一个目录以将项目配置输出到该目录(如果尚未创建该目录)。

    mkdir OUTPUT_DIRECTORY
    
  2. 运行 gcloud beta resource-config bulk-export 命令以将项目的整个配置输出到 OUTPUT_DIRECTORY 路径:

    gcloud beta resource-config bulk-export \
       --path=OUTPUT_DIRECTORY \
       --project=PROJECT_ID \
       --resource-format=terraform
    

通过生成的代码创建 Terraform 模块

运行 gcloud beta resource-config terraform generate-import 命令,指向输出目录中的内容:

gcloud beta resource-config terraform generate-import OUTPUT_DIRECTORY

此命令会生成 Terraform 模块和导入脚本:

  • gcloud-export-modules.tf 文件。此文件指向子资源中的所有模块。此文件的内容如下所示:

    provider "google" {
     project = "PROJECT_ID"
    }
    
    module "OUTPUT_DIRECTORY-projects-PROJECT_ID-ComputeFirewall" {
     source = "./OUTPUT_DIRECTORY/projects/PROJECT_ID/ComputeFirewall"
    }
    
    module "OUTPUT_DIRECTORY-projects-PROJECT_ID-ComputeBackendService-global" {
     source = "./OUTPUT_DIRECTORY/projects/PROJECT_ID/ComputeBackendService/global"
    }
    

    等等。

  • 名称类似 terraform_import_20220331-19-12-33.sh 的可执行 shell 脚本。该 Shell 脚本包含一系列 terraform import 命令:

    #!/bin/sh
    # Terraform Import Script generated by gcloud cli
    
    terraform import module.OUTPUT_DIRECTORY-projects-PROJECT_ID-ComputeFirewall.google_compute_firewall.allow_ssh projects/PROJECT_ID/global/firewalls/allow-ssh
    

    等等。

    terraform import 命令用于将 generate-import 命令创建的模块导入 Terraform 状态。

将模块导入 Terraform 状态

  1. 将它初始化:

    terraform init
    
  2. 运行脚本:

    ./terraform_import_20220331-19-12-33.sh
    

    输出:

    module.examples-projects-PROJECT_ID-ComputeInstance-us-central1-a.google_compute_instance.instance_1:
    Importing from ID
    "projects/PROJECT_ID/zones/us-central1-a/instances/instance-1"...
    module.examples-projects-PROJECT_ID-ComputeInstance-us-central1-a.google_compute_instance.instance_1:
    Import prepared!
     Prepared google_compute_instance for import
    module.examples-projects-PROJECT_ID-ComputeInstance-us-central1-a.google_compute_instance.instance_1:
    Refreshing state...
    [id=projects/PROJECT_ID/zones/us-central1-a/instances/instance-1]
    
    Import successful!
    
    The resources that were imported are shown above. These resources are now in
    your Terraform state and will henceforth be managed by Terraform.
    

后续步骤