如何修复Terraform state file 中丢失的资源

有时天灾人祸, 当本人尝试利用terraform 创建1个vm时, 当执行到最后一步时出现了问题

如何修复Terraform state file 中丢失的资源_第1张图片
从日志看出, 其实资源能正确创建, 但是同步state file时出现了问题, 这个项目的state file是存放在GCS /bucket 上的。
backend.tf

terraform {
  backend "gcs" {
    bucket  = "jason-hsbc"
    prefix  = "terraform/state"
  }
}

root cause? 日志上写的是网络问题, 估计是踮脚的东西突然塌了几秒

先试下rerun, 其实我已经知道rerun注定失败, 因为这时, gcs 上的state file 并没有这个vm资源, 但是这个vm资源其实已经被创建。
所以当下次执行同样的terraform version时, terraform 还是会尝试创建这个vm资源, 但是其id 已经被上次创建的vm占用. 失败!

如何修复Terraform state file 中丢失的资源_第2张图片




解决方法1, 手动删除这个vm, 再重新执行terraform apply

这个方法肯定是work的, 相当有效。
但是过于暴力, 而且在生产环境不一定让开发人员这么做。




解决方法2, 手动更新 state file

具体步骤是先把state file 从gcs download 到本地, 然后把这个vm的资源加上去, 再上传回gcs
这个 方案 又过于技术了, 而且风险更高, 万一改错了别的地方…

有没有自动同步state file的方法呢?
有!




解决方法3, terraform refresh 命令

先看看 terraform refresh的解释:

1.更新状态信息:terraform refresh 从基础设施中获取当前的资源状态,并将这些信息更新到 Terraform 的状态文件中。这样,Terraform 就能了解实际基础设施的当前状态,以便在后续的操作中进行准确的计划和变更。

2.检测变更:通过与当前基础设施进行比较,terraform refresh 可以检测到已经发生的变更。它会比较基础设施中的资源属性和 Terraform 状态文件中的资源属性,并标记出任何不匹配的地方。

3.同步状态:如果资源的属性在基础设施中发生了变化,terraform refresh 将更新 Terraform 状态文件中相应资源的属性信息。这样,在后续的计划和应用变更过程中,Terraform 将使用最新的属性信息来确保与基础设施保持一致。

4.识别已删除资源:terraform refresh 还可以识别基础设施中已被删除的资源。它会在 Terraform 的状态文件中标记这些资源,并在后续的计划和应用步骤中通知您这些资源已被删除,以便您可以相应地处理。

上面的解释来自于 chatgpt
通俗地讲

  1. 可以更新terraform 脚本中定义的资源的属性更新, 例如vm1 被加了1个subnet, 这个change 可以更新回 terraform state.
  2. 检测上面那种类型的变更, 也就是只检测不修改 : terraform apply -refresh-only
  3. 跟第一点一样
  4. 如果某个资源实际上被其他手动在云上删除, 这个命令可以识别, 并把状态更新入state file(实际上也是资源属性更新的一种)

但是!
不支持本文开头介绍的情况 – terraform refresh 不支持 资源已经被创建 而没有写入state file的case




解决方法4, terraform import 命令

看来正主出来了

语法: terraform import 《resource tf address》《resource instance ID》

出现了两个变量, 下面是解释

resource tf address

就是 这个资源的terraform 地址啦
我们可以用 terraform state list 来查看state file 已经注册的所有resource 的 terraform 地址

[gateman@manjaro-x13 Terraform-GCP-config]$ terraform state list
module.artifact_registry.google_artifact_registry_repository.repository
module.artifact_registry.google_project_service.artifact_registry
module.bigquery.google_project_service.bq_api
module.bucket.google_storage_bucket.bucket-jason-hsbc
module.bucket.google_storage_bucket.bucket-jason-hsbc-dataflow
module.network.google_compute_firewall.tf-vpc0-firewall
module.network.google_compute_firewall.tf-vpc1-firewall
module.network.google_compute_network.tf-vpc0
module.network.google_compute_network.tf-vpc1
module.network.google_compute_router.tf-vpc0-nat-router
module.network.google_compute_router_nat.tf-vpc0-cloud-nat
module.network.google_compute_subnetwork.tf-vpc0-subnet0
module.network.google_compute_subnetwork.tf-vpc0-subnet1
module.network.google_compute_subnetwork.tf-vpc1-subnet0
module.pubsub.google_pubsub_subscription.subscription_a1
module.pubsub.google_pubsub_subscription.subscription_a2
module.pubsub.google_pubsub_topic.topic_a
module.vm.google_compute_instance.k8s-master
module.vm.google_compute_instance.k8s-node0
module.vm.google_compute_instance.k8s-node1
module.vm.google_compute_instance.tf-vpc0-subnet0-vm0
module.vm.google_compute_instance.tf-vpc0-subnet0-vm1
module.vm.google_compute_instance.tf-vpc0-subnet0-vpc1-subnet0-vm0
module.vm.google_compute_instance.tf-vpc0-subnet1-vm0
module.vm.google_compute_instance.tf-vpc1-subnet0-vm0
module.vm.google_compute_instance_from_template.tf-vpc0-subnet0-vm20
module.vm.google_compute_instance_from_template.tf-vpc0-subnet0-vm21
module.vm.google_compute_instance_from_template.tf-vpc0-subnet1-vm1
module.vm.google_compute_instance_template.vm-template-vpc0-subnet0-e2-small-tomcat
module.bigquery.module.bq.google_bigquery_dataset.dataset1
module.bigquery.module.bq.google_bigquery_table.table1
[gateman@manjaro-x13 Terraform-GCP-config]$ 
resource instance ID

对应的就是该资源在GCP 上创建的实例ID
我们可以用 terraform show 查看全部
或者 terraform state show 《resource tf address》 来查看某个资源的instance id

gateman@manjaro-x13 Terraform-GCP-config]$ terraform state show module.vm.google_compute_instance_from_template.tf-vpc0-subnet0-vm21
# module.vm.google_compute_instance_from_template.tf-vpc0-subnet0-vm21:
resource "google_compute_instance_from_template" "tf-vpc0-subnet0-vm21" {
    attached_disk            = []
    can_ip_forward           = false
    cpu_platform             = "Unknown CPU Platform"
    current_status           = "TERMINATED"
    deletion_protection      = false
    enable_display           = false
    guest_accelerator        = []
    id                       = "projects/jason-hsbc/zones/europe-west2-c/instances/tf-vpc0-subnet0-vm21"
    instance_id              = "442217657071685871"
    label_fingerprint        = "42WmSpB8rSM="
    labels                   = {}
    machine_type             = "e2-small"
    metadata                 = {}
    metadata_fingerprint     = "t09GrcHA4z0="
    name                     = "tf-vpc0-subnet0-vm21"
    project                  = "jason-hsbc"
    resource_policies        = []
    scratch_disk             = []
    self_link                = "https://www.googleapis.com/compute/v1/projects/jason-hsbc/zones/europe-west2-c/instances/tf-vpc0-subnet0-vm21"
    service_account          = [
        {
            email  = "[email protected]"
            scopes = [
                "https://www.googleapis.com/auth/cloud-platform",
            ]
        },
    ]
    source_instance_template = "https://www.googleapis.com/compute/v1/projects/jason-hsbc/global/instanceTemplates/vm-template-vpc0-subnet0-e2-small-tomcat?uniqueId=7261720283884147418"
    tags                     = []
    tags_fingerprint         = "42WmSpB8rSM="
    zone                     = "europe-west2-c"

    boot_disk {
        auto_delete = true
        device_name = "persistent-disk-0"
        mode        = "READ_WRITE"
        source      = "https://www.googleapis.com/compute/v1/projects/jason-hsbc/zones/europe-west2-c/disks/tf-vpc0-subnet0-vm21"

        initialize_params {
            image                 = "https://www.googleapis.com/compute/v1/projects/jason-hsbc/global/images/e2-small-tomcat-image"
            labels                = {}
            resource_manager_tags = {}
            size                  = 20
            type                  = "pd-standard"
        }
    }

    network_interface {
        access_config      = []
        alias_ip_range     = []
        name               = "nic0"
        network            = "https://www.googleapis.com/compute/v1/projects/jason-hsbc/global/networks/tf-vpc0"
        network_ip         = "192.168.0.34"
        queue_count        = 0
        stack_type         = "IPV4_ONLY"
        subnetwork         = "https://www.googleapis.com/compute/v1/projects/jason-hsbc/regions/europe-west2/subnetworks/tf-vpc0-subnet0"
        subnetwork_project = "jason-hsbc"
    }

    scheduling {
        automatic_restart           = false
        instance_termination_action = "STOP"
        min_node_cpus               = 0
        on_host_maintenance         = "TERMINATE"
        preemptible                 = true
        provisioning_model          = "SPOT"
    }

    shielded_instance_config {
        enable_integrity_monitoring = true
        enable_secure_boot          = false
        enable_vtpm                 = true
    }
}
[gateman@manjaro-x13 

上面的 projects/jason-hsbc/zones/europe-west2-c/instances/tf-vpc0-subnet0-vm21 就是instance id了

所以为了解决本文的问题
我们应该执行
terraform import module.vm.google_compute_instance_from_template.tf-vpc0-subnet1-vm1 projects/jason-hsbc/zones/europe-west2-c/instances/tf-vpc0-subnet1-vm1

但是很不幸, 出现了下面的错误
Error: resource google_compute_instance_from_template doesn’t support import

google_compute_instance_from_template 类型的vm不支持 terraform import!

所以本文的问题还是用方法1 解决的。

但是我相信一些其他类型的资源, 例如bucket, BQ table等可以用这个方法解决state file同步问题。

你可能感兴趣的:(terraform,gcp,google,cloud,terraform,googlecloud,gcp)