※この記事は HashiCorp 公式ブログ Detecting and Managing Drift with Terraform を日本語に翻訳したものです。
原文:https://www.hashicorp.com/blog/detecting-and-managing-drift-with-terraform
はじめに
Terraform を使ってインフラを管理する場合、コードで定義したインフラ状態とクラウド環境の実際の状態がズレることがあります。
このズレを ドリフト(drift) と呼びます。ドリフトが発生すると、Terraform は望ましくないリソース変更や再作成を計画する可能性があります。
本記事では、Terraformの下記ファンクションを用いてどのようにドリフトを検出し管理するかを説明します。
- Terraform State ステートファイルとTerraformがリソースを追跡する方法
- Terraform Refresh refreshコマンドと実世界のドリフトの調整
- Terraform Plan planコマンドと望ましい構成と実世界の状態の調整
- Terraform Config ドリフト管理に役立つ設定オプション
1. 例として使用するリソース
以下は、この記事全体の例として使用するリソースです:
# AWS EC2 VM with AMI and tags
resource "aws_instance" "example" {
ami = "ami-656be372"
instance_type = "t1.micro"
tags {
drift_example = "v1"
}
}
このようなシンプルな EC2 インスタンスを用いて、ドリフトがどのように検出されるかを見ていきます。
2. Terraform State: Terraformがリソースを追跡する方法
Terraform は apply を実行した際、インフラの情報を ステートファイル (terraform.tfstate) に保存します。
ステートは Terraform が「どのリソースを管理しているか」を追跡するための重要なファイルであり、JSON 形式で内部的に管理されます。直接編集は推奨されません。
ステートファイルはTerraformにとって不可欠であり、次の機能を果たします:
- 構成で定義されたリソースと実際のリソースを対応付ける。
- 依存関係や依存順序など、リソースに関するメタデータを追跡する。
- 非常に大規模なインフラを管理する際のパフォーマンス向上のため、リソース属性をキャッシュする。
- チーム間のより良いコラボレーションを可能にする同期機能。
- Terraformが管理するリソースを追跡し、同じ環境内のその他のリソースを無視する。
3. ステートの中身を確認する
ステートファイルに保存されているリソース情報は、以下のように確認できます:
$ terraform show
aws_instance.example:
id = i-011a9893eff09ede1
ami = ami-656be372
instance_type = t1.micro
tags.drift_example = v1
...
また、特定リソースだけ表示するには:
$ terraform state show aws_instance.example
id = i-011a9893eff09ede1
ami = ami-656be372
availability_zone = us-east-1d
instance_state = running
instance_type = t1.micro
tags.drift_example = v1
...
4. terraform refresh による現実との同期
Terraform は plan や apply の実行前に、refresh(同期) フェーズを自動で行います。
これにより、クラウドプロバイダ上の最新情報をステートに反映させ、差分計算を適切に行います。
手動で refresh を実行する場合は:
$ terraform refresh
aws_instance.example: Refreshing state... (ID: i-011a9893eff09ede1)
これはステートファイルを実際の実行環境の状態に更新するだけで、インフラ自体は変更しません。
5. terraform plan による差分検出
Terraform は desired state(コード側の宣言) と最新の real-world state(クラウド側の実際の状態) を比較し、差分を計算します。
この差分がドリフトとして検出されます。
terraform plan を実行すると、この差分がテキストで表示されます。
apply を実行すると、その plan に基づいて実際のリソースが適用されます。
6. ドリフトの例 — タグ値の変更
AWS Console で手動でタグの値を変更した場合:
$ 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_instance.example: Refreshing state... (ID: i-011a9893eff09ede1)
------------------------------------------------------------------------
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_instance.example
tags.drift_example: "v2" => "v1"
Plan: 0 to add, 1 to change, 0 to destroy.
------------------------------------------------------------------------
この出力は、「ステートと実際の値が異なる」ことを示しており、Terraform はタグを code 側に合わせる差分を表示します。
7. ドリフトの例 — リソース削除
リソース(例では EC2)を手動で削除した場合:
$ terraform plan
...
aws_instance.example: Refreshing state...
...
+ aws_instance.example
Plan: 1 to add, 0 to change, 0 to destroy.
ステート側には存在するが、実際にはリソースが存在しないため 再作成する計画が出力されます。
8. Lifecycle Options による制御
Terraform の lifecycle ブロックは、ドリフトに対する挙動を細かく制御できます。
prevent_destroy
削除を防止したい場合:
lifecycle {
prevent_destroy = true
}
この設定があると、削除を含む変更がある場合エラーとなります。
ignore_changes
特定のフィールド差分を無視するための設定:
lifecycle {
ignore_changes = ["ami"]
}
この例では、AMI の値が異なっても差分として扱いません。
9. まとめ
Terraform のドリフトとは desired state と real-world state の不一致 を意味します。
Terraform はステートファイルを利用し、plan 時に差分を検出します。
refresh によってステートを実際の状態と同期できます。
lifecycle 設定により、削除防止や特定フィールドの無視などの制御が可能です。
参考リンク(公式)
Detecting and Managing Drift with Terraform — HashiCorp 公式ブログ
https://www.hashicorp.com/blog/detecting-and-managing-drift-with-terraform