【大阪 / 横浜】インフラ / サーバーサイドエンジニア募集中!

【大阪 / 横浜】インフラ / サーバーサイドエンジニア募集中!

【導入実績 500社以上】AWS 構築・運用保守・監視サービス

【導入実績 500社以上】AWS 構築・運用保守・監視サービス

【圧倒的 低コスト】Oracle Cloud 構築・運用保守・監視サービス

【圧倒的 低コスト】Oracle Cloud 構築・運用保守・監視サービス

【WordPress専用】高速 クラウド / サーバー『WebSpeed』

【WordPress専用】高速 クラウド / サーバー『WebSpeed』

【低コスト】Wasabi オブジェクトストレージ 構築・運用サービス

【低コスト】Wasabi オブジェクトストレージ 構築・運用サービス

【100URLの登録が0円】Webサイト監視サービス『Appmill』

【100URLの登録が0円】Webサイト監視サービス『Appmill』

【SNSアプリ開発】LINE カスタムアプリ開発サービス

【SNSアプリ開発】LINE カスタムアプリ開発サービス

【ECアプリ開発】Shopify カスタムアプリ開発サービス

【ECアプリ開発】Shopify カスタムアプリ開発サービス

【音声アプリ開発】Twilio カスタムアプリ開発サービス

【音声アプリ開発】Twilio カスタムアプリ開発サービス

【グローバル対応】北米リージョン・クラウド / サーバー サポート

【グローバル対応】北米リージョン・クラウド / サーバー サポート

【取材記事】サーバーサイド・バックエンドエンジニアを募集中

【取材記事】サーバーサイド・バックエンドエンジニアを募集中

【YouTube】ビヨンド公式チャンネル「びよまるチャンネル」

【YouTube】ビヨンド公式チャンネル「びよまるチャンネル」

Terraformで既存のインフラリソースをインポートする方法

インフラエンジニアの寺岡です。
皆さんは「既存のインフラ構成もTerraformで管理できるようにしたい」と考えたことはないでしょうか。
Terraformではそれを実現するコマンドが用意されているのでこの記事で紹介します。

事前にTerraformを利用せずにVPCを1つ作成しておきました。

今回はこちらをTerraformにインポートしてみます。

ディレクトリ構成

$ tree
.
├── README.md
├── provider.tf
├── terraform.tfstate
├── variables.tf
└── vpc.tf

0 directories, 5 files

providerとvariableを記述する

インポートする前にproviderとvariableは最低限必要なので記述します。

provider.tf

provider "aws" {
  access_key = var.access_key
  secret_key = var.secret_key
  region     = var.region

  assume_role {
    role_arn = var.role_arn
  }
}

variables.tf

####################
# Provider
####################
variable "access_key" {
  description = "AWS Access Key"
}

variable "secret_key" {
  description = "AWS Secret Key"
}

variable "role_arn" {
  description = "AWS Role Arn"
}

variable "region" {
  default = "ap-northeast-1"
}

AWSのアクセスキーなどは環境変数に保存しておきましょう。

$ export TF_VAR_access_key=XXXXXXXXXXXXXXXXXXXX
$ export TF_VAR_secret_key=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
$ export TF_VAR_role_arn=arn:aws:iam::XXXXXXXXXXXX:role/XXXXXXXXXXXXXXXXXXX

planを実行する

試しにPlanを実行します。
今は何もインポートしていないので「No changes.」で実行が終わります。

$ terraform plan
Refreshing Terraform state in-memory prior to plan...
The refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state storage.


------------------------------------------------------------------------

No changes. Infrastructure is up-to-date.

This means that Terraform did not detect any differences between your
configuration and real physical resources that exist. As a result, no
actions need to be performed.

importを実行する

Terraformで既存リソースをインポートする場合は「terraform import」コマンドを実行します。
コマンドの書式はTerraformのマニュアル(※1)に記載があるのでそちらを参考にして以下のコマンドを実行します。

$ terraform import aws_vpc.vpc vpc-09a9f1827bfd851f4
Error: resource address "aws_vpc.vpc" does not exist in the configuration.

Before importing this resource, please create its configuration in the root module. For example:

resource "aws_vpc" "vpc" {
  # (resource arguments)
}

エラーが出てしまいました。
インポートするときは「aws_vpc.vpc」のようにリソースの種類と名前を指定することになり
ここで指定したtfファイル上のリソースに対して既存リソースの情報がインポートされることになります。
そのため、予め対応するリソースをtfファイルに記述しておく必要があります。

vpcリソースを記述する

以下のように記載しておきます。

vpc.tf

####################
# VPC
####################
resource "aws_vpc" "vpc" {
  cidr_block           = "10.0.0.0/16"
  enable_dns_support   = true
  enable_dns_hostnames = true

  tags = {
    Name = "vpc-tfstate-test"
  }
}

再度importを実行する

再度実行してみます。
今度は問題なくインポートできましたね。

$ terraform import aws_vpc.vpc vpc-09a9f1827bfd851f4
aws_vpc.vpc: Importing from ID "vpc-09a9f1827bfd851f4"...
aws_vpc.vpc: Import prepared!
  Prepared aws_vpc for import
aws_vpc.vpc: Refreshing state... [id=vpc-09a9f1827bfd851f4]

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は何をやってくれているのでしょうか。
コマンドを実行すると「terraform.tfstate」という名前のファイルが作成されていることがわかります。

terraform.tfstate

{
  "version": 4,
  "terraform_version": "0.12.24",
  "serial": 1,
  "lineage": "c0359eb1-d905-e252-2d8d-525710adddb1",
  "outputs": {},
  "resources": [
    {
      "mode": "managed",
      "type": "aws_vpc",
      "name": "vpc",
      "provider": "provider.aws",
      "instances": [
        {
          "schema_version": 1,
          "attributes": {
            "arn": "arn:aws:ec2:ap-northeast-1:485076298277:vpc/vpc-09a9f1827bfd851f4",
            "assign_generated_ipv6_cidr_block": false,
            "cidr_block": "10.0.0.0/16",
            "default_network_acl_id": "acl-0cd8abfed52e0e951",
            "default_route_table_id": "rtb-08c13269b1b26c9b8",
            "default_security_group_id": "sg-007ef29e563b6f9c7",
            "dhcp_options_id": "dopt-6c0f430b",
            "enable_classiclink": false,
            "enable_classiclink_dns_support": false,
            "enable_dns_hostnames": true,
            "enable_dns_support": true,
            "id": "vpc-09a9f1827bfd851f4",
            "instance_tenancy": "default",
            "ipv6_association_id": "",
            "ipv6_cidr_block": "",
            "main_route_table_id": "rtb-08c13269b1b26c9b8",
            "owner_id": "485076298277",
            "tags": {
              "Name": "vpc-tfstate-test"
            }
          },
          "private": "eyJzY2hlbWFfdmVyc2lvbiI6IjEifQ=="
        }
      ]
    }
  ]
}

中身を見ると先ほどインポートしたリソースの情報が保存されていますね。
Terraformは実行したときに新規作成 or 変更 or 削除を自動で判断してリソースを作成してくれますが
この判断は実行時に読み込んだtfファイルとtfstateに書かれている内容の差分を元に行われています。
つまり、指定した既存リソースをTerraform上で管理するためにはtfstateの内容を変更する必要があり
「指定した既存リソースの情報を読み込みtfstateに追加してくれるコマンド」がterraform importです。

再度planを実行する

terraform importを実行したので再度planを実行してみましょう。

$ terraform plan
Refreshing Terraform state in-memory prior to plan...
The refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state storage.

aws_vpc.vpc: Refreshing state... [id=vpc-09a9f1827bfd851f4]

------------------------------------------------------------------------

No changes. Infrastructure is up-to-date.

This means that Terraform did not detect any differences between your
configuration and real physical resources that exist. As a result, no
actions need to be performed.

aws_vpc.vpcがTerraform上のリソースとして読み込まれていますね。
enable_dns_hostnamesをfalseに変更してみましょう。

$ terraform plan
Refreshing Terraform state in-memory prior to plan...
The refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state storage.

aws_vpc.vpc: Refreshing state... [id=vpc-09a9f1827bfd851f4]

------------------------------------------------------------------------

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  ~ update in-place

Terraform will perform the following actions:

  # aws_vpc.vpc will be updated in-place
  ~ resource "aws_vpc" "vpc" {
        arn                              = "arn:aws:ec2:ap-northeast-1:485076298277:vpc/vpc-09a9f1827bfd851f4"
        assign_generated_ipv6_cidr_block = false
        cidr_block                       = "10.0.0.0/16"
        default_network_acl_id           = "acl-0cd8abfed52e0e951"
        default_route_table_id           = "rtb-08c13269b1b26c9b8"
        default_security_group_id        = "sg-007ef29e563b6f9c7"
        dhcp_options_id                  = "dopt-6c0f430b"
        enable_classiclink               = false
        enable_classiclink_dns_support   = false
      ~ enable_dns_hostnames             = true -> false
        enable_dns_support               = true
        id                               = "vpc-09a9f1827bfd851f4"
        instance_tenancy                 = "default"
        main_route_table_id              = "rtb-08c13269b1b26c9b8"
        owner_id                         = "485076298277"
        tags                             = {
            "Name" = "vpc-tfstate-test"
        }
    }

Plan: 0 to add, 1 to change, 0 to destroy.

------------------------------------------------------------------------

Note: You didn't specify an "-out" parameter to save this plan, so Terraform
can't guarantee that exactly these actions will be performed if
"terraform apply" is subsequently run.

差分のみを変更しようとする挙動になっていますね。

まとめ

importコマンドの説明ページ(※2)にも記載されていますが
コマンドで書き換えてくれるのはあくまで「tfstateのみ」です。
つまり、実際のtfファイルについてはtfstateとの差分を見ながら自身で記述する必要があります。
将来的にはtfファイルも自動生成されるように機能追加されるようですが
現在のところは対象が多ければ多いほど辛くなってきます。。。

それを解決するためにterraformer(※3)がOSSとして公開されています。
次回はこちらの使い方をブログにまとめようと思います。

参考URL

※1 https://www.terraform.io/docs/providers/aws/r/vpc.html
※2 https://www.terraform.io/docs/import/index.html
※3 https://github.com/GoogleCloudPlatform/terraformer

この記事がお役に立てば【 いいね 】のご協力をお願いいたします!
0
読み込み中...
0 票, 平均: 0.00 / 10
31,570
facebook twitter はてなブックマーク
【大阪 / 横浜】インフラエンジニア / サーバーサイドエンジニア 積極採用中!

【大阪 / 横浜】インフラエンジニア / サーバーサイドエンジニア 積極採用中!

この記事をかいた人

About the author

寺岡佑樹

2016年ビヨンド入社、現在6年目のインフラエンジニア
MSPの中の人として障害対応時のトラブルシューティングを行いながら
AWSなどのパブリッククラウドを用いたインフラの設計/構築も行っている。
最近はDockerやKubernetesなどのコンテナ基盤の構築や
運用自動化の一環としてTerraformやPackerなどのHashicorpツールを扱うことが多く
外部の勉強会やセミナーで登壇するEvangelistの役割も担っている。

・GitHub
https://github.com/nezumisannn

・登壇経歴
https://github.com/nezumisannn/my-profile

・発表資料(SpeakerDeck)
https://speakerdeck.com/nezumisannn

・所有資格
AWS Certified Solutions Architect - Associate
Google Cloud Professional Cloud Architect