provisioner
块
注意:此页面是关于 Packer 的 HCL2 模板的。 HCL2 模板最初作为 Beta 功能被 Packer 1.5 版引入。从 v1.7 开始,HCL2 支持不再处于测试阶段,并且是编写 Packer 配置的首选方式。对于稳定的旧风格配置语言,请参阅模板文档。从 v1.6.2 开始,您可以使用 hcl2_upgrade
命令将遗留的 JSON 模板转换为 HCL2 配置文件。
provisioner
块声明了配置器的配置方式。
# builds.pkr.hcl
build {
# ...
provisioner "shell" {
inline = [
"echo provisioning all the things",
"echo the value of 'foo' is '${var.foo}'",
]
}
}
配置器通过内置的和第三方软件在启动后安装和配置机器镜像。Provisioner 使得镜像系统做好了可以被直接使用的准备。
有关配置器的更多信息可以在这里找到。
在指定的 source
上运行
您可以使用 only
或 except
配置来指定仅在特定 source
上运行配置器。only
将只在指定的 source
上运行配置器,except
将阻止在指定 source
上运行配置器。
这里有一个 only
的示例,但 except
的用法实际上是相同的:
# builds.pkr.hcl
source "amazon-ebs" "first-example" {
#...
}
source "amazon-ebs" "second-example" {
#...
}
build {
sources = [
"source.amazon-ebs.first-example",
"source.amazon-ebs.second-example",
]
provisioner "shell" {
# This provisioner only runs for the 'first-example' source.
only = ["amazon-ebs.first-example"]
inline = [
"echo provisioning all the things",
"echo the value of 'foo' is '${var.foo}'",
]
}
provisioner "shell" {
# This runs with all sources.
inline = [
"echo Hi World!"
]
}
}
only
和 except
中的 source
名称必须去掉 source.
的前缀。
only
或 except
中的值是 source
块的名称,而不是构建器类型或构建名称。
注意:仅在参数中,except
将匹配构建名称(例如:my_build.amazon-ebs.first-example
),但在配置器中,它们将匹配 source
名称(例如:amazon-ebs.third-example
)。
builder
块的 override
配置
虽然 Packer 的目标是生成相同的机器镜像,但有时在机器最终收敛为相同配置之前有一段时间内它们是不同的。在这些情况下,配置器可能需要为不同的构建设置不同的配置。我们可以在 builder
块中声明 override
参数来完成。
一个例子是构建 EC2 AMI 和 VMware 镜像。默认情况下,源 EC2 AMI 可能会配置有一个具有管理权限的用户,而 VMware 虚拟机没有这些权限。在这种情况下,可能需要以不同方式执行 shell 脚本。当然,目标是希望 shell 脚本能够最终将这两个镜像收敛为相同的。但是,它们最初可能需要以不同方式运行。
这个例子如下所示:
source "null" "example1" {
communicator = "none"
}
source "null" "example2" {
communicator = "none"
}
source "null" "example3" {
communicator = "none"
}
build {
sources = ["source.null.example2", "source.null.example3"]
source "source.null.example1" {
// Give a name to this source
name = "renamed"
}
provisioner "shell-local" {
inline = ["echo not overridden"]
override = {
example3 = {
inline = ["echo overrides for example3"]
}
// Refer to the source with the given name
renamed = {
inline = ["echo overrides for renamed"]
}
}
}
}
在这里例子里,使用了 override
配置。此参数的值是另一个 HCL 映射,其中键是source
块的名称,它的值又是另一个 HCL 映射。这一层的 HCL 属性映射仅包含正常的 provisioner
块的配置,这个配置会与默认的 provisioner
块配置进行合并。
错误处理器
有一个可选的名为 error-cleanup-provisioner
的专用配置器。该配置器只有在正常的配置器运行失败时,在实例关闭之前运行。这允许我们在最后一刻进行变更并清理 Packer 可能无法自行清理的资源。
例如,用户可以使用此配置器来确保实例正确地取消了对它在构建运行期间连接到的所有服务的订阅。
错误清理脚本的一个玩具示例:
source "null" "example" {
communicator = "none"
}
build {
sources = ["source.null.example"]
provisioner "shell-local" {
inline = ["exit 2"]
}
error-cleanup-provisioner "shell-local" {
inline = ["echo 'rubber ducky'> ducky.txt"]
}
}
运行前暂停
对于某些配置器,有时需要在运行之前暂停一段时间。具体的例子,在配置器重启机器的情况下,我们可能会希望在启动下一个配置器之前等待一段时间。
Packer 模板中的每个配置器定义都可以声明一个特殊配置 pause_before
,这是运行该配置器之前暂停的时长。默认情况下不会暂停。一个例子如下所示:
# builds.pkr.hcl
build {
# ...
provisioner "shell" {
inline = [
"echo provisioning all the things",
"echo the value of 'foo' is '${var.foo}'",
]
pause_before = "10s"
}
}
对于上面的配置器,Packer 会等待 10 秒,然后再上传和执行 shell 脚本。
错误重试
对于某些配置器,有时需要在失败时重试。一个具体的例子,比如配置器依赖的外部流程尚未完成的情况时。
Packer 模板中的每个配置器定义都可以声明一个特殊配置 max_retries
,这是配置器在出错时重试的最大次数。默认情况下,max_retries
为零,并且此时不会进行重试错误。一个例子如下所示:
# builds.pkr.hcl
build {
# ...
provisioner "shell" {
inline = [
"echo provisioning all the things",
"echo the value of 'foo' is '${var.foo}'",
]
max_retries = 5
}
}
对于上面的配置器,Packer 最多会重试五次,直到停止失败。如果在重试五次后配置器仍然失败,那么整个的构建将失败。
超时设置
有时一个命令可能比预期花费更多的时间
Packer 模板中的每个配置器定义都可以声明一个特殊配置 timeout
,即在认定配置器失败之前等待的时长。默认情况下没有超时设置。一个例子如下所示:
# builds.pkr.hcl
build {
# ...
provisioner "shell" {
inline = [
"echo provisioning all the things",
"echo the value of 'foo' is '${var.foo}'",
]
timeout = "5m"
}
}
对于上面的配置器,如果超过 5
分钟,Packer 会停止执行脚本。
超时在调试模式下没有影响。
构建上下文变量(Build Contextual Variables)
Packer 允许从配置器读取连接信息和实例的基本状态信息。这些信息存储在 build
变量中。查看上下文变量文档以了解更多信息,并查看如何使用它们的示例。