Open12

Terraform の removed ブロックと import ブロックでリソースの管理単位(state)を分離する

snakasnaka

背景

  • ライフサイクルの異なる一部のリソースを別の state で管理したい
  • 具体的には、サービスを提供するために必要なリソース(「サービス用リソース」)と、そのサービスをメンテナンス作業のために一時的に必要なリソース(「メンテ用リソース」)が1つの state に同居している状況だった。
  • メンテ用リソースの更新頻度は低いが、サービス用リソースの方は比較的更新頻度は高い。
  • Terraform Cloud で GitHub と VCS 連携 ( デフォルトブランチへのマージで Apply ) している
snakasnaka

作業方針

  • サービス用リソースの state からメンテ用リソースを削除する
  • メンテ用リソースを管理する workspace を用意する
  • メンテ用リソースの state に既存リソースを import する
snakasnaka
snakasnaka

from で state から削除する対象リソースのアドレスを指して、 lifecycle では実際のリソースを削除するかどうかを指定する。( false ならリソースは削除しない )

removed {
  from = aws_instance.example

  lifecycle {
    destroy = false
  }
}

snakasnaka

removed でリソースを削除する

まずは、removed で対象リソースを Terraform の管理から外す。( apply まで実行する )

(TBD)

snakasnaka

import ブロックでリソースの現在の state を Terraform に import する

旧 workspace からリーソースが切り離し移動先となる workspace が用意できたら、今度は対象リソースを新しい workspace に import する。

snakasnaka

terraform plan を実行して差分を確認する

  # module.hoge.aws_instance.fuga will be created

  + resource "aws_iam_role" "fuga" {
     ... ( 略 ) ...

上記のようにリソースを作成 (create) する plan が出てくるので、これらが import するべきリソースを指している

snakasnaka

plan を参考に root モジュールに import ブロックを記述していく

import {
  id = ""
  to = module.hoge.aws_iam_role.fuga
}
  • to{resource address} will be created{resouce address} の部分
  • id は対象のリソースタイプによって異なるので、都度 Provider のドキュメントを確認する
    • 上の例だと aws_instance のページで import の項目を参照する
    • to import instances using the 'id' と書いてあるので、リソースの id の値を記述する、ものによっては name だったり IP アドレスだったりするので注意すること
snakasnaka

次に plan を実行したときに以下のように will be imported になっているとOK

  # module.hoge.aws_instance.fuga will be imported

  + resource "aws_iam_role" "fuga" {
     ... ( 略 ) ...
snakasnaka

一部のリソースは import でリソースの作り直し ( delete & create ) となるケースもある。
自分のケースだと keypair とそれに紐づく EC2 instance がそうだった