Terraform 命令

更新时间:
复制 MD 格式

一旦在你的机器上安装 Terraform 之后,就可以在根模块所在的目录下,通过命令来与 Terraform 进行交互。本文涵盖的常见命令包括 terraform init、terraform plan、terraform apply、terraform destroy 和 terraform fmt。

  • terraform init:用于初始化和自动下载提供商的插件。

  • terraform plan:提供在执行 terraform apply 后将创建的资源的预览。

  • terraform apply:创建基础设施资源。

  • terraform destroy:销毁基础设施资源。

  • terraform fmt:自动格式化代码以匹配规范约定。

image

初始化阶段(Init)

terraform init 命令在初始化阶段运行,它是在完成 Terraform 配置后运行的第一个命令。terraform init 确保阿里云提供商的插件已完成下载,并安装在当前工作目录的子目录中,同时还包括各种其他记录文件。

terraform {
  required_providers {
    alicloud = {
      source = "aliyun/alicloud"
      version = "1.225.0"
    }
  }
}

提供商的代码定义块中包括一个 source 属性,指定从哪里下载提供商插件。

Terraform 是基于插件的架构来实现对多种基础设施和服务提供商支持的。每个 "提供商" 是一个独立的二进制文件,它与 Terraform 本身独立分发。terraform init 命令将自动下载和安装 Terraform 配置中使用到的任何提供者的二进制文件,如在本例中,提供商是 alicloud。

terraform init 运行之后,你会看到一个 "Initializing provider plugins" 的消息,告诉你 Terraform 将找到指定版本的插件并下载相关文件。命令运行完成之后,在当前工作目录中将会创建一个隐藏的 .terraform 目录,该目录中保存了已经下载的插件。

$ terraform init
Initializing the backend...
Initializing provider plugins...
- Finding aliyun/alicloud versions matching "1.225.0"...
- Reusing previous version of hashicorp/alicloud from the dependency lock file
- Installing aliyun/alicloud v1.225.0...
- Installed aliyun/alicloud v1.225.0 (verified checksum)
...
Terraform has been successfully initialized!

terraform init 命令的输出会告诉你 Terraform 已安装的提供商版本,在此例中是 1.225.0 版本。

预览阶段(Plan)

terraform plan 创建一个执行计划,并详细展示了在执行 terraform apply 时将创建、修改或销毁的所有资源信息。

运行 terraform plan 时,Terraform 会:

  1. 读取现有资源的在远端的当前状态,以确保 Terraform 状态是最新的。

  2. 将当前配置与先前状态进行比较,并记录任何差异。

  3. 构建一个执行计划,只修改达成你所需状态所必要的部分。

terraform plan 实际上不会创建或更改任何基础设施资源,而是为你提供预览基础设施创建和变更的机会。例如,在将 Terraform 配置提交到版本控制之前,你可能想要运行此命令,以确保其行为跟预期是一样的。

resource "alicloud_vswitch" "main_vswitch" {
  vpc_id        = "vpc-2zekfrr69r6qmotbmru1m"
  cidr_block    = "10.0.1.0/24"
  zone_id       = "cn-hangzhou-k"
  vswitch_name  = "main-vswitch"
}
运行 terraform plan 后,输出的执行计划中,配置文件中指定的 vpc_id、cidr_block、zone_id、vswitch_name 值会映射到计划输出的对应属性:text
Terraform will perform the following actions:
  # alicloud_vswitch.main_vswitch will be created
  + resource "alicloud_vswitch" "main_vswitch" {
      + availability_zone      = (known after apply)
      + cidr_block             = "10.0.1.0/24"
      + create_time            = (known after apply)
      + id                     = (known after apply)
      + ipv6_cidr_block        = (known after apply)
      + ipv6_cidr_block_mask   = (known after apply)
      + name                   = (known after apply)
      + status                 = (known after apply)
      + vpc_id                 = "vpc-2zekfrr69r6qmotbmru1m"
      + vswitch_name           = "main-vswitch"
      + zone_id                = "cn-hangzhou-k"
    }
Plan: 1 to add, 0 to change, 0 to destroy.

资源和参数旁边的符号表示对资源计划执行的具体操作:

  • 加号(+)

    资源旁边的加号意味着 Terraform 将创建该资源,并展示将要设置的属性

  • 减号斜线加号(-/+)

    表示 Terraform 将销毁当前资源并重新创建一个新的资源,而不是就地更新它的属性

  • 波浪号(~)

    表示 Terraform 将就地更新资源属性

  • 减号(-)

    表示销毁当前资源实例

运行 terraform plan 命令时,你可以使用可选参数 -out=<文件名> 将生成的计划保存到磁盘上的文件中,以便之后可以将文件作为执行计划传递给 terraform apply 来执行。

$ terraform plan -out=tf.tfplan

执行阶段(Apply)

terraform apply 执行通过 terraform plan 创建的执行计划,或者直接生成执行计划并确认执行,进而完成资源的创建和相互之间依赖关系的建立。

terraform apply 对执行计划的执行有两种方式:

  1. 直接执行 terraform plan 生成的执行计划。terraform plan 通过 -out 参数将执行计划保存为文件(比如文件命名为 tf.tfplan),terraform apply 可以直接使用该文件作为执行计划直接执行,无需等待确认:

$ terraform apply tf.tfplan
  1. 自身重新生成执行计划并等待确认再执行

和 terraform plan 命令一样,terraform apply 在执行时也会显示资源变更详情,并尝试创建执行计划等待用户确认执行。如果执行计划成功创建,Terraform 会暂停并等待确认再继续;如果计划中有任何不正确或不安全的地方,你可以在这里中止而不改变你的基础设施。

resource "alicloud_vswitch" "main_vswitch" {
  vpc_id        = "vpc-2zekfrr69r6qmotbmru1m"
  cidr_block    = "10.0.1.0/24"
  zone_id       = "cn-hangzhou-k"
  vswitch_name = "main-vswitch"
}
$ terraform apply
Terraform will perform the following actions:
  # alicloud_vswitch.main_vswitch will be created
  + resource "alicloud_vswitch" "main_vswitch" {
    + cidr_block       = "10.0.1.0/24"
      + vpc_id         = "vpc-bp1y88bqtlunfdvvctuuy"
      + vswitch_name   = "main-vswitch"
      + zone_id        = "cn-hangzhou-k"
      + …
    }
Plan: 1 to add, 0 to change, 0 to destroy.
Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.
  Enter a value: yes

如果 terraform apply 执行失败,请阅读错误消息并解决问题。

资源销毁(Destroy)

terraform destroy 用于销毁资源。terraform destroy 类似于 terraform apply,但它的行为就像配置中将所有资源定义删除并执行 terraform apply 一样。

Terraform 销毁资源主要有三种方式:

  1. terraform destroy 命令

    和 terraform apply 命令一样,terraform destroy 在执行时也会显示资源销毁的详情,并尝试创建销毁计划等待用户确认执行。如果销毁计划成功创建,Terraform 会暂停并等待确认再继续;如果计划中有任何不正确或不安全的地方,你可以在这里中止而不会销毁你的基础设施。

    $ terraform destroy
    Terraform will perform the following actions:
      # alicloud_vswitch.main_vswitch will be destroyed
      - resource "alicloud_vswitch" "main_vswitch" {
          - cidr_block    = "10.0.1.0/24" -> null
          - id            = "vsw-bp1svwz2meo2mqj8c9ewz" -> null
          - vpc_id        = "vpc-bp1y88bqtlunfdvvctuuy" -> null
          - vswitch_name  = "main-vswitch" -> null
          - zone_id       = "cn-hangzhou-k" -> null
          - ...
        }
    Plan: 0 to add, 0 to change, 1 to destroy.
    Do you really want to destroy all resources?
      Terraform will destroy all your managed infrastructure, as shown above.
      There is no undo. Only 'yes' will be accepted to confirm.
      Enter a value: yes
    alicloud_vswitch.main_vswitch: Destroying... [id=vsw-bp1svwz2meo2mqj8c9ewz]
    alicloud_vswitch.main_vswitch: Destruction complete after 4s
    Destroy complete! Resources: 1 destroyed.
  2. terraform plan 创建资源销毁的执行计划

    可以通过 terraform plan 的可选参数 -destroy 来生成一个销毁计划,并通过 terraform apply 来执行这个销毁计划。

$ terraform plan -destroy -out=tf.tfplan

如果想要销毁某个特定的资源,你也可以通过命令中的可选参数 -target=resource 来指定要销毁的特定资源。

  1. 删除配置并创建资源销毁执行计划

    从 Terraform 配置中删除所有资源或者单个想要销毁的资源的代码定义,并通过 terraform plan 和 terraform apply 来完成所有资源或者指定资源的销毁。

与 terraform plan 类似,Terraform 在销毁资源时将确定需要销毁的顺序,例如,如果 vSwitch 交换机中仍有资源(如 ECS 实例,RDS 实例等),阿里云将不允许删除 vSwitch 交换机,Terraform 会在实例被销毁后再销毁交换机。

terraform destroy 需要谨慎使用,它将销毁任何资源及其相关数据。例如,如果 OSS Bucket 中有数据,在运行 terraform destroy 时要小心,因为这些数据无法恢复。

在生产环境中销毁基础设施是罕见的事件,但如果你使用 Terraform 创建多个环境(例如开发、测试和预发布),那么销毁往往是一个有用的操作,可以用 terraform destroy 方便地清理临时对象。

代码格式化(fmt)

最后,我们来讨论一些代码格式化的最佳实践:

  • 将元参数与资源参数分开,放在代码的最前面或最后,并留出空行

    元参数是指 HCL 提供的预留参数,比如 count,for_each 等

  • 参数从块定义开始缩进两个空格

  • 当在一个块中定义两个或两个以上的参数时,让等号对齐

  • 当一个块包含嵌套块时,将该块放在所有参数之后

  • 最后,当代码包含多个块时,用空行将它们分开以提高可读性

# ❌ 错误示例
resource "alicloud_instance" "instance" {
  data_disks {    # 嵌套的代码块在最上面
    size     = 20
    category = "cloud_efficiency"
  }
  count = 10    # 元参数在中间
  instance_name="terraform-example"   # 等号未对齐
  …
}
# ✅ 正确示例
resource "alicloud_instance" "instance" {
  count  = 10    # 元参数在最上面
  instance_name = "terraform-example"   # 等号对齐
  …
  data_disks {    # 嵌套的代码块在最下面
    size     = 20
    category = "cloud_efficiency"
  }
}

运行 terraform fmt 将基于所有格式规则和推荐的样式自动对模块和代码进行格式化,以提高代码可读性和一致性。terraform fmt 自动保持一致的格式,因此你不必手动更改配置以确保其符合标准。