情報畑でつかまえてロゴ
本サイトは NTTテクノクロスが旬の IT をキーワードに
IT 部門が今知っておきたい最新テクノロジーに関する情報をお届けするサイトです

Terraform連載 第6回:Terraform v1.7 removedブロックの紹介

Terraform連載企画!v1.7で追加されると思われる機能から「removedブロック」をご紹介します

terraform_banner.png

はじめに

こんにちは、NTTテクノクロスの岩瀨です。

Terraformの紹介ブログ6回目です。今回はTerraform v1.7で追加されると思われる機能からremovedブロックをピックアップして紹介してみようと思います。

なお執筆時点(202312月中旬)ではv1.7pre-releaseのため、正式版では本記事の内容とは差異がある可能性がありますので、ご了承ください。

本記事は、v1.7.0-beta2を用いて検証を行います。

関連記事:
Terraform連載 第1回:いまさら聞けない、IaCってなに?~Terraform、IaSQLの紹介~
Terraform連載 第2回:Terraform v1.5の紹介&活用方法について考えてみた
Terraform連載 第3回:Terraform v1.6のtestコマンドについてご紹介
Terraform連載 第4回:for_eachの使い方
Terraform連載 第5回:module(モジュール)の紹介
「Terraform連載 第6回:Terraform v1.7 removedブロックの紹介」
Terraform連載 第7回:importブロックはmoduleのリソースも取り込めるか?
Terraform連載 第8回:Terraformの管理スコープとしてiDRACをimportしてみた

v1.7のremovedブロックとは

removedブロックにより、Terraformのコードを用いて、Terraform管理対象のリソースを管理外にすることができるようになります。

これまでTerraformで作成したリソースをTerraform管理外にするには、terraform state rmコマンドを使ってリソースを1つずつ管理外にする手順となっていました。

terraform state rmコマンドを使った場合の課題としては、tfstateから該当リソースの情報が削除された(=Terraform管理外になった)ことが記録に残らない事が挙げられます。コマンドのミスなどで誤ったリソースを管理外にしても、その変更が記録されず追跡できない、というわけです。

removedブロックを使った場合はTerraformのコードに管理外にすることが明示されますので、Gitなどの構成管理ツールによる追跡が行えるようになります。

また、モジュールごと管理外にする場合など管理外にするリソース数が多数ある場合、そのリソースの数だけterraform state rmコマンドを繰り返し実行する必要がありましたが、これも1回のapplyでまとめて管理外にすることもできるようになります。

removedブロックを使ってみる

では実際にremovedブロックを使ってみます。

環境は前回のmodule紹介記事で作成したnetworkモジュールで作成したリソースをTerraform管理外にしてみます。

準備:Terraformバージョンの確認

冒頭でも説明した通り、今回はv1.7.0-beta2を使用しています。

[bash]

$ terraform --version 
Terraform v1.7.0-beta2
on linux_amd64
+ provider registry.terraform.io/hashicorp/aws v5.31.0

準備:検証用のリソース作成

以下の構成のTerraformコードを作成し、terraform applyをしておきます。

いずれのファイルも、前回のmodule紹介記事で作成したものと同一で、東京リージョンにVPC1つとサブネット4つが作成された状態になっています。

├── environments
│   └── test-root
│       ├── main_tokyo.tf
│       └── providers.tf
└── modules
└── network
├── providers.tf
├── variables.tf
└── vpc-subnet.tf

removed_img001.png

removed_img002.png

removedブロックを書く

ルートモジュールのmain_tokyo.tfを以下のように修正します。

[terraform:main_tokyo.tf]

# main_tokyo.tf
 
#module "network_tokyo" {
#  source = "../../modules/network"
#
#  environment = "dev"
#  system_name = "tokyo"
#  vpc_cidr    = "172.16.0.0/16"
#
#  subnet_map_list = [
#    { "name" = "public-1a", "cidr" = "172.16.0.0/26", "az_name" = "ap-northeast-1a" },
#    { "name" = "private-1a", "cidr" = "172.16.0.64/26", "az_name" = "ap-northeast-1a" },
#    { "name" = "public-1c", "cidr" = "172.16.0.128/26", "az_name" = "ap-northeast-1c" },
#    { "name" = "private-1c", "cidr" = "172.16.0.192/26", "az_name" = "ap-northeast-1c" },
#  ]
#}
 
removed {
 from = module.network_tokyo
 lifecycle {
  destroy = false
 }
}

Terraformの管理から外すため、networkモジュールを呼び出しているコードは丸ごとコメントアウトしています(コードに残っていると、plan時にエラーになります)。

そのうえでremovedブロックを記載していますが、注意すべき点としてはlifecycleオプションでdestroy = falseを指定している点です。指定しなかった場合、管理外にするのではなく、リソースが削除されてしまいます。

terraform planを実行する

この状態からterraform planを実行して実行計画を表示してみます。

[bash]

$ terraform plan 
module.network_tokyo.aws_subnet.main["public-1c"]: Refreshing state... [id=subnet-016a525e2dad4e550]
module.network_tokyo.aws_subnet.main["private-1a"]: Refreshing state... [id=subnet-0be701229eb362c3e]
module.network_tokyo.aws_vpc.main: Refreshing state... [id=vpc-0d2c354e13eb5ce19]
module.network_tokyo.aws_subnet.main["private-1c"]: Refreshing state... [id=subnet-0533d0ef9c35db070]
module.network_tokyo.aws_subnet.main["public-1a"]: Refreshing state... [id=subnet-0775ae40a9cfbb5ed]
 
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
 
Terraform will perform the following actions:
 
 # module.network_tokyo.aws_subnet.main["private-1a"] will no longer be managed by Terraform, but will not be destroyed
 # (destroy = false is set in the configuration)
 . resource "aws_subnet" "main" {
    id                                             = "subnet-0be701229eb362c3e"
    tags                                           = {
      "Name" = "tokyo-dev-private-1a"
    }
    # (16 unchanged attributes hidden)
  }
 
 # module.network_tokyo.aws_subnet.main["private-1c"] will no longer be managed by Terraform, but will not be destroyed
 # (destroy = false is set in the configuration)
 . resource "aws_subnet" "main" {
    id                                             = "subnet-0533d0ef9c35db070"
    tags                                           = {
      "Name" = "tokyo-dev-private-1c"
    }
    # (16 unchanged attributes hidden)
  }
 
 # module.network_tokyo.aws_subnet.main["public-1a"] will no longer be managed by Terraform, but will not be destroyed
 # (destroy = false is set in the configuration)
 . resource "aws_subnet" "main" {
    id                                             = "subnet-0775ae40a9cfbb5ed"
    tags                                           = {
      "Name" = "tokyo-dev-public-1a"
    }
    # (16 unchanged attributes hidden)
  }
 
 # module.network_tokyo.aws_subnet.main["public-1c"] will no longer be managed by Terraform, but will not be destroyed
 # (destroy = false is set in the configuration)
 . resource "aws_subnet" "main" {
    id                                             = "subnet-016a525e2dad4e550"
    tags                                           = {
      "Name" = "tokyo-dev-public-1c"
    }
    # (16 unchanged attributes hidden)
  }
 
 # module.network_tokyo.aws_vpc.main will no longer be managed by Terraform, but will not be destroyed
 # (destroy = false is set in the configuration)
 . resource "aws_vpc" "main" {
    id                                   = "vpc-0d2c354e13eb5ce19"
    tags                                 = {
      "Name" = "tokyo-dev"
    }
    # (15 unchanged attributes hidden)
  }
 
Plan: 0 to add, 0 to change, 0 to destroy.
╷
│ Warning: Some objects will no longer be managed by Terraform
│ 
│ If you apply this plan, Terraform will discard its tracking information for the following objects, but it will not delete them:
│  - module.network_tokyo.aws_subnet.main["private-1c"]
│  - module.network_tokyo.aws_subnet.main["public-1a"]
│  - module.network_tokyo.aws_subnet.main["public-1c"]
│  - module.network_tokyo.aws_subnet.main["private-1a"]
│  - module.network_tokyo.aws_vpc.main
│ 
│ After applying this plan, Terraform will no longer manage these objects. You will need to import them into Terraform to manage them again.
╵
 
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
 
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.

リソースに対するアクションがwill no longer be managed by Terraform, but will not be destroyed、つまり「Terraformで管理されなくなるがリソースは削除しない」と表示されています。

リソースが削除される場合はwill be destroyedと表示されるので、メッセージから判別することができますね。

細かい点としては、変更されるリソースの表示が.になっていることも違いの一つです(リソースが削除される場合は-が表示されます)。

ちなみにterraform state listコマンドでTerraform管理リソースの一覧を表示することができます。まだapplyしていないため、各リソースは管理対象となっています。

[bash]

$ terraform state list 
module.network_tokyo.aws_subnet.main["private-1a"]
module.network_tokyo.aws_subnet.main["private-1c"]
module.network_tokyo.aws_subnet.main["public-1a"]
module.network_tokyo.aws_subnet.main["public-1c"]
module.network_tokyo.aws_vpc.main

terraform applyを実行する

terraform applyを実行することで、Terraform管理外にする処理が実行されます。

[bash]

$ terraform apply
 
(中略)
 
Plan: 0 to add, 0 to change, 0 to destroy.
╷
│ Warning: Some objects will no longer be managed by Terraform
│ 
│ If you apply this plan, Terraform will discard its tracking information for the following objects, but it will not delete them:
│  - module.network_tokyo.aws_subnet.main["public-1c"]
│  - module.network_tokyo.aws_subnet.main["private-1a"]
│  - module.network_tokyo.aws_subnet.main["public-1a"]
│  - module.network_tokyo.aws_subnet.main["private-1c"]
│  - module.network_tokyo.aws_vpc.main
│ 
│ After applying this plan, Terraform will no longer manage these objects. You will need to import them into Terraform to manage them again.
╵
 
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
 
 
Apply complete! Resources: 0 added, 0 changed, 0 destroyed.

これでリソースがTerraform管理外になりました。terraform state listコマンドを実行すると先程まで表示されていたリソースが表示されなくなっており、管理外になったことが分かります。

[bash]

$ terraform state list 
$ 

マネジメントコンソールから見ると、VPCおよびサブネットが残っていることが分かります。リソースは残したまま、Terraform管理から外すことができました。

removed_img003.png

removed_img004.png

まとめ

今回はTerraform v1.7removedブロックを用いてTerraformで作成したリソースをTerraform管理外にする手順を紹介しました。

管理外にしたいリソースが1つだけだとterraform state rmコマンドを使った手順との違いがあまり実感できないと思いますが、リソース数が多い場合にはかなり効果的になりそうだと思いました。

個人的に、モジュールで作ったリソースを丸ごとremovedブロックで管理外にできるのは驚きでした。検証前は対象リソース1つにつきremovedブロック1つと思い込んでいてterraform state rmとの違いが実感しづらかったのですが、うれしい誤算でした。

Terraform v1.7pre-releaseですが、beta-2まで開発が進んでいますので、もうまもなく正式版がリリースされるのではと思います。とても楽しみです。

お読みいただきありがとうございました。

IOWNデジタルツイン事業部では、Terraform EnterpriseおよびTerraform Cloud Plusに関する、日本語による保守サポートをご提供しております。Terraformの導入にあたってお悩みの方は、ぜひお気軽にご相談ください。

HashiCorp製品サポートサービス(弊社ホームページ)

連載シリーズ
著者プロフィール
岩瀬 正太郎