3. 现有基础设施的发现与导入策略
把已经运行多年的云上资源纳入 Terraform 管理,难点从来不在“写一条 import 命令”,而在于先搞清楚“现在到底有什么、它们之间是什么关系、哪些该纳管、纳管后配置长什么样”。如果跳过发现阶段直接 import,往往会得到一份与真实资源严重脱节的 state,后续 plan 出现大量意外 diff,反而增加风险。因此本节按“发现 → 生成配置 → 导入 → 校验”的顺序展开,重点讲清每一步的实际做法与判断依据。
一、发现阶段:先建立资源清单,而不是先写代码
发现的目标是得到一份可核对的资源台账,至少包含:资源类型、资源 ID、所属区域/可用区、名称标签、创建时间、依赖关系(如 ECS 属于哪个 VPC/子网、EIP 绑定了哪台实例)。获取方式主要有三类:
- 云厂商 CLI/SDK 扫描:例如阿里云
aliyun ecs DescribeInstances、AWSaws ec2 describe-instances,可按 region 与 tag 过滤,输出 JSON 后转换为清单。 - 资源中心/配置审计服务:如阿里云配置审计、AWS Config、Azure Resource Graph,能跨区域、跨产品聚合,适合做全量盘点。
- 第三方扫描工具:如
terraformer、former2、terracognita,可直接把扫描结果转成 HCL 与 import 脚本。
扫描时建议先按“环境 + 业务系统”打标签过滤,避免把测试、临时、已废弃资源一并纳入。下面是一段以标签筛选并导出实例清单的示例(示例参数,非实测结果):
# 按标签筛选生产环境 ECS,输出精简清单
aliyun ecs DescribeInstances \
--RegionId cn-hangzhou \
--Tag.1.Key Env --Tag.1.Value prod \
--PageSize 100 \
| jq -r '.Instances.Instance[] | [.InstanceId, .InstanceName, .Status, .VpcAttributes.VpcId] | @tsv'
输出形如 i-bp1xxxx order-api Running vpc-bp1yyyy,即可作为后续导入的输入清单。判断依据很直接:状态为 Running 且带 prod 标签的才进入纳管范围;Stopped 超过 30 天或标签缺失的,先标记为“待确认”,不急于导入。
二、生成配置:让 HCL 与真实资源对齐
terraform import 只把资源写入 state,不会生成 .tf 配置。因此导入前必须先有配置骨架,否则 import 后 plan 会提示“资源已存在但配置缺失”。生成配置有三种常见路径:
- 工具自动生成:terraformer 可按资源类型批量生成 HCL 与 import 脚本,适合资源量大、结构规整的场景。
- 手工编写 + 占位:先写最小可用配置(仅必填参数),import 后再用
terraform plan的 diff 反推缺失字段。 - 混合方式:自动生成主体,人工修正命名、变量抽取与模块划分,这是生产环境最稳妥的做法。
无论哪种方式,生成后都要做一次“配置与真实资源对齐”检查:把扫描清单中的关键属性(实例规格、镜像 ID、安全组、磁盘类型)与 HCL 逐项比对。若不一致,import 后第一次 plan 就会显示大量变更,说明配置没有反映真实状态。
三、导入:单资源与批量脚本
单资源导入最直接:先在 .tf 中写好资源块,再执行 import。以阿里云 ECS 为例:
resource "alicloud_instance" "order_api" {
instance_name = "order-api"
instance_type = "ecs.c6.large"
image_id = "centos_7_9_x64_20G_alibase_20220828.vhd"
security_groups = ["sg-bp1zzzz"]
vswitch_id = "vsw-bp1aaaa"
availability_zone = "cn-hangzhou-h"
}
terraform import alicloud_instance.order_api i-bp1xxxx
资源数量多时,手工逐条 import 不现实。可基于扫描清单生成批量脚本,例如把清单转成 import.sh:
#!/usr/bin/env bash
set -euo pipefail
while IFS=$'\t' read -r id name; do
addr="alicloud_instance.${name//-/_}"
echo "importing ${addr} <= ${id}"
terraform import "${addr}" "${id}"
done < instances.tsv
批量导入时要注意两点:一是 state 的并发写入,建议串行执行或使用远程后端加锁;二是导入顺序,先导入 VPC、子网、安全组等被依赖资源,再导入 ECS、RDS 等上层资源,避免引用地址找不到。
四、校验:用 plan 空 diff 作为纳管完成的判据
导入完成后,执行 terraform plan。如果输出 No changes. Your infrastructure matches the configuration.,说明配置与真实资源一致,纳管成功。若出现 diff,不要直接 apply,而应逐项核对:
- 属性缺失:HCL 中未声明的字段被云上默认值填充,需补全或显式忽略。
- 属性不一致:如磁盘类型、带宽峰值与真实值不同,需修正 HCL。
- 只读字段:部分属性由云平台生成,应通过
lifecycle { ignore_changes = [...] }处理。
最后用 terraform state list 核对资源数量,并与发现阶段的台账逐项比对。建议把“台账数量 = state 数量 = plan 无变更”作为纳管完成的验收标准,形成可复查的闭环。