将 DNS 记录自动切换到新图像

Auto-switching DNS records to new image

我们目前在 GCP 上使用单个计算引擎,我们希望在对其进行更改时开始试验一些 HashCorp 套件。计划是使用 Packer 创建新映像,然后启动这些映像,然后在启动后将 DNS 切换到新机器。

我们没有使用 Terraform 的经验(除了阅读书籍),所以有没有一种方法可以使用 Terraform 在 Google 中自动切换 DNS?

我找到了 Terraform DNS Provider and google_dns_managed_zone,但我不确定这两者如何关联或是否关联。我们也不是 GCP 的专家,所以我们不知道从控制台的哪里开始执行此操作。

google_dns_record_set docs example 提供了一个很好的示例,说明如何附加创建指向实例 IP 地址的 A 记录:

resource "google_dns_record_set" "frontend" {
  name = "frontend.${google_dns_managed_zone.prod.dns_name}"
  type = "A"
  ttl  = 300

  managed_zone = "${google_dns_managed_zone.prod.name}"

  rrdatas = ["${google_compute_instance.frontend.network_interface.0.access_config.0.assigned_nat_ip}"]
}

resource "google_compute_instance" "frontend" {
  name         = "frontend"
  machine_type = "g1-small"
  zone         = "us-central1-b"

  boot_disk {
    initialize_params {
      image = "debian-cloud/debian-8"
    }
  }

  network_interface {
    network       = "default"
    access_config = {}
  }
}

resource "google_dns_managed_zone" "prod" {
  name     = "prod-zone"
  dns_name = "prod.mydomain.com."
}

虽然这将处理创建实例并向其附加记录,但它依赖于 hard-coded 图像名称(要求您在使用 Packer 创建新图像时更改 Terraform 配置) Terraform 的默认生命周期规则意味着 when the image does change it will force a new instance to be created,先销毁旧实例,然后用新实例替换它。

理想情况下,您可能希望让 Packer 在一个系列中发布新图像,并让 Terraform 在下一次应用时自动使用该系列中的最新图像,而不更改配置。如果您想避免停机,您可能还想强制 Terraform 在翻转 DNS 记录然后销毁旧实例之前创建一个新实例。

谢天谢地,这一切都很容易做到!

使用 Packer 和 Terraform 自动发布和获取新镜像

使用 Packer googlecompute builder you can publish images as part of an image_family:

{
  "builders": [
    {
      "type": "googlecompute",
      "account_file": "account.json",
      "project_id": "my project",
      "source_image_family": "debian-cloud/debian-8",
      "image_family": "my-image-family",
      "ssh_username": "packer",
      "zone": "us-central1-a"
    }
  ],
  "provisioners": [
    {
      "type": "ansible",
      "playbook_file": "./path/to/playbook.yml"
    }
  ]
}

然后我们可以使用 Terraform 的 google_compute_image data source to find the most recent published image in an image family and make the google_compute_instance resource 在下一个 Terraform 操作(plan/apply 等)中自动选择它:

data "google_compute_image" "my_image" {
  family = "my-image-family"
}

resource "google_compute_instance" "frontend" {
  # ...

  boot_disk {
    initialize_params {
      image = "${data.google_compute_image.my_image.self_link}"
    }
  }

  # ...
}

在销毁旧实例之前创建新实例

既然我们已经让 Terraform 自动获取对已发布图像的更改,我们还需要确保这不会导致我们因 Terraform 替换实例而中断。

为此,我们只需更改 google_compute_instance 资源的默认 lifecycle 模型,方法是指定:

resource "google_compute_instance" "frontend" {
  # ...

  lifecycle {
    create_before_destroy = true
  }
}

Terraform 然后会在删除旧实例之前尝试创建新实例,因此依赖关系图来自:

destroy old instance -> create new instance -> change DNS record

至:

create new instance -> change DNS record -> destroy old instance

请注意,以上所有内容均未经测试,来自不使用 GCE 但在 AWS 中使用 Packer 和 Terraform 做类似事情的人。如果我对 GCE 的任何假设有误或代码不能正常工作,欢迎修改!