Terraform

Terraforming で既存のインフラを Terraform 管理下におく

More than 3 years have passed since last update.

Terraform は、主にインフラをスクラッチから構築する際に有用なツールです。

ですが、いま動いている既存のインフラに Terraform を導入したい、既存のインフラを Terraform で管理したいと思う方もいるのではないでしょうか。

今回は、Terraforming を使って既存のインフラを Terraform で管理できるようにする方法を紹介します。


Terraforming とは

Terraforming は、AWS の API を叩いて既存のインフラリソースから Terraform のコードを生成するツールです。

兄弟分に、DNSimple 用の Terraforming::DNSimple があります。


インストール

RubyGems として公開されているので、

$ gem install terraforming

また、Docker Image も公開してあるので、そちらを使いたい方は

$ docker pull quay.io/dtan4/terraforming:latest


使い方


tf 形式の出力

予め AWS のクレデンシャルを環境変数に入れておきます。

Mac ユーザなら envchain おすすめです。

export AWS_ACCESS_KEY_ID=XXXXXXXXXXXXXXXXXXXX

export AWS_SECRET_ACCESS_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
export AWS_DEFAULT_REGION=xx-yyyy-0

リソース名を指定するだけだと、tf 形式で出力されます。

S3 bucket の場合だと:

$ terraforming s3

resource "aws_s3_bucket" "hoge" {

bucket = "hoge"
acl = "private"
}

resource "aws_s3_bucket" "fuga" {
bucket = "fuga"
acl = "private"
}

これを s3.tf とかに書き出せばよいです。

Docker Container として動かす場合は以下のようになります。

$ docker run \

--rm \
--name terraforming \
-e AWS_ACCESS_KEY_ID=XXXXXXXXXXXXXXXXXXXX \
-e AWS_SECRET_ACCESS_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx \
-e AWS_DEFAULT_REGION=xx-yyyy-0 \
quay.io/dtan4/terraforming:latest \
terraforming s3


tfstate 形式の出力

既存のインフラを Terraform 管理に置くためには、tf ファイルを書くだけでは足りません。

状態管理ファイルである terraform.tfstate も書き換える必要があります。

--tfstate オプションをつけると、tfstate 形式で出力されます。

$ terraforming s3 --tfstate

{

"version": 1,
"serial": 1,
"modules": {
"path": [
"root"
],
"outputs": {
},
"resources": {
"aws_s3_bucket.hoge": {
"type": "aws_s3_bucket",
"primary": {
"id": "hoge",
"attributes": {
"acl": "private",
"bucket": "hoge",
"id": "hoge"
}
}
},
"aws_s3_bucket.fuga": {
"type": "aws_s3_bucket",
"primary": {
"id": "fuga",
"attributes": {
"acl": "private",
"bucket": "fuga",
"id": "fuga"
}
}
}
}
}
}

また、tfstate は既存の terraform.tfstate にマージした形で出力することもできます。

$ terraforming s3 --tfstate --merge=/path/to/tfstate

{

"version": 1,
"serial": 89,
"remote": {
"type": "s3",
"config": {
"bucket": "terraforming-tfstate",
"key": "tf"
}
},
"modules": {
"path": [
"root"
],
"outputs": {
},
"resources": {
"aws_iam_user.dtan4": {
"type": "aws_iam_user",
"primary": {
"id": "dtan4",
"attributes": {
"arn": "arn:aws:iam::012345678901:user/dtan4",
"id": "dtan4",
"name": "dtan4",
"path": "/",
"unique_id": "ABCDEFGHIJKLMN1234567"
}
}
},
"aws_s3_bucket.hoge": {
"type": "aws_s3_bucket",
"primary": {
"id": "hoge",
"attributes": {
"acl": "private",
"bucket": "hoge",
"id": "hoge"
}
}
},
"aws_s3_bucket.fuga": {
"type": "aws_s3_bucket",
"primary": {
"id": "fuga",
"attributes": {
"acl": "private",
"bucket": "fuga",
"id": "fuga"
}
}
}
}
}
}

もしリモート (S3, Atlas etc.) で terraform.tfstate を管理している場合は、手元でいじったあと serial を上げないとリモートのものと一致しないと怒られます。

が、Terraforming の --merge オプションはちゃんと serial (terraform.tfstate のバージョン番号) もインクリメントします。

これを terraform.tfstate に上書きすればよいです。

最後に terraform plan を実行して、差分が出ないことを確認して下さい。

$ terraform plan

No changes. Infrastructure is up-to-date. This means that Terraform
could not detect any differences between your configuration and
the real physical resources that exist. As a result, Terraform
doesn't need to do anything.


対応している AWS リソース

v0.1.0 時点では以下のリソースに対応しています。


  • Database Parameter Group

  • Database Security Group

  • Database Subnet Group

  • EC2

  • ELB

  • IAM Group

  • IAM Group Policy

  • IAM Instance Profile

  • IAM Policy

  • IAM Role

  • IAM Role Policy

  • IAM User

  • IAM User Policy

  • Network ACL

  • Route53 Record

  • Route53 Hosted Zone

  • RDS

  • S3

  • Security Group

  • Subnet

  • VPC


おわりに

Terraforming を使って、既存のインフラリソースを Terraform コードに落としこむための方法を紹介しました。

なぜ Terraforming を作ることにしたのか等の小話が下のブログ記事に書いてありますので、合わせてご覧いただけると幸いです。


REF