技術本部 サービスリライアビリティグループ(SRG)の長谷川 @rarirureluis です。
#SRG(Service Reliability Group)は、主に弊社メディアサービスのインフラ周りを横断的にサポートしており、既存サービスの改善や新規立ち上げ、OSS貢献などを行っているグループです。

 

やりたいこと

6年間、手入れがされていない AWS 環境がありました。

Security Group や EC2 は手で作成され、IaC 環境はありません。

そんな AWS リソースをできるだけ簡単に Terraform に落とし込んでみようと思います。

 

必要なもの

 

Step1 Terraform の雛形を作成する

今回の Terraform ディレクトリ構成は各環境ごとにディレクトリを切って、その下にリソースごとにもディレクトリを切る構成を取ります。

そして今回 Terraform に落とし込むのは EC2 を例にします。

.
└── resources
    └── prd
        └── ec2
            └── versions.tf

version.tf

terraform {
  required_version = ">= 1.0.8"
  required_providers {
    aws = {
      source = "hashicorp/aws"
      version = "3.63.0"
    }
  }
}

 

Step2 Terraform init する

$ cd resources/prd/ec2
$ terraform init

 

Step3 Terraformer で EC2 に関するリソースを Terraform 化する

$ cd resources/prd/ec2
$ terraformer import aws --resources=ec2_instance --regions=ap-northeast-1

--resources に関しては下記のコマンドで確認できます。ec2_instance が EC2 になります。

$ terraformer import aws list
accessanalyzer
acm
alb
... 省略

import を行うとカレントディレクトリ配下に generated というディレクトリが作成され、この中に tfstate を含めた EC2 に関するコードが全て置かれています。

generated
└── aws
    └── ec2_instance
        ├── instance.tf
        ├── outputs.tf
        ├── provider.tf
        └── terraform.tfstate

 

Step4 Terraformer の tfstate をアップグレードする

Terraformer を使うと Terraform 0.12 環境の tfstate になるため、Terraform 1.0 までアップグレードします。

Terraform アップグレード Tips

公式ドキュメントにどのような順番でアップグレードしていったらいいかの情報があります。

スクリーンショット 2021-12-02 18.45.35

ref: Upgrading to Terraform v1.0 – Terraform by HashiCorp

tfenv を利用し適宜 Terraform のバージョンを変更していますが、下位ディレクトリに .terraform-version ファイルがある場合にはそのバージョンに引っ張られるため、.terraform-version を変更し、作業前に意図したバージョンになっているかを $ terraform version で確認することをオススメします。

0.12 -> 0.13

$ cd generated/aws/ec2_instance
$ tfenv use 0.13.7
$ terraform 0.13upgrade
$ terraform init
$ terraform plan
$ terraform apply

Warning で非推奨の書き方をしている場合があるのでそれを修正しましょう。

Warning: Interpolation-only expressions are deprecated

  on outputs.tf line 6, in output "aws_instance_tfer--i-06ab3a2a9cffebacd_hoge_id":
   6:   value = "${aws_instance.tfer--i-06ab3a2a9cffebacd_hoge.id}"

これは

value = aws_instance.tfer--i-06ab3a2a9cffebacd_hoge.id

と書き換えるだけです。

0.13 -> 0.14

$ tfenv use 0.14.11
$ terraform init
$ terraform plan
$ terraform apply

0.14 -> 1.0

$ tfenv use 1.0.8
$ terraform init
$ terraform plan
$ terraform apply

これで 0.12 から 1.0 へアップグレードできました。
ローカルにある tfstate の terraform_version1.0.8 になっているはずです。

 

Step5 generated からひな形ディレクトリにファイルを移動する

.
├── resources
    └── prd
        └── ec2
            ├── init.tf
            ├── instance.tf
            ├── outputs.tf
            ├── provider.tf
            └── versions.tf

tfstate を local から s3 に移動する

# init.tf

terraform {
  backend "s3" {
    bucket = "terraform-aws-hoge"
    region = "ap-northeast-1"
  }
}
$ terraform init

これで s3://terraform-aws-hoge/resources.prd.ec2.tfstate が作成されます。

ここまで EC2 のリソースに関するコードは一切かかずにコード化ができました。

 

Terraformer ハードコーディング問題

Terraformer でコード化したリソースは他の依存リソースがハードコーディングされています。

例えば、EC2 に紐づく Security Group は vpc_security_group_ids = ["sg-9631baf3"] のようになっています。

Data Sources を使って、ハードコーディングされている部分を1箇所で管理するのがシンプルかもしれません。

 

さいごに

今回は 6年間手入れがされていない & IaC がない AWS リソース(環境)の重要性が上がったものの、リソース変更の際の心理的安全性が低かったため既存リソースを Terraform に落とし込み、ついでに整理も行いました。

対象の環境では Terraform で管理するものを EC2 と Security Group の2つに絞りました。
後々 RDS も落とし込みますが Aurora MySQL へのマイグレーションを控えているのでマイグレーション完了後に Terraform に落とし込む予定です。

他にも Fargate を利用していますが、Fargate に必要な ALB や IAM に関してはすべて AWS Copilot で管理しています。
今回の記事とは関係ないんですが、AWS Copilot 結構便利です。

もし、既存リソースを Terraform 化したい場合が場面に出くわしたらぜひこの記事のことを思い出してあげてください。