跳至内容

从 packethost/packet 迁移到 equinix/equinix

Equinix Metal(原名 Packet)已完全集成到 Platform Equinix 中,因此 Terraform 提供程序也随之更改。当前,Platform Equinix 平台上可使用 Terraform 管理的各种服务的提供程序是 (terraform-provider-equinix, provider equinix/equinix)。

如果您一直使用 terraform-provider-packet,并且想要使用更新的提供程序版本来管理 Equinix Metal 中的资源,则需要更改 HCL 文件中的引用。您可以直接更改资源名称,例如从 packet_device 更改为 equinix_metal_device。这样做应该可以,但会导致 packet_device 被销毁,并创建新的 equinix_metal_device。重新创建资源可能并不理想,本指南将介绍如何在不重新创建资源的情况下迁移到 equinix_metal_ 资源。

在开始迁移 Terraform 模板之前,请先升级。

  • 将 packethost/packet provider 更新到最新版本 (3.2.1)
  • Terraform 版本至少要达到 v0.13

使用 replace-provider 和 sed 实现快速迁移

与 Terraform HCL 模板类似,Terraform 状态文件也是一个包含资源名称及其属性的结构化文本文件。我们可以尝试将迁移作为文本替换任务,即尽可能地将 packet_ 替换为 equinix_metal_,并修复提供程序源引用。

在执行此操作之前,最好备份整个 Terraform 目录。

假设我们的基础设施是根据以下模板创建的:

terraform {
required_providers {
packet = {
source = "packethost/packet"
}
}
}

resource "packet_project" "example" {
name = "example"
}

resource "packet_vlan" "example" {
project_id = packet_project.example.id
facility = "sv15"
description = "example"
}

我们可以先在 Terraform 状态文件 (terraform.tfstate) 中使用子命令 terraform statereplace-provider 来更改提供程序:

terraform state replace-provider packethost/packet equinix/equinix

然后,我们替换 HCL 模板中的提供商引用。对所有包含该引用的文件执行此操作:

sed -i 's|packethost/packet|equinix/equinix|g' main.tf

然后我们只需将 Terraform HCL 文件中的所有字符串 packet_ 替换为 equinix_metal_ 即可。

sed -i 's/packet_/equinix_metal_/g' main.tf

这样做有点危险,所以之后请检查你的 git diff。它应该替换所有 packet_ 前缀以及 required_providers 块中的键。

然后,在 Terraform 状态文件中将 packet_ 替换为 equinix_metal_

sed -i 's/packet_/equinix_metal_/g' terraform.tfstate

示例模板现在看起来会是这样:

terraform {
required_providers {
equinix = {
source = "equinix/equinix"
}
}
}

resource "equinix_metal_project" "example" {
name = "example"
}

resource "equinix_metal_vlan" "example" {
project_id = equinix_metal_project.example.id
facility = "sv15"
description = "example"
}

接下来,我们需要运行 terraform init 来安装 equinix/equinix 提供程序。安装完成后,我们的模板应该与 Terraform 状态以及 Equinix Metal 中的上游资源保持一致。您可以通过运行 terraform plan 来验证结果。

如果计划不为空,则表示某些资源无法直接从上游读取,或者您的 packethost/packet 提供程序版本与当前 equinix/equinix 提供程序版本之间的属性发生了变化。

一次迁移一个资源

我们可以使用 terraform stateterraform import 来实现过渡,而不会破坏现有资源。

现有基础设施

我们假设已使用提供商 packethost/packet 创建了基础设施,并预留了设备和 IP 地址。硬件兼容性列表 (HCL) 如下所示:

terraform {
required_providers {
packet = {
source = "packethost/packet"
version = "3.2.1"
}
}
}

resource "packet_reserved_ip_block" "example" {
project_id = local.project_id
facility = "sv15"
quantity = 2
}

resource "packet_device" "example" {
project_id = local.project_id
facilities = ["sv15"]
plan = "c3.medium.x86"
operating_system = "ubuntu_24_04"
hostname = "test"
billing_cycle = "hourly"

ip_address {
type = "public_ipv4"
cidr = 31
reservation_ids = [packet_reserved_ip_block.example.id]
}

ip_address {
type = "private_ipv4"
}
}

资源 UUID

为了迁移到提供商 equinix/equinix,我们需要找到所有要迁移的资源的 UUID。在本例中,这些资源是 packet_reserved_ip_block.examplepacket_device.example。我们可以使用 terraform state 来查找这些 UUID。

对于保留的 IP 地址块:

$ terraform state show packet_reserved_ip_block.example

# packet_reserved_ip_block.example:
resource "packet_reserved_ip_block" "example" {
[...]
id = "e689072f-aa6e-4d51-8e37-c2fbe18b4ff0"
[...]
}

对于该设备:

$ terraform state show packet_device.example

# packet_device.example
resource "packet_device" "example" {
[...]
id = "8eb3bc10-0e1a-476a-aec2-6dc699df9c1c"
[...]

已迁移模板

一旦我们找到要迁移的资源的 UUID,就需要在 HCL 模板中进行如下更改:

  • required_providers 块需要 equinix/equinix
  • 来自提供者 equinix/equinix 的资源名称与相应资源的名称对应:sed 's/packet_/equinix_metal_'
  • packet_ 资源到 equinix_metal_ 资源的所有引用

修改后的模板将如下所示:

terraform {
required_providers {
equinix = {
source = "equinix/equinix"
}
}
}

resource "equinix_metal_reserved_ip_block" "example" {
project_id = local.project_id
facility = "sv15"
quantity = 2
}

resource "equinix_metal_device" "example" {
project_id = local.project_id
facilities = ["sv15"]
plan = "c3.medium.x86"
operating_system = "ubuntu_24_04"
hostname = "test"
billing_cycle = "hourly"

ip_address {
type = "public_ipv4"
cidr = 31
reservation_ids = [equinix_metal_reserved_ip_block.example.id]
}

ip_address {
type = "private_ipv4"
}
}

迁移 Terraform 状态

一旦我们相应地更改了模板,我们就可以从 Terraform 状态中删除旧的 packet_ 资源,并通过它们的 UUID 将新的资源作为 equinix_metal_ 资源导入。

从之前的状态检查可知,packet_device.example 的 UUID 为 8eb3bc10-0e1a-476a-aec2-6dc699df9c1c,packet_reserved_ip_block.example 的 UUID 为 e689072f-aa6e-4d51-8e37-c2fbe18b4ff0。

在 Terraform 状态和导入命令中,我们使用资源类型和名称,用点号分隔:

terraform state rm packet_reserved_ip_block.example
terraform import equinix_metal_reserved_ip_block.example e689072f-aa6e-4d51-8e37-c2fbe18b4ff0
terraform state rm packet_device.example
terraform import equinix_metal_device.example 8eb3bc10-0e1a-476a-aec2-6dc699df9c1c

接下来,我们需要运行 terraform init 来安装 equinix/equinix 提供程序。之后,我们的模板应该与 Terraform 状态以及 Equinix Metal 中的上游资源保持一致。我们可以通过运行 terraform plan 来验证迁移,它应该显示基础架构已更新。

解决迁移问题

当我们运行 terraform plan 来验证迁移是否成功时,Terraform 可能会发出警告,指出模板中的某些资源属性与导入的状态不一致。这是因为并非所有资源属性都能计算得出,例如,packet_device 中的 ip_address 代码块是用户自定义的,因此与下载的导入状态相比,差异值将不为空。

如果是 ip_address,则后续的 terraform apply 将更新本地状态而不更改上游资源,但如果某个属性导致上游更新,则需要手动解决,要么更改模板,要么让 Terraform 更改上游资源。

此页面有帮助吗?