この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
既存のAWS環境をエクスポートしてTerraformにまとめたい。
そんなことありませんか。
既存のAWS環境を元にtfファイルとtfstateファイルを出力してくれるterraformerというツールが最近出ました。
GoogleCloudPlatformが中心となって開発しており、GCPのみならず、既存のAWS、GitHub、Datadog、GitHub、Kubernetesの環境にも対応しています。
インストール方法
macOSでは、homebrew
経由でのインストールが既に可能です。
また、goで書かれているので直接ビルドすることも可能です。
下記にビルドする方法を記載しておきます。
$ git clone https://github.com/GoogleCloudPlatform/terraformer.git
$ GO111MODULE=on go mod vendor
$ go build -v
使用方法
AWSではこのように使用します。
使用可能なサービス一覧はREADMEに記載があります。
VPCやEC2、ALB、RDSなどといった主要なサービスは既にサポートされています。
$ echo 'provider "aws" {}' > init.tf
$ terraform init
$ terraformer import aws --resources=vpc,subnet --connect=true --regions=eu-west-1
$ terraformer import aws --resources=vpc,subnet --filter=aws_vpc=vpc_id1:vpc_id2:vpc_id3 --regions=eu-west-1
# https://github.com/GoogleCloudPlatform/terraformer#use-with-aws
GCPではこのように使用します。
使用可能なサービス一覧はREADMEに記載があります。
$ echo 'provider "gcp" {}' > init.tf
$ terraform init
$ terraformer import google --resources=gcs,forwardingRules,httpHealthChecks --connect=true --zone=europe-west1-a --projects=aaa,fff
$ terraformer import google --resources=gcs,forwardingRules,httpHealthChecks --filter=google_compute_firewall=rule1:rule2:rule3 --zone=europe-west1-a --projects=aaa,fff
# https://github.com/GoogleCloudPlatform/terraformer#use-with-gcp
AWS環境での検証
v0.7.5段階での内容ですが注意点があります。
現在terraformerはAWS CLIのプロファイルに対応していません。
なので認証情報を下記のようにして渡す必要があります。
export AWS_ACCESS_KEY_ID=xxx
、export AWS_SECRET_ACCESS_KEY=xxx
といった形で環境変数を通じて渡す- assume-roleを使用して下記のように実行する
$ assume-role your_profile terraformer import aws --resources=vpc,subnet --connect=true --regions=eu-west-1
実行環境
- terraform : v0.12.2
- terraformer : v0.7.5
- OS : macOS
やってみた
バージニア北部にEC2とALBを構築してその内容をエクスポートしてみました。
terraformerの使用前にterraformにproviderの情報を渡す必要があるのでinit.tf
というファイルを作成して初期化します。
$ echo 'provider "aws" {}' > init.tf
$ terraform init
ここまでできたらterraformerを実行します。
$ export AWS_ACCESS_KEY_ID=xxx
$ export AWS_SECRET_ACCESS_KEY=xxx
$ terraformer import aws \
--resources=vpc,subnet,igw,sg,alb,ec2_instance \
--filter=aws_vpc=id1:vpc-xxxxxxxxxxxxxxxxx \
--regions=us-east-1
2019/07/02 10:31:47 aws importing region us-east-1
2019/07/02 10:31:47 aws importing... vpc
2019/07/02 10:31:57 Refreshing state... aws_vpc.vpc-xxxxxxxxxxxxxxxxx
2019/07/02 10:32:04 aws importing... subnet
2019/07/02 10:32:11 Refreshing state... aws_subnet.subnet-xxxxxxxx
2019/07/02 10:32:11 Refreshing state... aws_subnet.subnet-xxxxxxxxxxxxxxxxx
2019/07/02 10:32:11 Refreshing state... aws_subnet.subnet-xxxxxxxxxxxxxxxxx
2019/07/02 10:32:11 Refreshing state... aws_subnet.subnet-xxxxxxxx
2019/07/02 10:32:11 Refreshing state... aws_subnet.subnet-xxxxxxxx
2019/07/02 10:32:11 Refreshing state... aws_subnet.subnet-xxxxxxxx
2019/07/02 10:32:11 Refreshing state... aws_subnet.subnet-xxxxxxxxxxxxxxxxx
2019/07/02 10:32:11 Refreshing state... aws_subnet.subnet-xxxxxxxxxxxxxxxxx
2019/07/02 10:32:11 Refreshing state... aws_subnet.subnet-xxxxxxxx
2019/07/02 10:32:11 Refreshing state... aws_subnet.subnet-xxxxxxxx
...
...
terraformer aws import
を実行するとターミナルへの出力の後にgenerated
というディレクトリが生成されます。
その中にterraform関連のファイルが出来上がっており、terraform用のファイルが入っています。
terraform.tfstate
や、*.tf
といったファイルが確認できます。
ディレクトリ構造はこのような形になっています。
$ tree generated/ | head -n 20
generated/
└── aws
├── alb
│ └── us-east-1
│ ├── lb.tf
│ ├── lb_listener.tf
│ ├── lb_listener_rule.tf
│ ├── lb_target_group.tf
│ ├── lb_target_group_attachment.tf
│ ├── outputs.tf
│ ├── provider.tf
│ ├── terraform.tfstate
│ └── variables.tf
├── ec2_instance
│ └── us-east-1
│ ├── instance.tf
│ ├── outputs.tf
│ ├── provider.tf
│ └── terraform.tfstate
├── igw
tfファイルの中身はこのようになっています。
terraformerでエクスポートしたVPCに紐づくsubnetに関してはハードコーディングされずに出力されています。
逆にエクスポートしなかったデフォルトのVPCに紐づくsubnetに関してはハードコーディングされてしまっています。
generated/aws/subnet/us-east-1/subnet.tf
resource "aws_subnet" "subnet-xxxxxxxxxxxxxxxxx" {
assign_ipv6_address_on_creation = false
cidr_block = "192.168.1.0/24"
map_public_ip_on_launch = false
tags {
Name = "terraformer-test-pub-2"
}
vpc_id = "${data.terraform_remote_state.vpc.aws_vpc_vpc-xxxxxxxxxxxxxxxxx_id}"
}
resource "aws_subnet" "subnet-xxxxxxxxxxxxxxxxx" {
assign_ipv6_address_on_creation = false
cidr_block = "192.168.3.0/24"
map_public_ip_on_launch = false
tags {
Name = "terraformer-test-private-2"
}
vpc_id = "${data.terraform_remote_state.vpc.aws_vpc_vpc-xxxxxxxxxxxxxxxxx_id}"
}
resource "aws_subnet" "subnet-xxxxxxxxxxxxxxxxx" {
assign_ipv6_address_on_creation = false
cidr_block = "192.168.0.0/24"
map_public_ip_on_launch = false
tags {
Name = "terraformer-test-pub-1"
}
vpc_id = "${data.terraform_remote_state.vpc.aws_vpc_vpc-xxxxxxxxxxxxxxxxx_id}"
}
resource "aws_subnet" "subnet-xxxxxxxxxxxxxxxxx" {
assign_ipv6_address_on_creation = false
cidr_block = "192.168.2.0/24"
map_public_ip_on_launch = false
tags {
Name = "terraformer-test-private-1"
}
vpc_id = "${data.terraform_remote_state.vpc.aws_vpc_vpc-xxxxxxxxxxxxxxxxx_id}"
}
resource "aws_subnet" "subnet-xxxxxxxx" {
assign_ipv6_address_on_creation = false
cidr_block = "172.31.16.0/20"
map_public_ip_on_launch = true
tags {}
vpc_id = "vpc-xxxxxxxx"
}
resource "aws_subnet" "subnet-xxxxxxxx" {
assign_ipv6_address_on_creation = false
cidr_block = "172.31.48.0/20"
map_public_ip_on_launch = true
tags {}
vpc_id = "vpc-xxxxxxxx"
}
~~~
また、EC2に関してはVPC、SGなどがハードコーディングされてしまっています。
generated/aws/ec2_instance/us-east-1/instance.tf
resource "aws_instance" "i-xxxxxxxxxxxxxxxxx_erraformer-test-1" {
ami = "ami-0b898040803850657"
associate_public_ip_address = false
availability_zone = "us-east-1a"
cpu_core_count = "1"
cpu_threads_per_core = "1"
credit_specification {
cpu_credits = "standard"
}
disable_api_termination = false
ebs_optimized = false
get_password_data = false
iam_instance_profile = "SSM_for_EC2"
instance_type = "t2.micro"
ipv6_address_count = "0"
key_name = "terraformer-test"
monitoring = false
private_ip = "192.168.2.230"
root_block_device {
delete_on_termination = true
iops = "100"
volume_size = "8"
volume_type = "gp2"
}
source_dest_check = true
subnet_id = "subnet-xxxxxxxxxxxxxxxxx"
tags {
Name = "erraformer-test-1"
}
tenancy = "default"
volume_tags {
name = "erraformer-test-1"
}
vpc_security_group_ids = ["sg-xxxxxxxxxxxxxxxxx"]
}
さいごに
既存の環境をエクスポートできるのでIaCへの移行が少し容易になるかもしれません。
まだベータ版ということもあり機能面ではまだまだ改良されていきそうなので今後が楽しみですね。