【问题标题】:Terraform wants to replace Google compute engine if its start/stop scheduler is modified如果修改了启动/停止调度程序,Terraform 想要替换 Google 计算引擎
【发布时间】:2021-10-29 08:05:11
【问题描述】:

首先,令我惊讶的是,我在 Google 上发现很少有资源提及 Terraform 的这个问题。 这是优化云实例成本的一项基本功能,所以我可能遗漏了一些事情,感谢您的提示和想法!

我想以编程方式创建一个实例并每天管理它的启动和停止。 资源“google_compute_resource_policy”似乎符合我的用例。但是,当我更改停止或开始时间时,Terraform 计划销毁并重新创建实例……这是我绝对不想要的!

资源“google_compute_resource_policy”通过参数resource_policies 附加到实例,其中指定:“修改此列表将导致实例重新创建。”

我不明白为什么 Terraform 对这个简单的更新处理得如此糟糕。确实不可能更新调度程序,但完全可以手动将其从实例中分离,然后在使用新的停止/启动调度重新创建它之前将其销毁并再次附加到实例。

是否有不通过空资源运行 gcloud 脚本来执行这些步骤的解决方法?

我试图在我的实例的“resource_policies”参数上添加一个“ignore_changes”生命周期,Terraform 不再想销毁我的实例,但它给了我以下错误:

Error when reading or editing ResourcePolicy: googleapi: Error 400: The resource_policy resource 'projects/my-project-id/regions/europe-west1/resourcePolicies/my-instance-schedule' is already being used by 'projects/my-project-id/zones/europe-west1-b/instances/my-instance', resourceInUseByAnotherResource"

这是我的 Terraform 代码

resource "google_compute_resource_policy" "instance_schedule" {
  name = "my-instance-schedule"
  region = var.region
  description = "Start and stop instance"

  instance_schedule_policy {
    vm_start_schedule {
      schedule = var.vm_start_schedule
    }
    vm_stop_schedule {
      schedule = var.vm_stop_schedule
    }
    time_zone = "Europe/Paris"
  }
}

resource "google_compute_instance" "my-instance" {

  // ******** This is my attempted workaround ********
  lifecycle {
    ignore_changes = [resource_policies]
  }

  name = "my-instance"
  machine_type = var.machine_type
  zone = "${var.region}-b"

  allow_stopping_for_update = true

  resource_policies = [
    google_compute_resource_policy.instance_schedule.id
  ]

  boot_disk {
    device_name = local.ref_name
    initialize_params {
      image = var.boot_disk_image
      type = var.disk_type
      size = var.disk_size
    }
  }

  network_interface {
    network = data.google_compute_network.default.name
    access_config {
      nat_ip = google_compute_address.static.address
    }
  }
}

如果有用,这里是 terraform apply 返回的内容

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  - destroy
-/+ destroy and then create replacement

Terraform will perform the following actions:

  # google_compute_resource_policy.instance_schedule must be replaced
-/+ resource "google_compute_resource_policy" "instance_schedule" {
      ~ id          = "projects/my-project-id/regions/europe-west1/resourcePolicies/my-instance-schedule" -> (known after apply)
        name        = "my-instance-schedule"
      ~ project     = "my-project-id" -> (known after apply)
      ~ region      = "https://www.googleapis.com/compute/v1/projects/my-project-id/regions/europe-west1" -> "europe-west1"
      ~ self_link   = "https://www.googleapis.com/compute/v1/projects/my-project-id/regions/europe-west1/resourcePolicies/my-instance-schedule" -> (known after apply)
        # (1 unchanged attribute hidden)

      ~ instance_schedule_policy {
            # (1 unchanged attribute hidden)

          ~ vm_start_schedule {
              ~ schedule = "0 9 * * *" -> "0 8 * * *" # forces replacement
            }

            # (1 unchanged block hidden)
        }
    }

Plan: 1 to add, 0 to change, 1 to destroy.

Do you want to perform these actions in workspace "prd"?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

google_compute_resource_policy.instance_schedule: Destroying... [id=projects/my-project-id/regions/europe-west1/resourcePolicies/my-instance-schedule]

Error: Error when reading or editing ResourcePolicy: googleapi: Error 400: The resource_policy resource 'projects/my-project-id/regions/europe-west1/resourcePolicies/my-instance-schedule' is already being used by 'projects/my-project-id/zones/europe-west1-b/instances/my-instance', resourceInUseByAnotherResource

注意:我正在使用 Terraform 0.14.7,我正在使用 google 提供程序版本 3.76.0

【问题讨论】:

    标签: google-cloud-platform terraform cloud google-compute-engine


    【解决方案1】:

    GCP 中的实例可以通过 google_compute_instance 使用参数 desired_status 来关闭而不破坏它,请记住,如果您是第一次创建实例,则此参数需要启用“RUNNING” .该模块可以如下使用。

    resource "google_compute_instance" "default" {
      name         = "test"
      machine_type = "f1-micro"
      zone         = "us-west1-a"
      desired_status = "RUNNING"
    }
    

    如果您需要先停止 VM,然后开始使用depends_on 创建dependency in terraform,您也可以修改“main.tf”文件。

    正如您在以下评论中看到的,将创建服务帐户,但将分配密钥,直到第一句完成。

    resource "google_service_account" "service_account" { 
       account_id = "terraform-test" 
       display_name = "Service Account"
    }
    
    resource "google_service_account_key" "mykey" {
      service_account_id = google_service_account.service_account.id 
      public_key_type = "TYPE_X509_PEM_FILE" 
      depends_on = [google_service_account.service_account]
    }
    

    如果第一个组件已经存在,则 terraform 仅部署依赖项。

    【讨论】:

    • 感谢您的提议@Nadia Espinosa 但是,这似乎并不能解决我的问题。当修改“google_compute_resource_policy”资源时,在“RUNNING”值上添加“desired_status”参数确实会生成相同的实例行为(其销毁)
    【解决方案2】:

    我在使用快照策略时遇到了同样的问题。

    我使用标志输入变量和计数来控制资源策略的创建。我第一次使用标志为“真”创建策略资源。当我想更改计划时间时,我将标志更改为“假”并应用计划。这将分离资源。

    然后我再次将标志设为“真”,并以新的时间应用该计划。

    这对我来说适用于快照策略。希望它也能解决你的问题。

    【讨论】:

      猜你喜欢
      • 2018-11-01
      • 2014-11-20
      • 2015-08-06
      • 1970-01-01
      • 2016-04-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-11
      相关资源
      最近更新 更多