1. 概述
Terraform 是一个广泛使用的 IaC(Infrastructure as Code,基础设施即代码)工具,通过声明式语言 HCL(HashiCorp Configuration Language) 来构建和管理资源集合。这些资源可以是云上的服务器、数据库、网络设备,也可以是本地文件系统中的文件。
通常在执行 terraform apply
时,我们会一次性创建计划中所有的资源。但在某些场景下,我们可能只需要应用部分资源,比如排查某个资源的问题,或者因为某个 provider 存在 bug 需要单独调试。这时我们不希望一次性执行整个计划。
本文将介绍如何通过指定特定配置文件,只应用 Terraform 计划中的一部分资源。我们使用的 Terraform 版本为 1.8.2。
2. 示例配置
本节将演示一个创建本地文件的 Terraform 配置,这些文件中包含不同语言的问候语。
配置目录下有如下文件:
$ ls
hello_en.tf hello_it.tf hello_tr.tf locals.tf
其中 hello_en.tf
、hello_it.tf
和 hello_tr.tf
分别用于创建英文、意大利文和土耳其文的问候文件,而 locals.tf
定义了这些资源中使用的本地变量。
2.1. 本地变量
我们先看 locals.tf
的内容:
locals {
output_dir = "/tmp/hellos_output_dir"
file_perm = "0744"
files = {
English = "hello_en.txt"
Italian = "hello_it.txt"
Turkish = "hello_tr.txt"
}
hello_messages = {
English = "Hello Baeldung!\n"
Italian = "Ciao Baeldung!\n"
Turkish = "Merhaba Baeldung!\n"
}
}
我们使用 locals
块定义了几个本地变量:
output_dir
:文件输出目录file_perm
:文件权限files
:各语言对应的文件名hello_messages
:各语言对应的问候语内容
这些变量在资源中被引用,实现统一配置。
2.2. 资源定义
以 hello_en.tf
为例,其内容如下:
resource "local_file" "hello_en" {
content = local.hello_messages["English"]
filename = "${local.output_dir}/${local.files["English"]}"
file_permission = local.file_perm
}
说明:
- 使用
resource
声明资源 - 资源类型为
local_file
,用于创建本地文件 content
指定文件内容,这里引用了locals.hello_messages["English"]
filename
是文件路径,由output_dir
和files["English"]
拼接而成file_permission
设置文件权限
另外两个文件 hello_it.tf
和 hello_tr.tf
结构类似,只是引用了不同的语言键值。
2.3. 构建基础设施
初始化 Terraform:
$ terraform init
...
Terraform has been successfully initialized!
直接执行 apply(跳过 plan):
$ terraform apply -auto-approve
Apply complete! Resources: 3 added, 0 changed, 0 destroyed.
查看生成的文件:
$ ls /tmp/hellos_output_dir
hello_en.txt hello_it.txt hello_tr.txt
$ cat /tmp/hellos_output_dir/hello_en.txt
Hello Baeldung!
成功创建了三个语言文件,内容正确。
3. 使用 -target
参数
默认情况下,terraform apply
会创建所有资源。如果我们只想创建某一个资源,可以使用 -target
参数。
3.1. 清理资源
先清理已有资源:
$ terraform destroy -auto-approve
Destroy complete! Resources: 3 destroyed.
此时 /tmp/hellos_output_dir
目录下的文件也被删除。
3.2. 单独应用某个资源
使用 -target
只创建 hello_tr
资源:
$ terraform apply -auto-approve -target=local_file.hello_tr
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
验证文件是否生成:
$ ls /tmp/hellos_output_dir/
hello_tr.txt
$ cat /tmp/hellos_output_dir/hello_tr.txt
Merhaba Baeldung!
✅ 成功只创建了 hello_tr.txt
文件。
3.3. 多个 -target
你也可以多次使用 -target
指定多个资源:
$ terraform apply -auto-approve -target=local_file.hello_tr -target=local_file.hello_en
⚠️ 注意:虽然 -target
很方便,但在正常流程中不推荐使用。因为它会绕过依赖关系,可能导致状态不一致。
4. 使用模块(Module)组织配置
模块是 Terraform 中组织配置文件的基本单位。任何包含配置文件的目录都可以视为一个模块。例如,我们的示例就是一个模块。
4.1. 重构目录结构
我们将配置文件整理如下:
$ tree
.
├── hello_messages
│ ├── hello_en.tf
│ ├── hello_it.tf
│ ├── hello_tr.tf
│ ├── locals.tf
│ └── outputs.tf
└── hello_zipper.tf
hello_messages
是一个子模块,包含创建文件的逻辑hello_zipper.tf
是根模块,调用子模块并打包生成的文件
4.2. 输出变量
子模块中新增 outputs.tf
:
output "output_dir" {
value = local.output_dir
}
用于将 output_dir
输出给根模块使用。
4.3. 根模块定义
hello_zipper.tf
内容如下:
module "hellos" {
source = "./hello_messages"
}
resource "archive_file" "hellos_zipped" {
type = "zip"
output_path = "./hellos.zip"
source_dir = module.hellos.output_dir
}
说明:
- 使用
module
块调用子模块hello_messages
- 使用
archive_file
资源将子模块生成的文件打包为 zip source_dir
引用了子模块的输出变量output_dir
4.4. 构建模块
在根模块目录下执行 apply:
$ terraform apply -auto-approve
查看生成的压缩包:
$ ls hellos.zip
hellos.zip
$ unzip hellos.zip
Archive: hellos.zip
inflating: hello_en.txt
inflating: hello_it.txt
inflating: hello_tr.txt
内容正确,说明模块构建成功。
✅ 使用模块可以更清晰地组织配置文件,并支持独立构建。例如,如果只修改了 hello_zipper.tf
,我们只需在根模块目录下执行 apply,无需使用 -target
。
5. 总结
本文介绍了如何通过指定特定配置文件来执行 terraform apply
,实现只创建部分资源:
- 使用
-target
参数可以指定具体资源(如local_file.hello_tr
) - 该参数也适用于
terraform plan
和terraform destroy
- 不建议在正常流程中频繁使用
-target
,因为它可能破坏依赖关系 - 使用模块可以更好地组织配置文件,实现模块化构建,减少对
-target
的依赖
合理使用模块结构和 -target
参数,能帮助我们在复杂项目中更灵活地控制资源的创建与更新。