TT Lab
开始
学习 学习路径 课程

Terraform/OpenTofu 基础

变量优先级与输出设计

在 TT Lab 中继续学习

目标

用四种方法给同一个变量赋值,亲自确认优先级,并完成一套包含验证、本地值、输出和敏感值的配置。

为什么重要

“改了变量却没有生效”这个问题的答案,几乎总是优先级。工具会从多个位置接收同名的值,即使发生冲突也不会报错,而是悄悄采用更强的那一个。这样虽然方便,调试却变得困难,所以需要有这样一种感觉:本来就是用来被覆盖的值放在弱的位置,必须坚守的值放在强的位置。尤其是通过命令行传入的值,无论什么情况都会胜出,却不会被记录在任何地方,如果在故障响应中使用之后没有反映到代码中,下一次部署就会悄悄把它改回去。最后,sensitive = true 只是遮住屏幕输出,值仍然原样保留在状态文件和 JSON 输出中。不了解这一局限,就相信“已经做了敏感标记,所以是安全的”,这是最常见的事故起点。

步骤

  1. 在 /root/tf/vars/variables.tf 中声明 environment 变量。type = string、default = "dev"、description 必须全部具备。在 /root/tf/vars/outputs.tf 中创建名称为 environment 的输出,按默认值应用之后,把输出以 JSON 形式保存到 /root/tf/vars/out/default-outputs.json(.environment.value 为 dev)。
  2. 在 /root/tf/vars/terraform.tfvars 中写入 environment = "stage" 并重新应用,把输出保存到 /root/tf/vars/out/tfvars-outputs.json。值必须变成 stage——文件胜过默认值。
  3. 这次在命令行中用 -var environment=prod 传值并应用,把输出保存到 /root/tf/vars/out/cli-outputs.json。tfvars-outputs.json 必须保持不变(仍是 stage)。
  4. 在 variables.tf 中声明 owner 变量,但不要把默认值固定写成 platform。用 TF_VAR_owner=platform 环境变量传值并应用,把输出保存到 /root/tf/vars/out/env-outputs.json(.owner.value 为 platform)。同时在 outputs.tf 中也添加 owner 输出。
  5. 在 variables.tf 中添加 replica_count 变量,并加入只允许 1 以上、5 以下的 validation 块。condition 和 error_message 都必须具备,并且 error_message 中必须原样包含允许范围 1-5 这几个字符。用超出范围的值(例如 -var replica_count=9)运行,把被拒绝的输出保存到 /root/tf/vars/out/validation.txt。
  6. 在 /root/tf/vars/main.tf 中创建 locals 块,把 name_prefix 定义为用连字符连接 environment 和 owner 的值。在 outputs.tf 中添加 name_prefix 输出。在第 8 步中重新创建的 cli-outputs.json 里,name_prefix 必须是 prod-platform。
  7. 把输出集中到 /root/tf/vars/outputs.tf 一处,至少放置四个(environment、owner、name_prefix、config_path),并且给所有输出都加上 description。config_path 原样导出这个配置所创建的 local_file 的 filename。
  8. 在 variables.tf 中用 sensitive = true 声明 api_token 变量,并通过 TF_VAR_api_token 传值。在 outputs.tf 中也添加 api_token 输出,并设为 sensitive = true。最后同时提供 -var environment=prod、TF_VAR_owner=platform 和 TF_VAR_api_token 并应用,然后重新创建 cli-outputs.json,并把供人阅读格式的输出也保存到 /root/tf/vars/out/sensitive.txt。后者中必须是被遮住的标记而不是值,并且不能看到真实的令牌字符串。

参考

声明具备类型、默认值和说明的变量

在 /root/tf/vars/variables.tf 中声明 environment 变量。type = string、default = "dev"、description 必须全部具备。在 /root/tf/vars/outputs.tf 中创建名称为 environment 的输出,按默认值应用之后,把输出以 JSON 形式保存到 /root/tf/vars/out/default-outputs.json(.environment.value 为 dev)。

变量块中除了值之外,还有需要附加的内容。三者都没有的话,几个月后就没人知道这个值是什么了。用 -json 导出输出并保存。

用 tfvars 文件覆盖默认值

在 /root/tf/vars/terraform.tfvars 中写入 environment = "stage" 并重新应用,把输出保存到 /root/tf/vars/out/tfvars-outputs.json。值必须变成 stage——文件胜过默认值。

目录中具有特定名称的文件,即使不单独指定也会被自动读取。文件中只使用 이름 = 값(韩文,意为“名称 = 值”)的格式。

用命令行的值胜过文件

这次在命令行中用 -var environment=prod 传值并应用,把输出保存到 /root/tf/vars/out/cli-outputs.json。tfvars-outputs.json 必须保持不变(仍是 stage)。

优先级的顶端是运行时直接给出的值。上一步保存的输出文件不要覆盖,保存到新文件中。

用环境变量注入值

在 variables.tf 中声明 owner 变量,但不要把默认值固定写成 platform。用 TF_VAR_owner=platform 环境变量传值并应用,把输出保存到 /root/tf/vars/out/env-outputs.json(.owner.value 为 platform)。同时在 outputs.tf 中也添加 owner 输出。

工具会自动读取在变量名前加上固定前缀的环境变量。如果把同样的值固定写在默认值中,就无法证明环境变量确实起了作用。

用代码固定允许范围

在 variables.tf 中添加 replica_count 变量,并加入只允许 1 以上、5 以下的 validation 块。condition 和 error_message 都必须具备,并且 error_message 中必须原样包含允许范围 1-5 这几个字符。用超出范围的值(例如 -var replica_count=9)运行,把被拒绝的输出保存到 /root/tf/vars/out/validation.txt。

在变量块中放入承载条件和消息的块。消息必须让用户仅凭它就能改正,所以原样写出允许范围。

用 locals 组合名称前缀

在 /root/tf/vars/main.tf 中创建 locals 块,把 name_prefix 定义为用连字符连接 environment 和 owner 的值。在 outputs.tf 中添加 name_prefix 输出。在第 8 步中重新创建的 cli-outputs.json 里,name_prefix 必须是 prod-platform。

locals 是无法从外部注入的具名表达式。构造出用连字符连接两个变量的值,并把它作为输出导出。

把带有说明的输出集中起来

把输出集中到 /root/tf/vars/outputs.tf 一处,至少放置四个(environment、owner、name_prefix、config_path),并且给所有输出都加上 description。config_path 原样导出这个配置所创建的 local_file 的 filename。

输出是这套配置的公共接口,所以集中在一个文件里。只要有一个缺少说明,评分就会通过统计数量把它找出来。

遮蔽敏感值,并确认其局限

在 variables.tf 中用 sensitive = true 声明 api_token 变量,并通过 TF_VAR_api_token 传值。在 outputs.tf 中也添加 api_token 输出,并设为 sensitive = true。最后同时提供 -var environment=prod、TF_VAR_owner=platform 和 TF_VAR_api_token 并应用,然后重新创建 cli-outputs.json,并把供人阅读格式的输出也保存到 /root/tf/vars/out/sensitive.txt。后者中必须是被遮住的标记而不是值,并且不能看到真实的令牌字符串。

变量和输出两边都需要敏感标记。分别保存供人阅读的输出和供机器读取的输出,比较这两种结果有何不同。