使用 Terraformer 将现有基础设施资源导入 Terraform
目录
我叫寺冈,是一名基础设施工程师。
,我们在下面的文章中介绍了 terraform import 命令,作为将现有资源导入 Terraform 的方法
正如本文总结中提到的,
使用 import 命令只能重写 tfstate,因此
需要自己编写 tf 文件,同时检查与 tfstate 的差异。
如果人多的话,好像要花很多时间,这是个问题。
这对你们所有人来说都是个好消息。
名为 terraformer 的工具作为 OSS 发布。
https://github.com/GoogleCloudPlatform/terraformer
CLI 工具,用于从现有基础设施生成 terraform 文件(将基础设施逆向代码)。
正如这样写的,它似乎是一个 CLI 工具,可以从现有基础设施自动生成 Terraform 文件。
Github上也有介绍如何使用,我们来尝试一下。
安装
对于Mac,您可以使用brew 命令安装它。
$brew install terraformer $terraformer 版本 Terraformer v0.8.7
到目前为止,这很容易。
这次我们将使用 v0.8.7。
基础设施配置
我提前使用 terraformer 创建了要导入的基础设施。
https://github.com/beyond-teraoka/terraform-aws-multi-environment-sample
配置图
我在同一个 AWS 账户中有 3 个环境。
- 发展
- 生产
- 管理
此外,每个环境还具有以下资源:
- 专有网络
- 子网
- 路由表
- 互联网网关
- NAT网关
- 安全组
- VPC 对等互连
- 电子工业园区
- EC2
- 白蛋白
- RDS
虽然图中没有显示,但是每个环境资源都被赋予一个Environment标签,并且
dev、prod和mng被设置为每个环境的值。
准备凭据
准备您的 AWS 凭证。
请根据您的环境准备此内容。
$ cat /Users/yuki.teraoka/.aws/credentials [beyond-poc] aws_access_key_id = XXXXXXXXXXXXXXXXXX aws_secret_access_key = XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX [beyond-poc-admin] role_arn = arn:aws:iam::XXXXXXXXXXXX:role/XXXXXXXXXXXXXXXX XXXX source_profile = Beyond-波克
运行地形改造者
首先,尝试执行 GitHub 上编写的示例。
$ terraformer 导入 aws --resources=alb,ec2_instance,eip,ebs,igw,nat,rds,route_table,sg,子网,vpc,vpc_peering --regions=ap-northeast-1 --profile=beyond-poc-admin 2020 /05/05 18:29:14 aws 导入区域 ap-northeast-1 2020/05/05 18:29:14 aws 导入... vpc 2020/05/05 18:29:15 open /Users/yuki.teraoka /.terraform.d/plugins/darwin_amd64:没有这样的文件或目录
执行 terraform init 时似乎需要插件目录。
准备init.tf和init.tf。
$ echo 'provider "aws" {}' > init.tf $ terraform init
我会尝试再次运行它。
$ terraformer import aws --resources=alb,ec2_instance,eip,ebs,igw,nat,rds,route_table,sg,subnet,vpc,vpc_peering --regions=ap-northeast-1 --profile=beyond-poc-admin
看来导入成功了。
已经创建了一个名为 generated 的目录,该目录此前并不存在。
目录结构
$ 树 └── aws ├── alb │ ├── lb.tf │ ├── lb_listener.tf │ ├── lb_target_group.tf │ ├── lb_target_group_attachment.tf │ ├── 输出.tf │ ├──提供商.tf │ ├── terraform.tfstate │ └── 变量.tf ├── ebs │ ├── ebs_volume.tf │ ├── 输出.tf │ ├── 提供商.tf │ └── terraform.tfstate ├ ── ec2_instance │ ├── 实例.tf │ ├── 输出.tf │ ├── 提供者.tf │ ├── terraform.tfstate │ └── 变量.tf ├── eip │ ├── eip.tf │ ├── 输出.tf │ ├── 提供者.tf │ └── terraform.tfstate ├── igw │ ├── internet_gateway.tf │ ├── 输出.tf │ ├── 提供者.tf │ ├── terraform .tfstate │ └── 变量.tf ├── nat │ ├── nat_gateway.tf │ ├── 输出.tf │ ├── 提供商.tf │ └── terraform.tfstate ├── rds │ ├── db_instance .tf │ ├── db_parameter_group.tf │ ├── db_subnet_group.tf │ ├── 输出.tf │ ├── 提供商.tf │ ├── terraform.tfstate │ └── 变量.tf ├── 路由表 │ ├ ── main_route_table_association.tf │ ├──outputs.tf │ ├──provider.tf │├──route_table.tf │├──route_table_association.tf │├──terraform.tfstate │└──variables.tf ├── sg │ ├── 输出.tf │ ├── 提供商.tf │ ├── security_group.tf │ ├── security_group_rule.tf │ ├── terraform.tfstate │ └── 变量.tf ├── 子网 │ ├─ ─ 输出.tf │ ├── 提供商.tf │ ├── 子网.tf │ ├── terraform.tfstate │ └── 变量.tf ├── vpc │ ├── 输出.tf │ ├── 提供商.tf │ ├── terraform.tfstate │ └── vpc.tf └── vpc_peering ├──outputs.tf ├──provider.tf ├──terraform.tfstate └──vpc_peering_connection.tf 13个目录,63个文件
我希望您注意目录结构。Terraformer
似乎将其导入到默认结构“{output}/{provider}/{service}/{resource}.tf”中。
这也记录在 GitHub 上。
Terraformer 默认情况下将每个资源分隔成一个文件,并将其放入给定的服务目录中。
资源文件的默认路径是 {output}/{provider}/{service}/{resource}.tf,并且可能因每个提供程序而异。
这种结构存在以下问题:
- 由于 tfstate 是针对每个 Terraform 资源进行划分的,因此即使是很小的更改也需要多次应用。
- 所有环境的资源都记录在同一个tfstate中,因此一个环境的变化会影响所有环境。
如果可以的话,我想把tfstate按照develop、生产、manage等环境来划分,
这样每个环境的所有资源都记录在同一个tfstate中。
当我研究是否可以做到这一点时,我发现了以下内容。
- 可以使用 --path-pattern 选项显式指定层次结构
- 只能导入具有使用 --filter 选项指定的标签的资源。
将这两者结合起来似乎可以实现这一点,所以让我们尝试一下。
$ terraformer import aws --resources=alb,ec2_instance,eip,ebs,igw,nat,rds,route_table,sg,subnet,vpc,vpc_peering --regions=ap-northeast-1 --profile=beyond-poc-admin - -path-pattern {输出}/{provider}/develop/ --filter="Name=tags.Environment;Value=dev" $ terraformer import aws --resources=alb,ec2_instance,eip,ebs,igw,nat,rds ,route_table,sg,子网,vpc,vpc_peering --regions=ap-northeast-1 --profile=beyond-poc-admin --path-pattern {输出}/{provider}/生产/ --filter="名称= Tags.Environment;Value=prod" $ terraformer import aws --resources=ec2_instance,eip,ebs,igw,route_table,sg,subnet,vpc,vpc_peering --regions=ap-northeast-1 --profile=beyond-poc- admin --path-pattern {output}/{provider}/manage/ --filter="Name=tags.Environment;Value=mng"
导入后的目录结构如下。
目录结构
$ 树 └── aws ├── 开发 │ ├── db_instance.tf │ ├── db_parameter_group.tf │ ├── db_subnet_group.tf │ ├── eip.tf │ ├── instance.tf │ ├── internet_gateway.tf │ ├── lb.tf │ ├── lb_target_group.tf │ ├── nat_gateway.tf │ ├──outputs.tf │ ├──provider.tf │ ├──route_table.tf │├──security_group .tf │ ├──subnet.tf │ ├── terraform.tfstate │ ├── 变量.tf │ └── vpc.tf ├── 管理 │ ├── instance.tf │ ├── internet_gateway.tf │ ├ ── 输出.tf │ ├── 提供商.tf │ ├── 路由表.tf │ ├── security_group.tf │ ├── 子网.tf │ ├── terraform.tfstate │ ├── 变量.tf │ ├─ ─ vpc.tf │ └── vpc_peering_connection.tf └── 生产 ├── db_instance.tf ├── db_parameter_group.tf ├── db_subnet_group.tf ├── eip.tf ├── instance.tf ├── internet_gateway。 tf ├── lb.tf ├── lb_target_group.tf ├── nat_gateway.tf ├── 输出.tf ├── 提供商.tf ├── 路由表.tf ├── 安全组.tf ├── 子网.tf ├ ── terraform.tfstate ├── Variables.tf └── vpc.tf 4个目录,45个文件
资源是按环境划分的。
如果你尝试在develop下查看vpc.tf,只会导入相应环境的VPC。
开发/vpc.tf
资源“aws_vpc”“tfer--vpc-002D-0eea2bc99da0550a6”{分配_生成_ipv6_cidr_block =“假”cidr_block =“10.1.0.0/16”enable_classiclink =“假”enable_classiclink_dns_support =“假”enable_dns_hostnames =“真”enable_dns_support =“真”实例_tenancy = "default" 标签 = { 环境 = "dev" 名称 = "vpc-terraformer-dev" } }
关于tfstate,每个环境的所有资源都记录在一个文件中,所以这里看起来没有问题。
内容比较长,我就不赘述了。
关注点
有些地方对资源ID值进行了硬编码。
有多个地方对资源ID值进行了硬编码,例如下面aws_security_group的vpc_id
资源“aws_security_group”“tfer--alb-002D-dev-002D-sg_sg-002D-00d3679a2f3309565”{description =“for ALB”出口{cidr_blocks = [“0.0.0.0/0”]description =“出站全部”from_port = “0”协议=“-1”self=“假”to_port=“0”}入口{cidr_blocks=[“0.0.0.0/0”]描述=“allow_http_for_alb”from_port=“80”协议=“tcp”self= “假”to_port =“80”}名称=“alb-dev-sg”标签={环境=“dev”名称=“alb-dev-sg”}vpc_id =“vpc-0eea2bc99da0550a6”}
在编写新的HCL时,像“vpc_id = aws_vpc.vpc.id”一样动态引用它,但
在导入时似乎仍然很难完成。
对于这部分,tfstate中已经记录了VPC ID,因此只需修改tf文件即可。
terraform_remote_state的描述与0.12不兼容
有些地方的HCL描述是针对Terraform 0.11系列的,例如下面aws_subnet的vpc_id。
资源“aws_subnet”“tfer--subnet-002D-02f90c599d4c887d3”{assign_ipv6_address_on_creation =“false”cidr_block =“10.1.2.0/24”map_public_ip_on_launch =“true”标签={环境=“dev”名称=“subnet-terraformer-dev” -public-1c" } vpc_id = "${data.terraform_remote_state.local.outputs.aws_vpc_tfer--vpc-002D-0eea2bc99da0550a6_id}" }
如果在这种状态下应用0.12系列,它会运行,但会出现警告。
另外,如果将 --path-pattern 选项更改为每个环境的单独目录,则
tfstate 本身将输出在一个文件中,但
在引用 tf 文件中的资源时,它们仍将被引用为 terraform_remote_state。
如果你看一下GitHub,有下面的描述,所以它就是规范。
使用 terraform_remote_state (本地和存储桶)在资源之间进行连接。
在上述 vpc_id 的情况下,aws_vpc 和 aws_subnet 记录在同一 tfstate 中,因此
可以简单地通过“vpc_id = aws_vpc.tfer--vpc-002D-0eea2bc99da0550a6.id”来引用它们。
看起来你必须自己修复这部分。
概括
你觉得怎么样?
如果使用 terraformer,导入现有基础设施似乎会更容易。
有一些担忧,但解决起来并不困难,所以我认为在可以接受的范围内。
我一直认为导入 terraform 很困难,所以我
真诚地尊重“Waze SRE”的人们,他们创建了一个工具,很好地解决了这个问题。
请大家尝试使用一下。