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 を作ることにしたのか等の小話が下のブログ記事に書いてありますので、合わせてご覧いただけると幸いです。