はじめに
Terraformを使ってみるとTerraformでコードを書く よりも 既存リソースをTerraformにインポートすることが結構あります。
公式のドキュメントを読めばやり方はわかります。
ただ、少しわかりづらい箇所もあるので細かい部分も説明しながらインポート手順を説明していきます
前提
- AWSアカウント作成済
- AWSリソース作成済(今回はこちらの記事で作成したlambda関数をリソースとして使用します。他のリソースでも構いません)
- terraform インストール済 (参考: https://dev.classmethod.jp/articles/beginner-terraform-install-mac/)
- terraformer インストール済 (参考: https://beyondjapan.com/blog/2020/05/terraformer-import-existing-infrastructure/)
ディレクトリ構成
root
┣━ test
┃ ┣━ provider.tf
┃ ┣━ terraform.tfvars
┃ ┗━ lambda.tf
┗━ .gitignore
インポートするための必要最低限のファイルとを用意します
.gitignoreはGiHub等にAWSのキーをpushしないためのファイルなのでローカルだけで作業する場合は不要です。
variable "aws_access_key" {}
variable "aws_secret_key" {}
provider "aws" {
access_key = var.aws_access_key
secret_key = var.aws_secret_key
region = "us-east-2"
}
# AWSのアクセスキーとシークレットキーを記述
aws_access_key = "xxxxxxxxxx"
aws_secret_key = "xxxxxxxxxx"
# ここにlambdaのリソースをインポートしていきます
# .tfstate files
*.tfstate
*.tfstate.*
# .tfvars files
*.tfvars
# terraformer import fils
*/generated/
インポート方法
Terraformで既存リソースをインポート
まずは terraform リソース名 でブラウザ検索してみましょう
今回はlambdaのリソースをインポートするので terraform lambdaで検索すると
Terraform公式のリンクが表示されます
https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_function

こちらのリンクに記載されているExample Usageの章を参考に最低限のリソースの雛形を書きます
# "test_lambda"の部分は任意の名前でOK
resource "aws_lambda_function" "test_lambda" {
}
これで雛形が完成です
次にインポートのコマンドを調べます
Importの章を確認しましょう
https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_function#import

ここにインポートの際に必要なコマンドが記載されています
$ terraform import aws_lambda_function.test_lambda my_test_lambda_function
こちらを解釈すると
$ terraform import aws_lambda_function.(インポート先の名前) (インポートしたいlambda関数の名前)
となります。
今回はインポート先の名前: test_lambda 、インポートしたいlambda関数の名前: start_stop_ec2_inatanceなのでそちらを使用してターミナル上でコマンド実行します
user@user test % terraform import aws_lambda_function.test_lambda start_stop_ec2_instance
aws_lambda_function.test_lambda: Importing from ID "start_stop_ec2_instance"...
aws_lambda_function.test_lambda: Import prepared!
Prepared aws_lambda_function for import
aws_lambda_function.test_lambda: Refreshing state... [id=start_stop_ec2_instance]
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 successful!のログが出れば成功です
インポートする際の注意点
一点注意して頂きたいのはリソースごとにインポートコマンドの書き方が異なります。
先ほどのlambdaの場合はコマンドの末尾にlambda関数の名前を入力していましたが、
例えばEC2インスタンスの場合は、以下のようにコマンドの末尾にはインスタンスのidを入力します
$ terraform import aws_instance.web i-12345678
参照:https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance#import
インポートのコマンドはリソースごとに調べて実行しましょう
Terraformerでtfファイルを出力
Terraformによるインポートが終わったら、Terraformerを使ってリソースの中身を書いていきます。
GitHubに必要なコマンドとリソース名が掲載されているのでこちらを使用します
https://github.com/GoogleCloudPlatform/terraformer/blob/master/docs/aws.md

基本的なコマンドは以下の通りです
$ terraformer import aws --resources=(リソース名) --regions=(リージョン名)
まずインポートしたいリソース名をGitHub上で検索します。
検索する理由はTerraformer上でのリソース名が一般的なリソース名を省略した形になっている場合があるからです
例えばsecurity_groupをインポートしたい場合、GitHub上で 検索するとsgで入力してね。と書いてあります

今回はlambdaをインポートしたいのでGitHub上で調べてみると、そのままlambdaがリソース名として使えそうです

リソース名がわかったらコマンドをターミナルで入力しましょう
user@user test % terraformer import aws --resources=lambda --regions=us-east-2
2021/09/07 09:05:11 aws importing region us-east-2
2021/09/07 09:05:14 aws importing... lambda
2021/09/07 09:05:16 aws done importing lambda
2021/09/07 09:05:16 Number of resources for service lambda: 1
2021/09/07 09:05:16 Refreshing state... aws_lambda_function.tfer--test_lambda
2021/09/07 09:05:19 Filtered number of resources for service lambda: 1
2021/09/07 09:05:19 aws Connecting....
2021/09/07 09:05:19 aws save lambda
2021/09/07 09:05:19 aws save tfstate for lambda
コマンドが成功すればgeneratedディレクトリが生成され、その中にlambda_function.tfファイルも生成されます
その中身を先ほど作成したlambda.tfファイルの雛形に書き写します
resource "aws_lambda_function" "test_lambda" {
environment {
variables = {
INSTANCE_ID = "i-xxxxxxxxxx"
}
}
function_name = "start_stop_ec2_instance"
handler = "lambda_function.lambda_handler"
memory_size = "128"
package_type = "Zip"
reserved_concurrent_executions = "-1"
role = "arn:aws:iam::xxxxxxxxxx:role/start_stop_instance_lambda"
runtime = "python3.8"
source_code_hash = "xxxxxxxxxxxxxxxxxxxx"
timeout = "3"
tracing_config {
mode = "PassThrough"
}
}
ここで一点注意して欲しいのがINSTANCE_ID = "i-xxxxxxxxxx"のようにハードコーディングされている箇所があることです
GitHub等にpushする際は変数化してハードコーディングを回避しましょう
インポートできたか確認
最後に既存リソースとTerraform上のリソースに差分がないかterraform planを実行して確認します
user@user test % terraform plan
aws_lambda_function.test_lanmbda: Refreshing state... [id=start_stop_ec2_instance]
No changes. Your infrastructure matches the configuration.
Terraform has compared your real infrastructure against your configuration and found no differences, so no changes are needed.
No changes. と出れば差分なくインポート完了です
終わり
今回はlambdaを使って既存リソースのインポートを行いました
他のリソースでも同様の手順でインポートできるのでぜひやってみてください