LoginSignup
5
1

More than 3 years have passed since last update.

Terraform の Configuration Drift を解消する

Last updated at Posted at 2020-12-03

本記事は Ateam Finergy Inc. Advent Calendar 2020 4日目の記事です。

はじめに

本記事を書くにあたり、動作検証に使用した Terraform のバージョンは下記の通りです。

% terraform -v
Terraform v0.13.2

また、想定読者は Terraform を使用していて、Drift の解決に困っている方、および、忘れがちな自分のためのメモです。

Configuration Drift

Terraform を使用していると、何らかの理由により、 Terraform が管理しているインフラストラクチャの状態ファイル .tfstate の内容と、実際のインフラストラクチャの乖離(Configration Drift)が発生する場合があります。

Drift が発生してしまった場合、対応方針としてはいくつか考えられると思いますが、今回は稼働しているインフラ側を正しい状態とし、Terraform で管理する状態の乖離を解消する方法を記載します。

Drift を解消する

下記のリソースを使用し、Driftが発生した状態を再現してみます。

main.tf
# AWS EC2 VM with AMI and tags
resource "aws_instance" "example" {
  ami           = "ami-0289fbf73734505e2"
  instance_type = "t3.micro"
  tags = {
    drift_example = "v1"
  }
}

terraform apply を実行し、インスタンスを作成します。

% terraform apply
...省略...
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

次に、AWSコンソールを使用してインスタンスのタグを手動で v2 に更新した後、terraform plan で実行計画を出力し、Drift を確認します。

% 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-**********]

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

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 will be updated in-place
  ~ resource "aws_instance" "example" {
      ~ tags                         = {
          ~ "drift_example" = "v2" -> "v1"
        }
    }

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

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

Terraform がタグの値を v2 から v1 に更新することがわかります。 Terraform は Drift を修正し、設定の値と一致するようにタグを修正しようとしています。この状態で terraform apply を実行すると、実際のインフラストラクチャ側のタグは v1 に戻されてしまいます。

Terraform の設定と状態を手動で変更する

このように乖離が少ないケースであれば、設定ファイルを手動編集することにより解決することができます。
.tf .tfstate ファイルを以下のように編集します。
.tfstate を手動更新する場合、serial をインクリメントしておきましょう)

main.tf
   tags = {
-    drift_example = "v1"
+    drift_example = "v2"
   }
terraform.tfstate
@@ -1,7 +1,7 @@
-  "serial": 1,
+  "serial": 2,
@@ -76,7 +76,7 @@
             "tags": {
-              "drift_example": "v1"
+              "drift_example": "v2"
             },

terraform 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_instance.example: Refreshing state... [id=i-**********]

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

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.

無事乖離が解消され、Terraform 側からの変更が無くなりました。

terraform import コマンドを使用する

より大きな乖離が発生したケースを想定してみます。例えば、管理するリソースを後から追加したい場合などです。

例として、AWSコンソールからブロックストレージを作成し、先程のインスタンスに紐付けました。

terraform import コマンドを使用し、既存のインフラストラクチャの情報を .tfstate ファイルに取り込む手順を以下に記載します。

# import コマンドによる状態の上書きができないので、まず古い情報を削除します
# state rm コマンドは実行時、状態の削除とともに .backup ファイルを作成します
% terraform state rm aws_instance.example
Removed aws_instance.example
Successfully removed 1 resource instance(s).

# import を実行します
% terraform import aws_instance.example i-**********
aws_instance.example: Importing from ID "i-**********"...
aws_instance.example: Import prepared!
  Prepared aws_instance for import
aws_instance.example: Refreshing state... [id=i-**********]

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.

うまく取り込めたようなので、.tfstate の差分を確認してみます。

.tfstate
@@ -1,7 +1,7 @@
-  "serial": 2,
+  "serial": 3,
@@ -26,7 +26,19 @@
-            "ebs_block_device": [],
+            "ebs_block_device": [
+              {
+                "delete_on_termination": false,
+                "device_name": "/dev/sdf",
+                "encrypted": false,
+                "iops": 100,
+                "kms_key_id": "",
+                "snapshot_id": "",
+                "volume_id": "vol-**********",
+                "volume_size": 1,
+                "volume_type": "gp2"
+              }
+            ],

先程追加したブロックストレージの情報が無事追加されていました。
terraform 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_instance.example: Refreshing state... [id=i-**********]

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

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.

Terraform 側からの変更は行われないので問題なさそうです。

ツールを使用して Reverse Terraform する

terraformerterraforming といったツールを用いて、既存のインフラストラクチャから新たに Terraform で管理する .tf .tfstate にエクスポートすることもできます。

ストレージやネットワークなどが完全にセットアップされた状態のインスタンスや、複数にわたるクラスター・ノードを、手動で編集・インポートを行うよりも、このようなツールを使用するほうが現実的な方法でしょう。

まとめ

Terraform の Configuration Drift を解消する方法として下記の3点を紹介しました。状況に応じて活用していただければ幸いです。

  • Terraform の設定と状態を手動で変更する
  • terraform import コマンドを使用する
  • ツールを使用して Reverse Terraform する

また、問題の対応方法を知っておくことは大切ですが、Terraform や Infrastructure as Code のベストプラクティスを知り、問題を未然に防ぐことも大切だと思いました。(戒め)

参考URL

5
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
1