解决 Terraform 的配置漂移问题

这篇文章是Ateam Finergy Inc. Advent Calendar 2020第四天的文章。

首先

在撰写本篇文章时,使用的Terraform版本如下所示。

% terraform -v
Terraform v0.13.2

此外,本文旨在为正在使用Terraform并遇到漂移问题的读者以及容易遗忘的自己提供备忘。

配置漂移

使用 Terraform 时,由于某些原因,可能会发生状态文件 .tfstate 的内容与实际基础架构的偏差(Configration Drift)。

如果出现漂移现象,可以考虑几种应对策略,但本次记录了将正在运行的基础架构视为正确状态,并解决与Terraform管理状态的偏离方法。

解决漂移问题

使用下面的资源,尝试再现漂移发生的情况。

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

执行Terraform应用并创建一个实例。

% 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正在修正漂移并尝试修正标签以与配置的值匹配。在这种情况下执行terraform apply将导致实际基础架构的标签被还原回v1。

手动更改Terraform的配置和状态。

如果在这种情况下差异很小,可以通过手动编辑配置文件来解决问题。
请按以下方式编辑.tf和.tfstate文件。
(如果手动更新.tfstate,请确保递增serial)

   tags = {
-    drift_example = "v1"
+    drift_example = "v2"
   }
@@ -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文件的差异。

@@ -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 不会进行任何更改。

使用工具进行反向Terraform操作

您还可以使用terraformer工具或terraforming工具从现有的基础架构中导出.tf和.tfstate文件,以便在Terraform中进行管理。

相比于手动编辑或导入完全设置好的实例或跨多个群集节点的存储和网络等设定,使用这样的工具是更为实际的方法。

总结

我提供了以下三种方法来解决Terraform的配置漂移问题。希望你能根据实际情况加以利用。

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

terraform import コマンドを使用する
ツールを使用して Reverse Terraform する

此外,了解问题处理方法固然重要,我也认为了解Terraform和基础设施即代码的最佳实践,以预防问题的发生同样至关重要。(戒示)

请提供参考链接。

    • Import – Terraform by HashiCorp

State – Terraform by HashiCorp
Detecting and Managing Drift with Terraform
Import Terraform configuration | Terraform – HashiCorp Learn
How to manage Terraform state. A guide to file layout, isolation, and… | by Yevgeniy Brikman | Gruntwork

广告
将在 10 秒后关闭
bannerAds