Terraform

Terraformerを使用して既存のAWS環境をエクスポートする

Terraformを導入するにあたって、まっさらなゼロからソースを書き始めるよりかは、まずサンプルやたたき台があったほうが始めやすいと思います。

AWSコンソールからポチポチと構築した環境をそのままエクスポートしてTerraformコードに落とし込めると、AWSの画面とコードを具体的に比較でき、とても理解しやすくなります。

そこで自分はTerraformerというツールを使用しました。

既存環境をエクスポートする手法は他にもありましたがコマンド一発でサクッとできそう、かつGoogleが買収した会社のSREチーム作成ということで信頼性も高そうだったのでこちらを選択しました。

スポンサーリンク

エクスポート手順

事前準備

Terraformのプラグインが必要になるため、こちらの記事を参考にTerraformをインストールし、作業ディレクトリで terraform init を実行しpluginをダウンロードします。

% cd workdir
% cat main.tf 
terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 3.0"
    }
  }
}
%
% terraform init
%
## pluginがダウンロードされる
% find .terraform/ -type f
.terraform/plugins/registry.terraform.io/hashicorp/aws/3.21.0/darwin_amd64/terraform-provider-aws_v3.21.0_x5
%


作業ディレクトリ関係なく、どのディレクトリにいても共通でプラグインを使用したい場合(=都度ダウンロードする必要がない)は、ホームディレクトリの~/.terraform.d/plugins にコピーしておきましょう。

## ~/.terraform.dがない場合は作成。
% ls -d ~/.terraform.d || mkdir ~/.terraform.d
% 
## ディレクトリ作成しつつコピーしたいのでrsync
% rsync -av .terraform/plugins/registry.terraform.io/hashicorp/aws/3.21.0/darwin_amd64 ~/.terraform.d/plugins
%


なおLinuxの一般ユーザーで terraform init をすると、.terraform/providers ディレクトリにプラグインがダウンロードされる場合があり、terraformerがエラーとなります。(.terraform/pluginsじゃないと認識しないっぽい)。

この場合もホームディレクトリの~/.terraform.d/plugins にコピーしておきましょう。

$ find .terraform/ -type f
.terraform/providers/registry.terraform.io/hashicorp/aws/3.21.0/linux_amd64/terraform-provider-aws_v3.21.0_x5
$
## ~/.terraform.dがない場合は作成。
$ ls -d ~/.terraform.d || mkdir ~/.terraform.d
$ 
## ディレクトリ作成しつつコピーしたいのでrsync
$ rsync -av  .terraform/providers/registry.terraform.io/hashicorp/aws/3.21.0/linux_amd64 ~/.terraform.d/plugins
$

インストール

Linux

パッケージはないのでバイナリファイルを直接ダウンロードします。

$ export PROVIDER=aws
$ curl -LO https://github.com/GoogleCloudPlatform/terraformer/releases/download/$(curl -s https://api.github.com/repos/GoogleCloudPlatform/terraformer/releases/latest | grep tag_name | cut -d '"' -f 4)/terraformer-${PROVIDER}-linux-amd64  
$ chmod +x terraformer-${PROVIDER}-linux-amd64
$ sudo mv terraformer-${PROVIDER}-linux-amd64 /usr/local/bin/terraformer
$

Mac

Homebrew でインストールできます。

% brew install terraformer  
%

コマンド

エクスポート(というかローカルへのインポート)は terraformer import [プロバイダー] [コマンド|オプション] が基本構文になります。

なお本記事ではAWSしか利用しませんが指定できるプロバイダーは多数あり terraformer import -h で確認できます。

list

listコマンドでエクスポート可能なAWSのサービス名を確認できます。

注意点としてすべてのサービスが利用できるわけではありません。たとえばdocumentdbなどはありません。(なぜだ。。)

% terraformer import aws list
accessanalyzer
acm
alb
...

%

-r (–resources) / -x (–excludes) / –profile

-r でエクスポートするAWSのサービスを指定します。とりあえず全部取得したい場合は “*”を指定します。
-x で除外することもできます。
–profile でAWSCLIの名前付きプロファイルを指定できます。

% terraformer import aws -r=ec2_instance,vpc,subnet 
...

## プロファイルで設定していれば、リージョンは明示的に指定しなくても大丈夫です
% terraformer import aws -r=ec2_instance,vpc,subnet --profile=hoge --regions=ap-northeast-1
...

% terraformer import aws -r="*" -x=ec2_instance --profile=hoge 
...

## デフォルトではgenerated というディレクトリに出力されます。
% ls 
generated	main.tf
%

-C (–compact) / -p (–path-pattern)

-Cでresrouoce type毎に分割してできる複数の出力ファイルをresources.tf というひとつファイルにまとめます。結果に検索かけるときなどありがたいかも。

% terraformer import aws -r=alb
...

% 
% find generated -type f 
generated/aws/alb/outputs.tf
generated/aws/alb/terraform.tfstate
generated/aws/alb/lb.tf                          ...resrouoce type毎に出力される
generated/aws/alb/lb_target_group.tf             ...resrouoce type毎に出力される
generated/aws/alb/lb_listener.tf                 ...resrouoce type毎に出力される
generated/aws/alb/lb_target_group_attachment.tf  ...resrouoce type毎に出力される
generated/aws/alb/variables.tf
generated/aws/alb/provider.tf
% 
% rm -rf generated
%
% terraformer import aws -r=alb -C 
...

% find generated -type f 
generated/aws/alb/outputs.tf
generated/aws/alb/terraform.tfstate
generated/aws/alb/resources.tf                  ...すべてのresrouoce typeがまとめて出力される
generated/aws/alb/variables.tf
generated/aws/alb/provider.tf
% 


-pで出力ディレクトリを操作します。デフォルトでは {output}/{provider}/{service}/{resource}.tf として出力されます。-Cと併用できるためすべてをまとめることもできます。

% terraformer import aws -r=ec2_instance,vpc,subnet
%
## デフォルトはディレクトリが細分化されて出力されます
% find generated -type f
generated/aws/alb/outputs.tf
generated/aws/alb/terraform.tfstate
...
generated/aws/ec2_instance/variables.tf
generated/aws/ec2_instance/provider.tf
...
generated/aws/vpc/resources.tf
generated/aws/vpc/provider.tf
generated/aws/vpc/vpc.tf
...
generated/aws/subnet/provider.tf
generated/aws/subnet/subnet.tf
% 
% rm -rf generated
%
## ディレクトリまとめてみる
% terraformer import aws -r=ec2_instance,vpc,subnet -p {output}/{provider} 
% find generated -type f
...
generated/aws/provider.tf
generated/aws/subnet.tf
generated/aws/instance.tf
generated/aws/vpc.tf
%
% rm -rf generated
%
## resources.tfに全部まとめてみる
% terraformer import aws -r=ec2_instance,vpc,subnet -p {output} -C
% find generated -type f
generated/outputs.tf
generated/terraform.tfstate
generated/resources.tf
generated/variables.tf
generated/provider.tf
%

-f (–filter)

リソースIDや属性でフィルタリングできます。属性はawsプロバイダーのものを指定するようです。

## タグ名が Name で値が dev-server1 か dev-server2 で絞る。
## このように条件が複数ある場合は:で分けます
% terraformer import aws -r=ec2_instance,vpc,subnet -f="Name=tags.Name;Value=dev-server1:dev-server2"
%
## Typeで EC2を指定してタグで絞る
% terraformer import aws -r=ec2_instance,vpc,subnet -f="Type=ec2_instance;Name=tags.Name;Value=dev-server1:dev-server2"
%
## vpc idで絞る
% terraformer import aws -r=vpc -f=vpc=vpc-0e9xxxxxe486a
%
## instance idで絞る
% terraformer import aws -r=ec2_instance -f=instance=i-0c5cexxxxxx58f92
%

Terraformer以外でのエクスポート

既存環境をエクスポートする方法は、Terraformer以外にも以下の選択肢があります。

Terraform自体のサブコマンド import

Terraformサブコマンドのimport ですが、これはコードを自動生成するものではなくTerraformの状態ファイル(.tfstate)を生成するものとなります。最終的にはその状態ファイルの内容を元に自分でコード化する必要があります。

またエクスポートするためには対象のリソースをあらかじめTerraformのコードとして枠だけ作成しておく必要があり、事前準備が大変そうだったので見送りました。

(追記:Terraformに慣れてくるとimportコマンドも使いやすかったです。以下の記事にまとめました。)

Terraforming

こちらのツールになります。ただ、自分が利用しているECSに対応しておらず、記事作成時点で最後のコミットが2019年7月となっておりメンテされてなさそうだったので見送りました。

参考

(´・ω・`)ゞアリガトゴザイマス.。.・゚

Github GoogleCloudPlatform/terraformer
Terraformerを使ってTerraformに既存インフラのリソースをインポートする