如何使用 Terraform 导入现有基础设施资源

目录
我叫寺冈,是一名基础设施工程师。
你是否曾经想过,“我想用 Terraform 来管理我现有的基础设施配置?”
Terraform 提供了一些命令来实现这一点,我将在本文中介绍这些命令。
我事先创建了一个 VPC,但没有使用 Terraform。

这次,我们将把它导入到 Terraform 中。
目录结构
$ tree . ├── README.md ├── provider.tf ├── terraform.tfstate ├── variables.tf └── vpc.tf 0 个目录,5 个文件
描述提供者和变量
导入之前,我们需要先编写提供程序和变量,因为这是最低要求。
provider.tf
provider "aws" { access_key = var.access_key secret_key = var.secret_key region = var.region assume_role { role_arn = var.role_arn } }
variables.tf
#################### # 提供商 ################### 变量 "access_key" { description = "AWS 访问密钥" } 变量 "secret_key" { description = "AWS 秘密密钥" } 变量 "role_arn" { description = "AWS 角色 ARN" } 变量 "region" { default = "ap-northeast-1" }
将您的 AWS 访问密钥存储在环境变量中。
$ export TF_VAR_access_key=XXXXXXXXXXXXXXXXXX $ export TF_VAR_secret_key=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX $ export TF_VAR_role_arn=arn:aws:iam::XXXXXXXXXXXX:role/XXXXXXXXXXXXXXXXXXX
执行计划
我们来运行一下计划。
由于我们还没有导入任何内容,因此执行将以“无更改”结束。
$ terraform plan 在执行计划之前,正在刷新内存中的 Terraform 状态…… 刷新后的状态将用于计算此计划,但不会持久化到本地或远程状态存储。 --------------------------------------------------------------------------- 无更改。基础架构已是最新状态。这意味着 Terraform 未检测到您的配置与实际存在的物理资源之间存在任何差异。因此,无需执行任何操作。.
运行导入
要使用 Terraform 导入现有资源,请运行“terraform import”命令。
命令格式在 Terraform 手册(※1),请参考手册并运行以下命令。
$ terraform import aws_vpc.vpc vpc-09a9f1827bfd851f4 错误:资源地址“aws_vpc.vpc”在配置中不存在。导入此资源之前,请在根模块中创建其配置。例如:resource "aws_vpc" "vpc" { # (资源参数) }
发生错误。
导入时,您需要指定资源类型和名称,例如“aws_vpc.vpc”,现有资源的信息将被导入到此处指定的 tf 文件中的资源中。
因此,您需要预先在 tf 文件中写入相应的资源。
描述 VPC 资源
我将这样写:
vpc.tf
#################### # VPC ################### resource "aws_vpc" "vpc" { cidr_block = "10.0.0.0/16" enable_dns_support = true enable_dns_hostnames = true tags = { Name = "vpc-tfstate-test" } }
再次运行导入程序
我们再试一次。
这次导入很顺利。
$ terraform import aws_vpc.vpc vpc-09a9f1827bfd851f4 aws_vpc.vpc: 正在从 ID "vpc-09a9f1827bfd851f4" 导入... aws_vpc.vpc: 导入已准备就绪!已准备好 aws_vpc 以进行导入 aws_vpc.vpc: 正在刷新状态... [id=vpc-09a9f1827bfd851f4] 导入成功!已导入的资源如上所示。这些资源现在已添加到您的 Terraform 状态中,并将由 Terraform 进行管理。.
这条 Terraform 导入命令的作用是什么?
运行该命令后,你会看到创建了一个名为“terraform.tfstate”的文件。
terraform.tfstate
{ "version": 4, "terraform_version": "0.12.24", "serial": 1, "lineage": "c0359eb1-d905-e252-2d8d-525710adddb1", "outputs": {}, "resources": [ { "mode": "managed", "type": "aws_vpc", "name": "vpc", "provider": "provider.aws", "instances": [ { "schema_version": 1, "attributes": { "arn": "arn:aws:ec2:ap-northeast-1:485076298277:vpc/vpc-09a9f1827bfd851f4", "assign_generated_ipv6_cidr_block": false, "cidr_block": "10.0.0.0/16", "default_network_acl_id": "acl-0cd8abfed52e0e951", "default_route_table_id": "rtb-08c13269b1b26c9b8", "default_security_group_id": "sg-007ef29e563b6f9c7", "dhcp_options_id": "dopt-6c0f430b", "enable_classiclink": false, "enable_classiclink_dns_support": false, "enable_dns_hostnames": true, "enabledns_support": true, "id": "vpc-09a9f1827bfd851f4", "instance_tenancy": "default", "ipv6_association_id": "", "ipv6_cidr_block": "", "main_route_table_id": "rtb-08c13269b1b26c9b8", "owner_id": "485076298277", "tags": { "Name": "vpc-tfstate-test" } }, "private": "eyJzY2hlbWFfdmVyc2lvbiI6IjEifQ==" } ] } ] }
查看内容,你会发现刚刚导入的资源信息已保存。
Terraform 执行时,会自动判断是要创建、修改还是删除资源,并据此进行相应的操作。这一判断基于运行时加载的 tf 文件与 tfstate 文件中写入的内容之间的差异。
换句话说,为了管理 Terraform 中指定的现有资源,你需要更改 tfstate 的内容,而 terraform import 命令会读取指定的现有资源的信息并将其添加到 tfstate 中。
再次运行计划
现在我们已经运行了 terraform import 命令,让我们再运行一次 plan 命令。
$ terraform plan 在执行计划之前,正在刷新内存中的 Terraform 状态... 刷新后的状态将用于计算此计划,但不会持久化到本地或远程状态存储。 aws_vpc.vpc:正在刷新状态... [id=vpc-09a9f1827bfd851f4] --------------------------------------------------------------------------- 无更改。基础设施已是最新状态。这意味着 Terraform 未检测到您的配置与实际存在的物理资源之间存在任何差异。因此,无需执行任何操作。.
aws_vpc.vpc 已作为资源加载到 Terraform 中。
让我们将 enable_dns_hostnames 设置为 false。
$ terraform plan 在执行计划之前,正在刷新内存中的 Terraform 状态... 刷新后的状态将用于计算此计划,但不会持久化到本地或远程状态存储。 aws_vpc.vpc:正在刷新状态... [id=vpc-09a9f1827bfd851f4] --------------------------------------------------------------------------- 已生成执行计划,如下所示。资源操作用以下符号表示:~ 就地更新 Terraform 将执行以下操作:# aws_vpc.vpc 将被就地更新 ~ 资源 "aws_vpc" "vpc" { arn = "arn:aws:ec2:ap-northeast-1:485076298277:vpc/vpc-09a9f1827bfd851f4" assign_generated_ipv6_cidr_block = false cidr_block = "10.0.0.0/16" default_network_acl_id = "acl-0cd8abfed52e0e951" default_route_table_id = "rtb-08c13269b1b26c9b8" default_security_group_id = "sg-007ef29e563b6f9c7" dhcp_options_id = "dopt-6c0f430b" enable_classiclink = false enable_classiclink_dns_support = false ~ enable_dns_hostnames = true -> false enable_dns_support = true id = "vpc-09a9f1827bfd851f4" instance_tenancy = "default" main_route_table_id = "rtb-08c13269b1b26c9b8" owner_id = "485076298277" tags = { "Name" = "vpc-tfstate-test" } } 计划:0 个要添加,1 个要更改,0 个要销毁。 --------------------------------------------------------------------------- 注意:您没有指定“-out”参数来保存此计划,因此 Terraform 无法保证如果随后运行“terraform apply”,这些操作将完全执行。.
它似乎只想改变差异。
概括
导入命令说明页(※2)所述
换句话说,你需要一边查看与 tfstate 的差异,一边自己编写实际的 tf 文件。未来似乎会添加自动生成 tf 文件的功能,但就目前而言,目标越多,难度就越大……
为了解决这个问题,Terraformer (※3)作为开源软件发布了。
我将在下一篇博文中解释如何使用它。
参考网址
*1 : https://www.terraform.io/docs/providers/aws/r/vpc.html
*2 : //www.terraform.io/docs/import/index.html
*3 : //github.com/GoogleCloudPlatform/terraformer
2