Terraform 学习总结—— 如何解决存量云资源的管理难题

Posted 科技D人生

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Terraform 学习总结—— 如何解决存量云资源的管理难题相关的知识,希望对你有一定的参考价值。

一、背景信息

通常在以下四种运维场景需要考虑如何解决存量云资源的管理:

  • 场景一:长期使用控制台、阿里云 CLI、资源编排服务或者直接调用 API 创建和管理资源,初次使用 Terraform 的场景。
  • 场景二:长期使用 Terraform 管理资源,如果通过控制台对单个云资源做属性变更,希望保持原有的资源状态(State)一致的场景。
  • 场景三:所有资源都定义在一个模板中,想要对原有模板进行重构拆分,以降低随着资源不断增多而带来的模板和 state 的管理复杂度的场景。
  • 场景四:想要将新版 Provider 中新增的参数同步到原文档中的场景。

Terraform 基于资源模板定义不仅可以实现对新资源的创建,变更,删除等操作,还可以通过简单的命令将那些游离在 Terraform 管理体系之外的云资源进行导入和纳管,进而实现对所有云资源的统一管理。

二、Terraform 导入存量资源

Terraform 对资源的导入可以分为三个步骤:

  1. 获取资源 ID:基于资源 ID 查询资源并获取其属性。
  2. 模板声明所要导入的资源:模板驱动,即使是要导入的资源,也需要在模板中进行声明。
  3. 补齐资源模板定义:导入成功后,需要根据资源属性补齐已经在模板中声明的资源定义。

2.1、获取资源 ID。对资源 ID 的获取可以通过 Web 控制台,CLI,API 等多种方式,最简单的方式是通过 Terraform 的 DataSource,输入简单的查询条件,例如获取一个负载均衡实例:

data "alicloud_slbs" "default" 
  name_regex  = "for-demo*"

output "slb_ids" 
  value = data.alicloud_slbs.default.ids

运行 terraform apply 命令即可展示所有符合条件的 SLB 的 ID:

$ terraform apply
data.alicloud_slbs.default: Refreshing state...

Apply complete! Resources: 0 added, 0 changed, 0 destroyed.

Outputs:

slb_ids = [
  "lb-gw8vinrqxxxxxxxxxxx",
  "lb-gw8axostxxxxxxxxxxx",
]

2.2、模板声明所要导入的资源。和创建资源一样,在导入资源前,也需要在模板中进行资源声明,以便指定所要导入的资源在 State 中的存放路径。如下所示,声明一个负载均衡实例:

resource "alicloud_slb" "this" 

简单的声明之后,无需定义具体的参数即可开始资源的导入操作。在 Terraform 中,导入一个资源的操作通过 import 命令来完成,完整的命令格式为 terraform import <资源类型>.<资源标识> <资源 ID> ,详细操作如下:

$ terraform import alicloud_slb.this lb-gw8vinrqxxxxxxxxxxx
alicloud_slb.this: Importing from ID "lb-gw8vinrqxxxxxxxxxxx"...
alicloud_slb.this: Import prepared!
  Prepared alicloud_slb for import
alicloud_slb.this: Refreshing state... [id=lb-gw8vinrqxxxxxxxxxxx]

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.

2.3、补齐资源模板定义。由于模板中没有完成对所导入资源的详细定义,因此,资源导入成功后,模板内容与 State 存储的内容存在差异,此时如果直接运行 plan 命令,将会看到一个 update:

$ 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.

data.alicloud_slbs.default: Refreshing state...
alicloud_slb.this: Refreshing state... [id=lb-gw8vinrqxxxxxxxxxxx]

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

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:

  # alicloud_slb.this will be updated in-place
  ~ resource "alicloud_slb" "this" 
        address              = "47.254.181.122"
        ...
      ~ delete_protection    = "on" -> "off"
        id                   = "id=lb-gw8vinrqxxxxxxxxxxx"
        ...
      ~ name                 = "for_demo-test" -> "tf-lb-20191108144235105700000001"
        ...
    

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

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

Note: You didn't specify an "-out" parameter to save this plan, so Terraform
can't guarantee that exactly these actions will be performed if
"terraform apply" is subsequently run.

为了保持资源模板与资源状态的一致,需要在模板中手动补齐缺失的参数定义,直到运行 plan 不会再有变更信息为止:

resource "alicloud_slb" "this" 
  delete_protection = "on"
  name              = "for_demo-test"

所要补齐的内容主要以那些引起更新的字段为主,补齐完成后运行 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.

data.alicloud_slbs.default: Refreshing state...
alicloud_slb.this: Refreshing state... [id=lb-gw8vinrqtqx1ro1r94c96]

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

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 移除存量资源

在实际操作场景中,经常会遇到资源的误导入,导入路径不符,想要调整资源路径,想要永久保留某资源等多种复杂情况。面对这些情况,整体的实现思路也是非常简单:先将导入后的资源从 State 中移除,然后重新导入。资源的移除操作可以通过 state rm 命令来完成,完整的命令格式为 terraform state rm <资源类型>.<资源标识> ,详细操作如下:

$ terraform state rm alicloud_slb.this
Removed alicloud_slb.this
Successfully removed 1 resource instance(s).

state rm 命令只是将指定的资源从 State 文件中移除,并不会将其真正删除,这也正是为后续的导入操作做好了铺垫。

四、总结

对于以上四种场景我们可以使用以下解决方案:

  • 场景一的解决方案:通过 terraform import 命令来完成对存量资源的导入,进而使用 Terraform 统一管理。
  • 场景二的解决方案:在确定清楚参数属性具体值之后,如果以模板参数值为准,那么只需运行 apply 命令再变更回来即可;如果以控制台的值为准,那么只需补充或修改模板参数值即可。
  • 场景三的解决方案:可以先通过terraform state rm命令将所有需要重组的资源移出State,等模板重构结束后,再使用terraform import将其导入即可。
  • 场景四的解决方案:和上一解决方案一样,通过“先移出再导入”调整即可。

Terraform 的命令非常灵活和简单,基于模板和 State 一致性的原理,借助 terraform import 可以轻松地实现对存量资源的统一管理,不用再担心那些游离在 Terraform 管理体系之外资源无法管理的痛点,也无需惧怕某个资源从 State 中移除后无法继续管理的问题,所有的云资源都可以被 Terraform 统一管理起来。

以上是关于Terraform 学习总结—— 如何解决存量云资源的管理难题的主要内容,如果未能解决你的问题,请参考以下文章

Terraform 学习总结—— 如何解决存量云资源的管理难题

Terraform 学习总结——Terraform 命令详解

Terraform 学习总结—— Terraform 常用命令再总结

Terraform 学习总结—— Terraform 常用命令再总结

Terraform 学习总结—— Terraform 常用命令再总结

Terraform 学习总结(10)—— 阿里云平台 Terraform 代码开发技巧总结