从 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 state 和 replace-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 state 和 terraform 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.example 和 packet_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 更改上游资源。