terraform importを使って既存リソース情報を取得(初めてのAzureでTerraform(3))

初めてのTerraform第3回になります。

Terraformを使うと、コードを使ったAzureリソースのデプロイ出来る事はわかったのですが、すでにAzure Portalを使ってデプロイしていたリソースの管理はどうなるのかが自分は分かりませんでした。

例えばデプロイ済みのリソースをTerraform使って削除や変更したいと言った場合はどうなるのでしょうか。

今回はこの疑問を解決すべくAzureリソースグループをサンプルにterraform importコマンドを使った既存のリソース構成情報取得(更新)をやってみました。リソース情報の取得だけではなく、変更削除等を行いたかったのでImportを利用しています。

※リソースを認識させるだけ(読み取り専用)であればDataブロックを利用する方法もあります。

スポンサーリンク

Terraformは構成をterraform.tfstateで管理している

Terraform自身で構成情報を管理している

Terraform自身がtfstateというファイルでリソースの構成を管理しています。Azure側のリソース構成をチェックしているわけではありません。(同期しているとかそういう事じゃないという意味です。)

terraform applyコマンド等でリソースの構成変更した場合にはこのtfstateファイルが更新されます。Terraform自身でAzure環境がこうなっているよと言う情報をtfstateファイルに保存します。(実際にファイルがterraformコマンド実行したディレクトリに存在します。)

ですが、Azure Portalでリソースをデプロイした場合には、Terraformでは何もしていないのでtfstateは更新されず、デプロイされたリソースの情報はTerraformには保管されません。

したがって、Terraformを使ってデプロイしていないリソースについてTerraformは認識していない状態になります。今回実施してみたように、すでにAzure上に存在するリソースであっても再度デプロイしようとします。(実際に実行するとすでにあるよとエラーになります。)

すでにAzure上にあるリソースはterraform importコマンドで認識させる

この状態を解決してリソースの状態を変更したりする場合は、TerraformにAzure上に存在する既存のリソースを認識させる必要があります。

具体的に言うと、Terraformが構成情報を管理しているtfstateファイルにデプロイされているリソースの情報を反映させる必要があります。

その為にTerraformではimportというコマンドが用意されています。なおリソースを認識させるだけであればDataモジュールを利用する方法もあります。

import(HashiCorp)

今回はterraform importコマンドをやってみます。

terraform importコマンドで既存リソース情報を取得

今回は以下の順番で確認してみました。

      • terraform importコマンドを実行せずに同じ名前のリソースグループをapply(デプロイ)
      • terraform importコマンドを実行
      • 同じ名前のリソースグループをplanで確認
      • terraform destroyでリソースグループを削除

今回作成したTerraformの設定ファイル一覧

terraform importコマンドを試すにあたって作成したファイルは6つになります。1つのディレクトリにすべてのファイルを置いています。

※1つのファイルに纏めても問題ないです。

作成したファイル
Terraform自体の設定ファイル

main.tf

required_providersを指定しています。Terraformがどのプロバイダー(Azure等)を利用するのか指定します。

Provider Requirements(Terraform)

※0.13以降で登場したようです。

provider.tf

デプロイするproviderを指定しています。Azureのリソースをデプロイする事を宣言しています。

デプロイするサブスクリプションやテナントをはproviderの宣言の中で指定します。

version.tf Terraform自体のVersionを指定しています。Terraform自体がVerにより挙動が異なる為、このVerを使用しているよと指定します。
変数定義や設定値関連の設定ファイル

variable.tf

変数を定義しています。今回はリソースグループに関する変数を定義しています。

terraform.tfvars

設定値を記載しています。今回はリソースグループに関する設定値を記載しています。

リソースに関するテンプレートファイル
rg_01.tf リソースグループに関するテンプレートファイル。ファイル名は任意です。

実際に作成したファイルの内容になります。main.tf、provider.tf、version.tfについては第一回参照ください。

設定ファイル
  • 作成条件
    • リソースグループ名は、test-rgとする
    • ロケーションはeastus2(米国東部2)とする

【rg-01.tf

var.rg-nameでリソースグループ名、 var.rg-locationでロケーションの変数を呼び出しています。rg-01としていますが、ここは任意の値で問題ないです。(すみません。命名規則のベストプラクティスでは_(アンダースコア)利用が推奨されているそうです。)

resource “azurerm_resource_group" “rg-01" {
  name     = var.rg-name
  location = var.rg-location
}

importコマンド実行は、このように空で作成しても問題はございません。今回はapplyしてエラーを確認する為にapply可能なように値を設定した形で作成しております。

resource “azurerm_resource_group" “rg-01" {
}

【variable.tf

variable.tfで変数を定義しています。変数名は任意です。今回はリソースグループ名をrg-name、ロケーションをrg-locationとして変数定義しています。

/*リソースグループ*/
variable “rg-name" {}
variable “rg-location" {}

【terraform.tfvars】

terraform.tfvarsで設定値を定義しています。設定値は任意です。今回はリソースグループ名をtest-rg、ロケーションをeastus2としています。

/*リソースグループ*/

rg-name        = “test-rg"
rg-location    = “eastus2"

terraform importをせずに同じ名前のリソースグループをデプロイ

Terraformを使って同じ名前のリソースグループをデプロイしてみます。

デプロイ作業

事前にAzure Portalを利用してtest-rgと言う名前でリソースグループをデプロイしておきます。

terraform initを実行します。

PS C:\terraform> terraform init

Initializing the backend…

Initializing provider plugins…
– Using previously-installed hashicorp/azurerm v2.46.0

Terraform has been successfully initialized!

<以下略>

terraform applyを実行してみます。最初のPlan時点ではエラーや変更無しにはなりませんでした。メッセージからリソース作成時にすでにリソースがある為にエラーになっている事が確認出来ました。

PS C:\terraform> terraform apply

+ create

Terraform will perform the following actions:

# azurerm_resource_group.rg-01 will be created
+ resource “azurerm_resource_group" “rg-01" {
+ id = (known after apply)
+ location = “eastus2"
+ name = “test-rg"
}

Plan: 1 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

azurerm_resource_group.rg-01: Creating…
?
│ Error: A resource with the ID
“/subscriptions/サブスクリプションID/resourceGroups/test-rg"

already exists – to be managed via Terraform this resource needs to be imported
into the State.Please see the resource documentation for
“azurerm_resource_group" for more information.


│ with azurerm_resource_group.rg-01,
│ on rg_01.tf line 1, in resource “azurerm_resource_group" “rg-01":
│ 1: resource “azurerm_resource_group" “rg-01" {

terraform importを実行する

エラーになる事が確認出来たので、次はterraform importコマンドを実行してみます。

terraform import

terraform importコマンド実行時に利用するリソースIDをコピーします。リソースIDはプロパティ内にあります。

terraform importを実行します。コマンドは”terraform import テンプレートのリソースタイプとリソース名、(“azurerm_resource_group" “rg-01″部分) リソースID(Azure上のリソースID)”になります。

コマンド実行結果を見るとImport successful!と表示されておりimportが成功した事が分かります。

PS C:\terraform>terraform import azurerm_resource_group.rg-01 /subscriptions/サブスクリプションID/resourceGroups/test-rg

azurerm_resource_group.rg-01: Importing from ID “/subscriptions/サブスクリプションID/resourceGroups/test-rg"…azurerm_resource_group.rg-01: Import prepared!
Prepared azurerm_resource_group for import
azurerm_resource_group.rg-01: Refreshing state… [id=/subscriptions/サブスクリプションID/resourceGroups/test-rg]

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.tfstateと言うファイル内に、リソースグループの状態が記録されている事が分かります。(第一回でTerraformを使ってリソースグループを作成した場合と同様に出来ています。)

terraform import実行後にplanを実行してみる

terraform plan

terraform planを実行します。すでにリソースがあるから変更がないよと言うメッセージが表示されており、Terraformで認識されている事が分かりました。

PS C:\terraform> terraform plan
azurerm_resource_group.rg-01: Refreshing state… [id=/subscriptions/サブスクリプションID/resourceGroups/test-rg]

No changes. Infrastructure is up-to-date.

This means that Terraform did not detect any differences between your configuration and the remote system(s). As a result,
there are no actions to take.

最後にterraform destroyでリソースグループを削除する

最後にTerraformで管理されている事を確認する為に、terraform destroyでリソースグループを削除してみます。

terraform destroy

terraform destroyを実行しリソースグループを削除してみます。Destroy complete!となっており、Azure Portalで作成したリソースグループをTerraform使って削除できました。

PS C:\terraform> terraform destroy
azurerm_resource_group.rg-01: Refreshing state… [id=/subscriptions/サブスクリプションID/resourceGroups/test-rg]

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the
following symbols:
– destroy

Terraform will perform the following actions:

# azurerm_resource_group.rg-01 will be destroyed
– resource “azurerm_resource_group" “rg-01" {
– id = “/subscriptions/サブスクリプションID/resourceGroups/test-rg" -> null
– location = “eastus2" -> null
– name = “test-rg" -> null
– tags = {} -> null

– timeouts {}
}

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

Do you really want to destroy all resources?
Terraform will destroy all your managed infrastructure, as shown above.
There is no undo. Only 'yes’ will be accepted to confirm.

Enter a value: yes

azurerm_resource_group.rg-01: Destroying…

Destroy complete! Resources: 1 destroyed.

terraform importコマンドを利用する事で、Azure Portal等で作成したリソースもTerraformで管理できるようになることが分かりました。