变量与输出

LinuxBeginner
立即练习

简介

想象一下,你正在点咖啡。如果菜单上只写着「咖啡」,你每次可能都会拿到黑咖啡。但如果菜单提供了「尺寸」或「牛奶类型」等选项,你就可以自定义订单,而咖啡师不需要为每种组合学习新的配方。

在 Terraform 中,变量可以让配置重复使用。你只需修改输入值,无需重写整个文件。

输出可以让 Terraform 报告重要的结果值,例如 ID、名称或地址。变量和输出结合使用,可以让 Terraform 配置更加模块化,也更实用。

完成本实验后,你将拥有一个灵活的 Terraform 配置,可以根据需要创建具有不同名称的容器。

变量将配置逻辑与环境特定的数据分离开来。输出则负责将有用的结果值发布给用户或后续自动化流程。

创建变量文件

优秀的厨师会在开始烹饪前整理好食材。在 Terraform 中,最佳实践是将自定义选项(变量)放在独立文件中,而不是与主要配置混在一起。

这个文件的标准名称是 variables.tf。创建该文件不会改变 Terraform 的工作方式——Terraform 会读取目录中的所有 .tf 文件,并将它们视为一本完整的配置文件——但这样可以让配置更加有条理。

在 IaC 中,这种组织方式非常重要,因为实际配置通常会快速增长。将变量、资源和输出清晰分开,可以大幅简化后续维护。

进入项目目录并创建这个文件:

cd ~/project
touch variables.tf

现在已经有一个空文件,可以在其中定义变量。下一步将向文件中添加内容。

定义变量

现在需要声明有哪些可用选项。这就像在订单表单中添加一个「名称」字段。

使用 nano 打开 variables.tf:

nano variables.tf

添加以下代码块。它告诉 Terraform:「有一个名为 container_name 的选项,该选项接受文本(字符串);如果用户没有提供值,就使用 ExampleNginxContainer 作为名称。」

variable "container_name" {
  description = "Value of the name for the Docker container"
  type        = string
  default     = "ExampleNginxContainer"
}

保存并退出 nano(按 Ctrl+O,然后按 Enter,最后按 Ctrl+X)。

现在表单字段已经存在,接下来需要在配置中使用它。创建一个使用该变量的 main.tf 文件。

创建 main.tf:

nano main.tf

粘贴以下代码。注意 name = var.container_name。这就是将变量接入配置的方式。

terraform {
  required_providers {
    docker = {
      source  = "kreuzwerker/docker"
      version = "~> 3.0.1"
    }
  }
}

provider "docker" {}

resource "docker_image" "nginx" {
  name         = "nginx:latest"
  keep_locally = false
}

resource "docker_container" "nginx" {
  image = docker_image.nginx.image_id
  name  = var.container_name
  ports {
    internal = 80
    external = 8000
  }
}

记得保存并退出 nano。

使用 var.container_name 表示:「不要将名称直接写死;读取 container_name 变量中的值,并使用该值作为名称。」

定义输出

购买商品时,你会收到一张收据。在 Terraform 中,输出就像收据一样,会显示刚刚创建的资源的重要信息。

这对于获取资源创建前无法知道的信息非常有用,例如系统分配的随机 ID 或公共 IP 地址。

当某个基础设施组件需要将信息交给操作人员、另一个 Terraform 模块或后续自动化步骤时,输出尤其有用。

创建名为 outputs.tf 的文件,用于整理这些返回值。使用 nano 打开它:

nano outputs.tf

添加以下代码块。它告诉 Terraform:「完成操作后,输出 nginx 容器的 ID。」

output "container_id" {
  description = "ID of the Docker container"
  value       = docker_container.nginx.id
}

保存并退出 nano。

现在运行配置。

首先初始化项目,以下载 Docker provider:

terraform init

接下来应用配置。这次不指定容器名称,因此 Terraform 会使用默认值(ExampleNginxContainer)。使用 -auto-approve 可以跳过「yes」确认提示,节省时间。

terraform apply -auto-approve

查看输出的最底部。你应该会看到 Outputs:,其后显示 container_id。

覆盖变量

变量的真正优势在于:无需重写代码即可修改变量值。假设你想启动第二个容器,并为它设置不同的名称。你不需要编辑 main.tf。

只需使用 -var 选项告诉 Terraform 覆盖默认值即可。这就像告诉咖啡师:「实际上,把它改成大杯。」

运行以下命令:

terraform apply -var="container_name=MyDynamicContainer" -auto-approve

仔细查看输出。Terraform 会显示:docker_container.nginx must be replaced。

为什么会这样?因为在 Docker 中,运行中的容器不能轻易重命名。要更改名称,Terraform 会先销毁旧容器(-),再使用新名称创建一个新容器(+)。这体现了不可变基础设施的一个重要原则:我们通过替换对象来完成变更,而不是直接修改对象。

确认新容器正在运行:

docker ps --format "{{.Names}}"

你应该会看到 MyDynamicContainer。

总结

恭喜!你已经成功让 Terraform 代码具有动态性。

在本实验中,你学习了:

  • 变量:如何使用 variables.tf 为代码创建灵活的「表单字段」。
  • 引用:如何使用 var.variable_name 将这些值插入主要配置。
  • 输出:如何使用 outputs.tf 在运行结束后显示重要数据(即「收据」)。
  • 覆盖值:如何在命令行中使用 -var 输入新值,从而在不同场景中复用同一份代码。