Zenn
🐕

IaC化はTerraform Importを使おう

2025/03/21に公開

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 の導入ステップ

  1. 既存リソースの確認
    • 例: AWS S3バケットを手動で作成する。(bucket名はexample-import-test-bucketとする。)
  2. 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するはぜひ参考にしてください
https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket#import

  1. terraform initterraform 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 の管理下に取り込まれます。

  1. 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 化を進めやすい
DELTAテックブログ

Discussion

ログインするとコメントできます