Terraformer を利用し既存インフラをコード化する


[Ateam Group Manager ＆ Specialist Advent Calendar 2020](https://qiita.com/advent-calendar/2020/ateam) の 22 日目は、Increments 株式会社 @mziyut が担当します。

## はじめに

普段皆さんは、インフラをどのように管理していますでしょうか。
Infrastructure as Code(IaC)と当たり前に言われる中もちろんコード上で管理している方が多いと思います。
ただ、一方で過渡期であったり、緊急で構成の変更を求められることは 0 ではありません。
軽微な変更であれば、容易に取り込むことが出来ますが、新規のリソースを追加した際には取り込むことは至難の業となります。

今回は、 Terraformer[^1] を利用し既存インフラのコード化を行ってみようと思います。

[^1]: [GoogleCloudPlatform/terraformer: CLI tool to generate terraform files from existing infrastructure (reverse Terraform). Infrastructure to Code](https://github.com/GoogleCloudPlatform/terraformer)

## 既存インフラをコード化する

今回は、Terraform 及び terraformer コマンドが利用出来ること。
Terraform backend 等は正しく設定されていることを前提に進めます。

### 今回の実行環境

- Terraform backend
  - Terraform Cloud
- Terraform version
  - v0.14.3
- Terraformer version
  - v0.8.10

### セキュリティグループ を取り込んでみる

今回は、セキュリティグループを新規追加したとしてこちらをコード化してみようと思います。
※セキュリティグループなら何かのリソースにアタッチしているはずですが今回は省略します。

今回のために、以下セキュリティグループをコンソールから作成しました

![スクリーンショット 2020-12-22 1.23.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55950/b11978c3-abcc-f198-63b7-4dced54e0952.png)

### Terraformer の実行準備

`terraformer import` を実行出来るように準備を進めていきます。
個人的に Terraformer を実行するディレクトリは Terraform Working Directory 以外での実行をおすすめします。
理由は以下となります。

- EC2 等 import した場合セキュリティグループなどべた書きになってしまう
- module 等綺麗に分割していても考慮せずにコード化されてしまう

そのため私は、**あくまで現在の state を取り込む** ことを目的に Terraformer を利用しています。
それでは、適当に `tmp` ディレクトリを作成しそのディレクトリ内で `terraformer import` を実行出来るように準備を進めていきます

```zsh
% mkdir tmp && cd $_
% echo 'provider "aws" {}' > main.tf
% terraform init

Initializing the backend...

Initializing provider plugins...
- Finding latest version of hashicorp/aws...
- Installing hashicorp/aws v3.22.0...
- Installed hashicorp/aws v3.22.0 (signed by HashiCorp)

Terraform has created a lock file .terraform.lock.hcl to record the provider
selections it made above. Include this file in your version control repository
so that Terraform can guarantee to make the same selections by default when
you run "terraform init" in the future.

Terraform has been successfully initialized!

You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.

If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.
```

`terraform init` を実行したことで `tmp` ディレクトリ以下は以下のようになりました

```zsh
% tree -a
.
├── .terraform
│   └── providers
│       └── registry.terraform.io
│           └── hashicorp
│               └── aws
│                   └── 3.22.0
│                       └── darwin_amd64
│                           └── terraform-provider-aws_v3.22.0_x5
├── .terraform.lock.hcl
└── main.tf

7 directories, 3 files
```

#### `terraformer import` を実行しよう

今回はセキュリティグループを import するので以下のようなコマンドを実行します。

```zsh
% terraformer import aws --resources sg --regions <リージョン名>
2020/12/22 01:20:47 aws importing region ap-northeast-1
2020/12/22 01:20:51 aws importing... sg
2020/12/22 01:20:52 Refreshing state... aws_security_group.tfer--default_sg-xxxx-xxxxxxxx
2020/12/22 01:20:52 aws Connecting....
2020/12/22 01:20:52 aws save sg
2020/12/22 01:20:52 aws save tfstate for sg
```

import を実行すると `generated` というディレクトリが作成されます。
その中に AWS 上に定義されているすべてのセキュリティグループがコード化されました。

```zsh
% 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
```

### 実際に生成されたコードを見てみましょう

今回セキュリティグループを作成したリージョンには 10 個のセキュリティグループが存在します。
これらのセキュリティグループすべてが 1 ファイルのなかに出力されます。
記事が必要以上に長くなってしまうため、今回作成したセキュリティグループ以外の import 結果については省略させて頂きます。
また、`generated/aws/sg/variables.tf` と `generated/aws/sg/terraform.tfstat` についても同様です。

```tf:generated/aws/sg/outputs.tf
output "aws_security_group_tfer--mziyut-002D-advent-002D-calendar-002D-2020_sg-xxxx-xxxxxxxxxxxxxxxxx_id" {
  value = "aws_security_group.tfer--mziyut-002D-advent-002D-calendar-002D-2020_sg-xxxx-xxxxxxxxxxxxxxxxx.id"
}
```

```tf:generated/aws/sg/provider.tf
provider "aws" {
  region = "<ここにリージョン名>"
}

terraform {
  required_providers {
    aws = {
      version = "~> 3.22.0"
    }
  }
}
```

```tf:generated/aws/sg/security_group.tf
resource "aws_security_group" "tfer--mziyut-002D-advent-002D-calendar-002D-2020_sg-xxxx-xxxxxxxxxxxxxxxxx" {
  description = "mziyut advent calender 2020 :tada:"

  egress {
    cidr_blocks = ["0.0.0.0/0"]
    from_port   = "0"
    protocol    = "-1"
    self        = "false"
    to_port     = "0"
  }

  name   = "mziyut-advent-calendar-2020"
  vpc_id = "vpc-xxxxxxxx"
}
```

## まとめ

今回 Terraformer を利用し既存インフラをコード化しました。
自らインフラの状態から Terraform を記述するよりも何倍も効率よく進めることができました。

気になる方は、一度触ってみてはいかがでしょうか。

## 最後に

[Ateam Group Manager ＆ Specialist Advent Calendar 2020](https://qiita.com/advent-calendar/2020/ateam) の 23 日目は、Increments 株式会社の @phigasui さんがお送りします。