变形者的陷阱
首先
晚上好。我是Progaku Advent Calendar 2022的第三天负责人,名叫きよすけ。
话不多说,大家有没有在做IaaC?(直截了当)时间有限,虽然有现有的基础设施,但还没有进行代码化…不过从现在开始从零开始编码会很辛苦吧…这样的人应该也不少吧?
在这种情况下,我发现了一个工具,叫做Terraformer。「嗯嗯…只需指定AWS资源并导入,它就会自动生成.tf文件…这不是神器吗??简直没有不用的理由了!」于是我立刻决定使用它。
然而,这并不是一颗银弹,对吧?虽然稍微有些匆忙,但我简单总结了一下陷阱,请参考。
目标读者
-
- AWS、Terraformについての基礎知識がある方
- 既存のインフラをコード化したい方
环境
-
- M1 Mac Big Sur 11.6
-
- Terraformer v0.8.21
- Terraform v1.2.3
Terraformer(是什么意思)?
-
- 上記でも解説したように既存のインフラストラクチャからTerraformコードを生成してくれるツール。インポートするとデフォルトでgeneratedディレクトリが作られ、そのなかにコードが自動生成される。
コードは一つのファイルにまとまって出力される。
$ echo ‘provider “aws” {}’ > main.tf
$ terraform init
$ terraformer import aws --resources sg --regions <リージョン名>
$ tree -a
.
├── .terraform
│ └── providers
│ └── registry.terraform.io
│ └── hashicorp
│ └── aws
│ └── 3.22.0
│ └── darwin_amd64
│ └── terraform-provider-aws_v3.22.0_x5
├── .terraform.lock.hcl
├── generated
│ └── aws
│ └── sg
│ ├── outputs.tf
│ ├── provider.tf
│ ├── security_group.tf
│ ├── terraform.tfstate
│ └── variables.tf
└── main.tf
10 directories, 8 files
导入时的陷阱
SSOの認証情報ではインポート時に認証エラーになる。(SSOで使っているユーザーのプロファイルを指定してインポートが出来ない)
TerraformではSSOユーザープロファイルでCLIの実行ができるが、Terraformerの場合は、Terraformer実行用のIAMユーザーを用意し、このユーザープロファイルを指定する必要があった。
このとき、TerraformerのIAMに適切な権限を設定する必要があるが結構めんどくさいので注意。
TerraformerはAWS CLIのプロファイルに対応していなかったが試してみた所現在は対応しているっぽい。
会加载默认策略等等。
-
- AWSS3FullAccessとか元々あるポリシーもコード化されてしまう。
タグ付けやIDでフィルタリングできるのでこれらのオプションを駆使して工夫して実際にコード化したいリソースをインポートする必要がある。
リソースIDでフィルタリング
$ terraformer import aws –resources=vpc,subnet –filter=vpc=myvpcid –regions=eu-west-1
タグ指定でフィルタリング
$ terraformer import aws –resources=s3 –filter=“Name=tags.Abc” –regions=eu-west-1
可用的Terraform版本过旧
- terraform0.13.6までの対応(1系はサポートしていない)。
依赖关系无法解决问题。
我认为这可能是最棘手和繁琐的一点。
例如,当导入VPC和子网时,Terraform会自动生成以下源代码。
你能明白问题出在哪里吗?(如果你经常写Terraform的话,我想你会知道问题出在哪里。)
resource "aws_vpc" "example-ecs-vpc" {
cidr_block = "10.1.0.0/16"
enable_dns_hostnames = true
enable_dns_support = true
tags = {
"Name" = "example-ecs-vpc"
}
tags_all = {
"Name" = "example-ecs-vpc"
}
}
resource "aws_subnet" "tfer--subnet-00e08070gur80898" {
assign_ipv6_address_on_creation = "false"
cidr_block = "10.1.144.0/20"
(…省略…)
availability_zone = "ap-northeast-1c"
tags = {
ENV = "example-ecs"
Name = "example-ecs-subnet-private2-ap-northeast-1c"
}
tags_all = {
ENV = "example-ecs"
Name = "example-ecs-subnet-private2-ap-northeast-1c"
}
vpc_id = "vpc-01234567890abcdef"
}
是的,aws_subnet的vpc_id已经硬编码了。
本来应该是
vpc_id = aws_vpc.example-ecs-vpc.id
应该写成「这是应该写的地方」。
然而,基于基本的Terraform生成的源代码中,subnet_id、vpc_id、IAM角色名称和ARN等都被硬编码生成。这样一来,Terraform无法解决资源之间的依赖关系。
-
- VPCより先にサブネットを作ろうとする
- またIAMロールが作成されていないのにEC2にアタッチしようとする
发生类似的情况时,Terraform会产生“根本没有这个资源”的错误,这使我感到非常恼火。而且有时候除非执行terraform apply命令,否则无法察觉到这个问题,因此我认为只能通过不断尝试和错误来解决它。
自动生成的代码不能直接使用。
如果说出这句话,会有一种“没有元也没有子”的感觉,但即使解决了上述的依赖问题,还是会经常出现错误,所以需要用手来进行一些修正。需要注意的是,有些属性是不推荐使用的,有些甚至是不需要指定的属性也被包含在了源代码中。另外,有时候会发现本来应该导入的资源没有被创建。在我个人的经验中,遇到这种情况时,建议直接使用terraform import并结合tfstate来编写Terraform,这样可以更快速和准确地完成工作,所以对于临时操作来说,使用这种方法也是一个选择。
总结
-
- Terraformerは決して銀の弾丸ではない
-
- インポート時は必要なものを絞って戦略的に行う
SSOを使っている場合でも別途Terraformer実行用のIAMユーザーの作成が必要(ここは改善されるかもしれない)
自動生成されたコードはそのままでは使えないので、結局手でそこそこ修正する必要がある
場合によってはterraform importを活用すべし
とはいえ、1からTerraformを書くよりTerraformerで叩き実装をしてやっていったほうがはやいとは思う!