IaC化はTerraform Importを使おう
IaC化はTerraform Importを使おう
はじめに
近年、インフラ業界では IaC 化 がスタンダードになりつつあります。
初めはスピード重視で、AWS などのサービスをコンソール操作で構築していたとしても、サービスが成長するにつれインフラが複雑化しがちです。
インフラを触る人数が増えると、「誰がどこをいつ変更したのかがわからない」 といった問題も生じます。
この状況を変えるのが IaC 化 です。
IaC 化によって、インフラのどのリソースを誰がいつ変更したのかを 容易に追跡できる ようになり、コードレビューも可能になるという大きなメリットがあります。
下記のようにIaCに特化したサービスなども出てきています。
IaC booster
本記事では、既存のインフラを IaC 化したい場合に有用な Terraform Import 機能についてお話しします。
1. Terraform Importについて
Terraform には、既存リソースを管理下に取り込むための terraform import
という機能があります。
- Terraform Import ブロックはバージョン1.5 以降でサポートされた機能です。
- HCL コードでインポート内容を明示 でき、コードレビューや履歴管理が容易になります。
- 「いつ、誰が、どのリソースをインポートしたか」をチーム全員で共有しやすい、というメリットがあります。
- CI/CD と相性抜群で、自動テストの中で
terraform plan
などを回して、Import Block の設定が正しいか検証可能
2. 実際にやってみる:Import の導入ステップ
-
既存リソースの確認
- 例: AWS S3バケットを手動で作成する。(bucket名は
example-import-test-bucket
とする。)
- 例: AWS S3バケットを手動で作成する。(bucket名は
- Terraform リソース定義
#サンプルコード
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
provider "aws" {
region = "ap-northeast-1"
}
resource "aws_s3_bucket" "example" {
bucket = "example-import-test-bucket"
}
import {
to = aws_s3_bucket.example
id = "example-import-test-bucket"
}
importするresourceのidと取り込むresource名を指定します。
importの記述の仕方はterraformの公式ドキュメントのresource定義の下の方に載っていますので、importするはぜひ参考にしてください
-
terraform init
→terraform plan
を実行
上記のファイルを用意したら、まずはterraform init
を実行します。
続いてterraform plan
を実行すると、既存の S3 バケットをインポート予定であることが表示されます。
$ terraform plan
aws_s3_bucket.example: Preparing import... [id=example-import-test-bucket]
aws_s3_bucket.example: Refreshing state... [id=example-import-test-bucket]
Terraform will perform the following actions:
# aws_s3_bucket.example will be imported
resource "aws_s3_bucket" "example" {
acceleration_status = null
arn = "arn:aws:s3:::example-import-test-bucket"
bucket = "example-import-test-bucket"
bucket_domain_name = "example-import-test-bucket.s3.amazonaws.com"
bucket_prefix = null
bucket_regional_domain_name = "example-import-test-bucket.s3.ap-northeast-1.amazonaws.com"
hosted_zone_id = "Z2M4EHUR26P7ZW"
id = "example-import-test-bucket"
object_lock_enabled = false
policy = null
region = "ap-northeast-1"
request_payer = "BucketOwner"
tags = {}
tags_all = {}
grant {
id = "xxxx"
permissions = [
"FULL_CONTROL",
]
type = "CanonicalUser"
uri = null
}
server_side_encryption_configuration {
rule {
bucket_key_enabled = true
apply_server_side_encryption_by_default {
kms_master_key_id = null
sse_algorithm = "AES256"
}
}
}
versioning {
enabled = false
mfa_delete = false
}
}
Plan: 1 to import, 0 to add, 0 to change, 0 to destroy.
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Note: You didn't use the -out option to save this plan, so Terraform can't guarantee to take exactly these actions if
you run "terraform apply" now.
$
上記のように Plan: 1 to import と表示されていれば、Terraform が既存バケットをインポートしようとしていることがわかります。
resourceとして何を取り込むのか、明確にわかります。(余裕があれば、argumentも実際の取り込むものに合わせて書いておくと良いでしょう)
この状態で terraform apply を実行すると、実際にバケットが Terraform の管理下に取り込まれます。
- terraform applyを実行する
$ terraform apply
aws_s3_bucket.example: Preparing import... [id=example-import-test-bucket]
aws_s3_bucket.example: Refreshing state... [id=example-import-test-bucket]
Terraform will perform the following actions:
# aws_s3_bucket.example will be imported
resource "aws_s3_bucket" "example" {
acceleration_status = null
arn = "arn:aws:s3:::example-import-test-bucket"
bucket = "example-import-test-bucket"
bucket_domain_name = "example-import-test-bucket.s3.amazonaws.com"
bucket_prefix = null
bucket_regional_domain_name = "example-import-test-bucket.s3.ap-northeast-1.amazonaws.com"
hosted_zone_id = "Z2M4EHUR26P7ZW"
id = "example-import-test-bucket"
object_lock_enabled = false
policy = null
region = "ap-northeast-1"
request_payer = "BucketOwner"
tags = {}
tags_all = {}
grant {
id = "xxxx"
permissions = [
"FULL_CONTROL",
]
type = "CanonicalUser"
uri = null
}
server_side_encryption_configuration {
rule {
bucket_key_enabled = true
apply_server_side_encryption_by_default {
kms_master_key_id = null
sse_algorithm = "AES256"
}
}
}
versioning {
enabled = false
mfa_delete = false
}
}
Plan: 1 to import, 0 to add, 0 to change, 0 to destroy.
Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value: yes
aws_s3_bucket.example: Importing... [id=example-import-test-bucket]
aws_s3_bucket.example: Import complete [id=example-import-test-bucket]
Apply complete! Resources: 1 imported, 0 added, 0 changed, 0 destroyed.
これで既存リソースをterraform配下に取り込むことができました。
このimportが良い点は2つあります。
- planが実行できる→ リソースの差分や構成を確認しながらインポートできる。
- コードにimportするという宣言ができる→ PR レビュー時にインポート対象を明確に示すことができる
どちらもレビューやチーム開発の観点で大きく役立つポイントです。
3. CI への応用
-
自動検証: GitHub Actions など で
terraform validate
/terraform plan
を自動実行し、Import の設定やPlanの内容も含めて差分やエラーをチェックできる。 - コードレビューの効率化: Import対象を PR 上で明確に示せるため、レビュー時にリソースIDや設定ミスを早期発見できる。(一度Importしたあとは、importブロックのコードは必要なくなるので、消しても良い。)
- 変更履歴の管理: 履歴管理・テスト結果・誰が何をインポートしたかを一元的に追跡しやすい
4. まとめ
- Terraform Import は、既存リソースを コード管理化 する際に非常に有効
- レビュー・履歴管理・自動化 で大きなメリットがある
- これから IaC 化を進める場合は、早めに Import を取り入れて、チーム全体で運用をスムーズに進めることができる
- 「Import + CI/CD」運用を確立すれば、チームで属人化を防ぎながら IaC 化を進めやすい
Discussion