【terraform】importコマンドでtfstateファイルを複数モジュールに分割する

「コンテナ時代のWebサービスの作り方」を読みながらTerraformを触ってみている。

booth.pm

その中で、Terraformを使う例としてVPCとEC2を作成する項目があった。本ではまず1つのtfファイルに両方のリソースをまとめて記述した後、ec2とvpcでモジュールを分けた書き方を紹介している。

  • パターンA: 1つのtfファイルに両方のリソースを記述する例 (tfstateファイルはS3バケットtest/ 以下に格納)
test
|- sample.tf #VPC, Subnet, EC2リソースを定義
# test
terraform apply sample.tf
...
Apply complete! Resources: 3 added, 0 changed, 0 destroyed.
  • パターンB: リソースの種類ごとにモジュールを分ける例(tfstateファイルはS3バケットtest/vpc/ test/ec2/ 以下にそれぞれ格納)
test
|- vpc
|   |- vpc.tf #VPC, Subnetリソースを定義
|- ec2
    |- ec2.tf #EC2リソースを定義

ここで疑問に思ったのが、パターンA -> パターンBのように、もし最初に1つのtfファイルをapplyしその後でモジュールを分けたくなった場合どうするのかということ。というのも、パターンAとBでは tfstate の格納場所が異なっているため、Aのtfファイルをapplyした後にBで分けた2つのtfファイルをapplyしようとしても、既にAで作られたtfstateファイルを検知できず、リソースが二重にapplyされかねない。

# test/vpc
terraform plan
...
Plan: 2 to add, 0 to change, 0 to destroy.

このような場合、 terraform import を使って既存リソースの情報を取り込んでおく必要がある。
import コマンドは ADDRESSID の2つの引数を必須としている。 ADDRESS はtfファイル内で定義した resource のアドレスを指す。例えば test/vpc/vpc.tf内で my_vpc という名前でVPCリソースを定義していた場合、 aws_vpc.my_vpc と指定すればよい。(すなわち、 import コマンドで既存のリソースを取り込むには、そのリソースに対応するtfファイルをあらかじめ作成しておかなければならない)
ID の方は、作成済みのリソースを一意に識別できるようにプロバイダ上で割り振られた値を指す。値の確認方法は各プロバイダによるが、AWSVPCであれば VPC ID を、EC2であれば Instance ID を使う。これらはAWSのコンソールやaws cliを使って確認できる。
これらを使って terraform import を実行する。デフォルトではコマンドを実行したディレクトリにあるtfファイルが参照される。

# test/vpc
terraform import aws_vpc.my_vpc vpc-xxxxxxxxxxxxxxxxx
aws_vpc.my_vpc: Importing from ID "vpc-xxxxxxxxxxxxxxxxx"...
aws_vpc.my_vpc: Import prepared!
  Prepared aws_vpc for import
aws_vpc.my_vpc: Refreshing state... [id=vpc-xxxxxxxxxxxxxxxxx]

Import successful!

The resources that were imported are shown above. These resources are now in
your Terraform state and will henceforth be managed by Terraform.

terraform import aws_subnet.my_subnet subnet-xxxxxxxxxxxxxxxxx
aws_subnet.my_subnet: Importing from ID "subnet-xxxxxxxxxxxxxxxxx"...
aws_subnet.my_subnet: Import prepared!
  Prepared aws_subnet for import
aws_subnet.my_subnet: Refreshing state... [id=subnet-xxxxxxxxxxxxxxxxx]

Import successful!

The resources that were imported are shown above. These resources are now in
your Terraform state and will henceforth be managed by Terraform.

import コマンドを実行するたびに、tfファイルの backend 等で指定された保存場所にtfstateファイルが作成される。直後に terraform plan を行うと、差分がなくなっている。

# test/vpc
terraform plan
...
No changes. Infrastructure is up-to-date.

後はEC2の方も同様に行えば、余計な差分を生まずにtfstateファイルを移行できる。

import コマンドは、現時点(terraform v0.12.28 + provider.aws v2.68.0)ではあくまでtfstateファイルを変更するのみで、tfファイルの自動生成はしてくれない。これを補ってくれるOSSツールもあるようだが、 公式ドキュメントには A future version of Terraform will also generate configuration. と書いてあるので少しだけ期待している。