56_packer的使用

JSON Template Structure

模板是一个JSON对象,它有一组配置Packer各个组件的键。下面列出了模板中可用的密钥。每把钥匙都要注明是否需要。

builders(必需)

是一个或多个对象的数组,用于定义将用于为此模板创建机器映像的构建器,并配置这些构建器中的每一个。有关如何定义和配置生成器的更多信息,请阅读关于在模板中配置生成器的小节。

description(可选)

是一个字符串,提供对模板功能的描述。此输出仅用于inspect命令.

min_packer_version(可选)

是一个字符串,它具有解析模板所需的最低packer版本。这可用于确保模板使用正确版本的封隔器。无法指定最大版本,因为Packer保留了与Packer修复程序的向后兼容性。

post-processors (可选)

是一个或多个对象的数组,定义了要对构建的图像进行的各种后处理步骤。如果未指定,则不会进行任何后处理。有关后处理程序的功能以及如何定义它们的更多信息,请阅读关于在模板中配置后处理程序这一小节。

provisioners(可选)

一个或多个对象的数组,用于定义将用于为每个构建器创建的计算机安装和配置软件的provisioner。如果未指定,则不会运行任何提供程序。有关如何定义和配置提供者的更多信息,请阅读关于在模板中配置提供者的小节。

variables(可选)

是一个或多个键/值字符串的对象,用于定义模板中包含的用户变量。如果未指定,则不会定义任何变量。有关如何定义和使用用户变量的更多信息,请阅读关于模板中用户变量的小节。

说明:

JSON不支持注释,Packer将未知密钥报告为验证错误。如果您想对模板进行注释,可以在根级键前面加下划线。实例:
'''JSON
{
"_comment": "This is a comment",
"builders": [{}]
}
'''

重要提示:只有根级别的键才能以下划线为前缀。构建程序、提供程序等中的密钥仍将导致验证错误。
注:Packer支持1.6.0版本的HCL2。HashiCorp配置语言不支持模板文件中任何位置的注释。如果注释对您很重要,请考虑使用packer HCL2_update命令将JSON模板升级到HCL2。如果您还没有准备好升级到HCL,一个解决方法是在运行Packer构建之前,使用jq从Packer模板中删除不受支持的注释。

例如,这里有一个名为commented_template.json的文件:

'''JSON
{
"_comment": ["this is", "a multi-line", "comment"],
"builders": [
{
"_comment": "this is a comment inside a builder",
"type": "null",
"communicator": "none"
}
],
"_comment": "this is a root level comment",
"provisioners": [
{
"_comment": "this is a different comment",
"type": "shell",
"_comment": "this is yet another comment",
"inline": ["echo hellooooo"]
}
]
}

如果使用以下jq命令:

{
"builders": [
{
"type": "null",
"communicator": "none"
}
],
"provisioners": [
{
"type": "shell",
"inline": ["echo hellooooo"]
}
]
}

该工具将生成一个新文件,其中包含:

{
"builders": [
{
"type": "null",
"communicator": "none"
}
],
"provisioners": [
{
"type": "shell",
"inline": ["echo hellooooo"]
}
]
}
一旦您得到了未注释的文件,您就可以像往常一样在其上调用packer构建。

如果你安装的jq没有walk功能,并且你得到了一个错误,比如:

jq: error: walk/1 is not defined at ,
您可以创建一个文件~/.jq,并手动添加walk函数。
'''

模板示例

下面是一个基本模板的示例,该模板可以与打包器构建一起调用。它将在AWS中创建一个实例,运行后将脚本复制到其中,并使用SSH运行该脚本。

'''JSON
{
"builders": [
{
"type": "amazon-ebs",
"access_key": "...",
"secret_key": "...",
"region": "us-east-1",
"source_ami": "ami-fce3c696",
"instance_type": "t2.micro",
"ssh_username": "ubuntu",
"ami_name": "packer {{timestamp}}"
}
],

"provisioners": [
{
"type": "shell",
"script": "setup_things.sh"
}
]
}
'''

Template Builders (模板生成器)

在模板中,构建器部分包含Packer应用于为模板生成机器图像的所有构建器的数组。
建设者负责为各种平台创建机器并从中生成图像。例如,EC2、VMware、VirtualBox等都有单独的构建程序。默认情况下,Packer附带了许多构建程序,也可 以扩展到添加新的构建程序中。

本文档页将介绍如何在模板中配置生成器。但是,每个构建器可用的特定配置选项必须从该特定构建器的文档中参考。

在模板中,生成器定义的一部分如下所示:
{
"builders": [
// ... one or more builder definitions here
]
}

Builder Definition (生成器定义)

一个构建器定义映射到恰好一个构建。构建器定义是一个JSON对象,它至少需要一个类型键。类型是将用于创建生成的机器映像的生成器的名称。
除了类型之外,其他键还配置生成器本身。例如,AWS构建器需要access_key、secret_key和一些其他设置。这些直接放置在生成器定义中。
构建器定义示例如下所示,在本例中配置AWS构建器:
{
"type": "amazon-ebs",
"access_key": "...",
"secret_key": "..."
}

Named Builds 命名生成器

每个内置Packer都有一个名称。默认情况下,该名称只是正在使用的生成器的名称。总的来说,这已经足够好了。名称只是正在发生的事情的输出中的一个指标。但是,如果需要,可以使用生成器定义中的名称键指定自定义名称。
如果定义了多个使用相同底层构建器的构建,这一点尤其有用。在这种情况下,必须至少为其中一个指定名称,因为这些名称必须是唯一的。

Communicators 交流者

每个构建都与一个通信器相关联。通讯器用于建立连接,以提供远程机器(如AWS实例或本地虚拟机)。
各种构建器的所有示例都显示了一些通信器(通常是SSH),但通信器是高度可定制的,因此我们建议阅读通信器文档。

Template Communicators 模板通信器

通信器是Packer在创建机器时用来上传文件、执行脚本等的机制。
通信器在生成器部分中进行配置。

通信器(字符串)-Packer目前支持三种通信器:

none 不使用通讯器。如果设置了此选项,则大多数预设置程序也无法使用。
ssh 将建立到机器的ssh连接。这通常是默认设置。
winrm 将建立winrm连接。

除上述内容外,一些构建者还可以使用自定义通讯器。例如,Docker构建器有一个“Docker”通信器,它使用Docker exec和Docker cp来执行脚本和复制文件。
注:pause_before_connecting(duration string | ex:“1h5m2s”)-我们建议您启用SSH或WinRM作为来宾引导脚本的最后一步,但有时您可能会遇到竞争情况,需要Packer等待才能尝试连接到来宾。如果最终出现这种情况,可以使用模板选项pause_before_connecting。默认情况下,没有暂停。例如,如果将pause_before_connecting设置为10m,Packer将检查它是否可以正常连接。但是,一旦连接尝试成功,它将断开连接,然后等待10分钟,然后再连接到来宾并开始配置。

准备使用Communicator

根据你的构建者,你的沟通器可能没有“开箱即用”所需的一切。
如果你是从云映像构建的(例如,在亚马逊上构建),那么你的云提供商很有可能已经在映像上为你预配置了SSH,这意味着你所要做的就是在Packer模板中配置通信器。
但是,如果您是从一个全新且未配置的操作系统映像构建的,那么您几乎总是需要执行一些额外的工作来在来宾计算机上配置SSH。对于大多数操作系统发行版,这项工作将由boot_command执行,该命令引用一个文件,该文件提供了安装操作系统时常见的交互式问题的答案。此文件的名称因操作系统而异;一些常见的例子是Debian所需的“预置”文件、Centostart所要求的“kickstart”文件,或者Windows所需要的“应答文件”,也称为Autounattend.xml文件。为了简单起见,我们将在文档的其余部分中将此文件称为“预设”文件。
如果您不熟悉如何使用预先设置的文件自动引导映像,请查看我们的映像引导快速指南,或者研究您特定客户操作系统的自动配置。了解如何自动初始化操作系统对于成功使用Packer至关重要。

Communicator特定选项

有关如何使用每个通信器的更多详细信息,请访问通信器页面。

Template Engine 模板引擎

模板中的所有字符串都由一个通用的Packer模板引擎处理,其中的变量和函数可以用于在运行时修改配置参数的值。

模板的语法使用以下约定:

任何与模板相关的内容都会出现在双大括号内: {{}}。
函数直接在大括号中指定, 例如{{timestamp}}。
模板变量以句点为前缀并大写, 例如{{.Variable}}。

Functions 函数

函数在字符串上和字符串内执行操作,例如,{{timestamp}}函数可以在任何字符串中用于生成当前时间戳。
这对于需要唯一密钥(如AMI名称)的配置非常有用。
通过将AMI名称设置为类似My Packer AMI{{timestamp}}的名称,AMI名称将一直到第二个名称都是唯一的。
如果您需要大于1秒的粒度,则应使用{{uuid}},例如,当您在同一模板中有多个构建器时。

以下是可用功能的完整列表供参考。

build_name-正在运行的构建的名称。
build_type-当前使用的生成器的类型。
clean_resource_name-图像名称只能包含特定字符并具有最大长度,例如GCE上的63和Azure上的80。clean_resource_name将把大写转换为小写,并用“-”字符替换非法字符。
env-返回环境变量。
build-此引擎将允许您从提供程序和后处理器访问提供连接信息和基本实例状态信息的特殊变量。
isotime[FORMAT]-UTC时间,可以格式化。
lower-字符串小写。
packer_version-返回packer版本。
pwd-执行Packer时的工作目录。
replace-(old,new string,n int,s)replace返回字符串s的副本,其中前n个不重叠的old实例被new替换。
replace_all-(old,new string,s)ReplaceAll返回字符串s的一个副本,其中旧字符串的所有非重叠实例都被新字符串替换。
split-使用分隔符拆分输入字符串并返回请求的子字符串。
template_dir-构建模板的目录。
timestamp-Packer进程启动时的Unix时间戳(UTC)。
uuid-返回一个随机uuid。
upper-将字符串大写。
user-指定用户变量。

Template variables 模板变量

模板变量是Packer在构建时自动设置的特殊变量。一些构建器、提供器和其他组件具有仅可用于该组件的模板变量。模板变量是可识别的,因为它们以句点为前缀,例如{{.Name}}。例如,当使用shell生成器模板变量时,可以自定义execute_command参数,该参数用于确定Packer将如何运行shell命令。
{
"provisioners": [
{
"type": "shell",
"execute_command": "{{.Vars}} sudo -E -S bash '{{.Path}}'",
"scripts": ["scripts/bootstrap.sh"]
}
]
}
{{ .Vars }} and {{ .Path }}模板变量将分别替换为环境变量的列表和要执行的脚本的路径。

isotime Function Format Reference 等时函数格式参考

那么在Packer模板函数中是什么样子的呢?以下是如何使用等时函数声明变量的示例。
"variables": {
"myvar": "packer-{{isotime 2006-01-02 03:04:05}}"
}

您可以尝试在打包器模板或打包器控制台中修改以下示例,以了解如何设置不同的时间戳:

Input | Output
"packer-{{isotime 2006-01-02}}" | "packer-2021-05-17"
"packer-{{isotime Jan-_2-15:04:05.000}}" | "packer-May-17-23:40:16.786"
"packer-{{isotime 3:04PM}}" | "packer-11:40PM"
"{{ isotime }}" | "June 7, 7:22:43pm 2014"
"{{isotime 2006-01-02}}" | "2014-06-07"
"{{isotime Mon 1504}}" | "Sat 1922"
"{{isotime 02-Jan-06 03\_04\_05}}" | "07-Jun-2014 07_22_43"
"{{isotime Hour15Year200603}}" | "Hour19Year201407"

函数isotime的格式使用神奇的参考日期Mon Jan 2 15:04:05-0700 MST 2006,具体如下:

     Day of Week	    Month	     Date	Hour	Minute	Second	Year	Timezone

Numeric - 01 02 03(15) 04 05 06 -0700
Textual Monday (Mon) January(Jan) - - - - - MST

split Function Format Reference 拆分函数格式参考

以下是使用上述选项的一些示例:
build_name = foo-bar-provider

{{split build_name "-" 0}} = foo
{{split "fixed-string" "-" 1}} = string

请注意,双引号字符需要在模板内部转义(在这种情况下,在固定字符串值上):
{
"post-processors": [
[
{
"type": "vagrant",
"compression_level": 9,
"keep_input_artifact": false,
"vagrantfile_template": "tpl/{{split build_name "-" 1}}.rb",
"output": "output/{{build_name}}.box",
"only": ["org-name-provider"]
}
]
]
}

replace Function Format Reference 替换函数格式引用

以下是使用替换选项的一些示例:
build_name = foo-bar-provider

{{ replace_all "-" "/" build_name }} = foo/bar/provider
{{ build_name | replace "-" "/" 1 }} = foo/bar-provider

Template Post-Processors 模板后处理器

模板中的后处理器部分配置将对构建者构建的图像进行的任何后处理。后处理的示例包括压缩文件、上传工件等。
后处理器是可选的。如果模板中未定义后处理程序,则不会对图像进行后处理。构建的结果伪影只是构建器输出的图像。
本文档页将介绍如何在模板中配置后处理器。但是,每个后处理器可用的特定配置选项必须参考该特定后处理器的文档。
在模板中,后处理器定义的一部分如下所示:
{
"post-processors": [
// ... one or more post-processor definitions here
]
}
对于每个后处理器定义,Packer将获取每个定义的构建器的结果,并将其发送到后处理器。这意味着,如果在一个模板中定义了一个后处理程序和两个生成器,则默认情况下,后处理程序将运行两次(每个生成器一次)。如果你愿意的话,有一些方法可以控制构建器后处理器的应用,稍后将介绍。还可以防止后处理器运行。

Post-Processor Definition 后处理器定义

在模板中的后处理器阵列中,有三种方法可以定义后处理器。有简单的定义、详细的定义和顺序定义。
另一种思考方式是,“简单”和“详细”的定义是“序列”定义的快捷方式。
一个简单的定义只是一个字符串;后处理程序的名称。下面显示了一个示例。当后处理器不需要额外的配置时,使用简单的定义。
{
"post-processors": ["compress"]
}

一个详细的定义是JSON对象。它与构建者或提供者的定义非常相似。它包含一个类型字段来表示后处理器的类型,但也可能包含后处理器的附加配置。当除了后处理器的类型之外还需要额外的配置时,会使用详细的定义。下面显示了一个示例。
{
"post-processors": [
{
"type": "compress",
"format": "tar.gz"
}
]
}
序列定义是由其他简单或详细定义组成的JSON数组。
数组中定义的后处理器按顺序运行,每个后处理器的工件都被馈送到下一个,并且任何中间工件都被丢弃。序列定义不能包含其他序列定义。
序列定义用于将多个后处理程序链接在一起。
下面显示了一个示例,其中构建的工件被压缩,然后上传,但压缩的结果没有保留。非常重要的是,任何需要按顺序运行的后处理器都要按顺序运行!
{
"post-processors": [
["compress", { "type": "upload", "endpoint": "http://example.com" }]
]
}

Input Artifacts 输入工件

当使用后处理器时,输入工件(来自构建器或另一个后处理器)在后处理器运行后默认会被丢弃。这是因为通常情况下,您不希望中间工件处于创建最终工件的过程中。然而,在某些情况下,您可能希望保留中间工件。您可以通过将keep_put_artifact配置设置为true来告诉Packer保留这些工件。示例如下所示:
{
"post-processors": [
{
"type": "compress",
"keep_input_artifact": true
}
]
}
此设置将仅将输入工件保留到特定的后处理器。如果您指定了一系列后处理程序,那么默认情况下,除了显式声明保留输入工件的后处理程序的输入工件外,所有中介都会被丢弃。

Run on Specific Builds 在特定构建上运行

您可以使用only或except字段仅对特定的生成运行后处理程序。
这两个字段执行您所期望的操作:only将仅在指定的生成上运行后处理程序,except将在指定生成以外的任何生成上运行前处理程序。将执行一系列后处理器,直到跳过后处理器为止。
下面显示了一个仅被使用的示例,但except的用法实际上是相同的。
只能在“详细”字段中指定only和except。如果要运行一系列后处理器,则only和except将影响该后处理器并停止该序列。
-except选项可以专门跳过已命名的后处理器。only选项忽略后处理程序。
([
{
"name": "vbox",
"type": "vagrant",
"only": ["virtualbox-iso"]
},
{
"type": "compress"
}
],
[
"compress",
{
"type": "upload",
"endpoint": "http://example.com"
}
])
only或except中的值是生成名称,而不是生成器类型。名称是HCL中必需的块标签,但在遗留JSON中,构建名称默认为其构建程序的类型(例如docker或amazon-ebs或virtualbox-iso),除非在配置中指定了特定的名称属性。

Template Provisioners 模板设置程序

在模板中,provisioners部分包含一组所有Provisioner,Packer应使用这些Provisioner在运行的机器中安装和配置软件,然后再将其转换为机器映像。
提供程序是可选的。如果模板中未定义任何预设置程序,则在生成的机器映像中不会安装除默认设置之外的任何软件。然而,这并不典型,因为Packer的大部分价值在于生成预配置软件的多个相同映像。
在模板中,提供者定义的一部分如下所示:
{
"provisioners": [
// ... one or more provisioner definitions here
]
}
对于每个定义,Packer将为每个配置的构建运行预配置程序。提供程序将按照在模板中定义的顺序运行。

Provisioner Definition 设置程序定义

provisioner定义是一个JSON对象,它必须至少包含类型键。
此键指定要使用的提供程序的名称。对象中的其他密钥用于配置预设置器,后面将介绍的少数特殊密钥除外。
例如,“shell”提供程序需要一个键,如script,该键指定要在所创建的计算机中执行的shell脚本的路径。
下面显示了一个示例提供程序定义,将shell提供程序配置为在计算机中运行本地脚本:
{
"type": "shell",
"script": "script.sh"
}

Run on Specific Builds 在特定构建上运行

您可以使用only或except配置仅对特定的生成运行预设置程序。这两种配置可以实现您的预期:only将仅在指定的生成上运行provisioner,except将在指定生成以外的任何生成上运行provisioner。
下面显示了一个仅被使用的示例,但except的用法实际上是相同的:
{
"type": "shell",
"script": "script.sh",
"only": ["virtualbox-iso"]
}
only或except中的值是生成名称,而不是生成器类型。如果您还记得,默认情况下,构建名称只是它们的构建器类型,但如果您指定了自定义名称参数,则应将其用作值,而不是类型。except中的值也可以是后处理器名称。

On Error Provisioner

您可以选择创建一个称为错误清理设置程序的专用设置程序字段。除非正常的设置运行失败,否则此设置程序将不会运行。如果正常的设置运行失败,则此特殊错误设置程序将在实例关闭之前运行。这允许您在最后一分钟做出更改,并清理Packer可能无法自行清理的行为。
例如,用户可以使用此提供程序来确保实例在生成运行期间正确地取消订阅其连接到的任何服务。
错误清除脚本的玩具用法示例:
{
"builders": [
{
"type": "null",
"communicator": "none"
}
],
"provisioners": [
{
"type": "shell-local",
"inline": ["exit 2"]
}
],
"error-cleanup-provisioner": {
"type": "shell-local",
"inline": ["echo 'rubber ducky'> ducky.txt"]
}
}

Build-Specific Overrides 生成特定覆盖

虽然Packer的目标是生成相同的机器图像,但有时需要一段时间,使机器不同,然后才能最终收敛为相同。在这些情况下,根据构建的不同,可能需要为提供程序进行不同的配置。这可以使用特定于生成的覆盖来完成。
例如,在构建EC2AMI和VMware机器时可能需要这样做。默认情况下,源EC2 AMI可以设置具有管理权限的用户,而VMware机器没有这些权限。在这种情况下,shell脚本可能需要以不同的方式执行。当然,目标是希望shell脚本将这两个图像聚合为相同的。但是,它们最初可能需要以不同的方式运行。
此示例如下所示:
{
"type": "shell",
"script": "script.sh",
"override": {
"vmware-iso": {
"execute_command": "echo 'password' | sudo -S bash {{.Path}}"
}
}
}
如您所见,使用了替代键。该键的值是另一个JSON对象,其中键是生成器定义的名称。这个值又是另一个JSON对象。这个JSON对象只是像往常一样包含预设置器配置。此配置将合并到默认的设置程序配置中。

Pausing Before Running 执行前暂停

对于某些设置程序,有时需要在运行它之前暂停一段时间。特别是,在设置程序重新启动计算机的情况下,您可能需要等待一段时间才能启动下一个设置程序。
Packer模板中的每个provisioner定义都可能需要一个特殊的配置pause_bfore,即在运行该provisioner之前暂停的时间。默认情况下,没有暂停。
示例如下所示:
{
"type": "shell",
"script": "script.sh",
"pause_before": "10s"
}
对于上面的provisioner,Packer将等待10秒才能上传并执行shell脚本。

Retry on error 出现错误时重试

对于某些提供程序,有时需要在失败时重试。特别是在提供者依赖尚未完成的外部流程的情况下。
Packer模板中的每个provisioner定义都可以采用特殊的配置max_retrys,即provisioner在出现错误时重试的最大次数。默认情况下,最大重试次数为零,并且不会对错误进行重试。示例如下所示:
{
"type": "shell",
"script": "script.sh",
"max_retries": 5
}
对于上述设置程序,Packer最多将重试五次,直到停止失败。如果重试五次后,设置程序仍然失败,则整个构建将失败。

Timeout 超时

有时,一个命令所花费的时间可能比预期的要长得多
Packer模板中的每个provisioner定义都可能需要一个特殊的配置超时,即在考虑provisioner失败之前等待的时间。
默认情况下,没有超时。示例如下所示:
{
"type": "shell",
"script": "script.sh",
"timeout": "5m"
}
对于上述提供程序,如果超过5分钟,Packer将取消脚本。
超时在调试模式下没有影响。

Template User Variables 模板用户变量

用户变量允许使用命令行、环境变量、Vault或文件中的变量进一步配置模板。这使您可以参数化模板,以便将机密令牌、特定于环境的数据和其他类型的信息排除在模板之外。这最大限度地提高了模板的可移植性。

用法

为了设置用户变量,您必须在模板的variables部分中定义它,或者使用命令行-var或-var文件标志来定义它。
即使您希望用户变量默认为空字符串,也最好明确定义它。这种明确性有助于减少新用户了解使用模板中的变量可以修改的内容所需的时间。
variables部分是用户变量名称到默认值的键/值映射。默认值可以是空字符串。示例如下:
{
"variables": {
"aws_access_key": "",
"aws_secret_key": ""
},

"builders": [
{
"type": "amazon-ebs",
"access_key": "{{user aws_access_key}}",
"secret_key": "{{user aws_secret_key}}"
// ...
}
]
}
在上面的例子中,模板定义了两个用户变量:aws_access_key和aws_secret_key。它们默认为空值。稍后,在我们定义的构建器中使用这些变量,以便为Amazon构建器配置实际密钥。
如果默认值为null,则需要用户变量。这意味着用户必须为此变量指定一个值,否则模板验证将失败。
用户变量是通过调用{{User}}函数来使用的,函数的形式为{{{User'variable'}}}。此函数可用于模板内的任何值,但类型除外:在生成器、提供程序、变量部分之外的任何位置。用户变量在模板的其余部分中全局可用。

Environment Variables 环境变量

可以使用用户变量在模板中使用环境变量。env函数仅在用户变量的默认值内可用,允许您将用户变量默认为环境变量。示例如下所示:
{
"variables": {
"my_secret": "{{env MY_SECRET}}"
}
}
这将默认“my_secret”为“my_secret”环境变量的值(如果不存在,则为空字符串)。

Consul keys 总密钥

总密钥可以使用领事密钥函数在模板中使用。由于与上述环境变量类似的原因,此函数仅在用户变量的默认值内可用。
{
"variables": {
"soft_versions": "{{ consul_key my_image/softs_versions/next }}"
}
}
这将把soft_versions默认为consur中键my_image/softs_versions/next的值。
consur的配置(地址、令牌…)必须指定为环境变量,如文档中所述。

Vault Variables Vault变量

机密可以从Vault中读取,并在模板中用作用户变量。vault功能仅在用户变量的默认值内可用,允许您将用户变量默认为vault机密。
使用v2 kv引擎的示例:
如果使用vault kv put secret/hello foo=world将值存储在vault中,则可以使用以下模板引擎访问该值:
{
"variables": {
"my_secret": "{{ vault /secret/data/hello foo}}"
}
}
将分配“my_secret”:“world”
使用v1 kv引擎的示例:
如果在vault中存储值,请使用:
vault secrets enable -version=1 -path=secrets kv
vault kv put secrets/hello foo=world
您可以使用以下模板引擎访问它:
{
"variables": {
"VAULT_SECRETY_SECRET": "{{ vault secrets/hello foo}}"
}
}
此示例访问Vault路径secret/data/foo,并返回存储在键栏上的值,将其存储为“my_secret”。
为了使其工作,必须将环境变量VAULT_TOKEN和VAULT_ADDR设置为有效值。
我们使用的api工具允许通过环境变量对Vault客户端进行更多自定义配置。
可用环境变量的完整列表为:
"VAULT_ADDR"
"VAULT_AGENT_ADDR"
"VAULT_CACERT"
"VAULT_CAPATH"
"VAULT_CLIENT_CERT"
"VAULT_CLIENT_KEY"
"VAULT_CLIENT_TIMEOUT"
"VAULT_SKIP_VERIFY"
"VAULT_NAMESPACE"
"VAULT_TLS_SERVER_NAME"
"VAULT_WRAP_TTL"
"VAULT_MAX_RETRIES"
"VAULT_TOKEN"
"VAULT_MFA"
"VAULT_RATE_LIMIT"
并且可以在这里找到关于这些变量中的每一个的使用的详细文档。

AWS Secrets Manager Variables AWS Secrets Manager变量

机密可以从AWS机密管理器中读取,并在模板中用作用户变量。aws_secretsmanager函数仅在用户变量的默认值内可用,允许您将用户变量默认为aws Secrets Manager机密。

Plaintext Secrets 明文机密

{
"variables": {
"password": "{{ aws_secretsmanager globalpassword }}"
}
}
在上面的示例中,假设机密全局密码不是作为密钥对存储的,而是作为单个非JSON字符串值存储的。aws_secretsmanager函数将作为原始字符串返回。

Single Key Secrets 单一密钥机密

{
"variables": {
"password": "{{ aws_secretsmanager sample/app/password }}"
}
}
在上面的示例中,假设sample/app/password中只存储了一个密钥。如果其中存储了多个密钥,则需要指示要获取的特定密钥,如下所示。

Multiple Key Secrets 多个密钥秘密

{
"variables": {
"db_password": "{{ aws_secretsmanager sample/app/passwords db }}",
"api_key": "{{ aws_secretsmanager sample/app/passwords api_key }}"
}
}

Using array values 使用数组值

有些模板需要数组值。您也可以将模板变量用于这些。例如,amazon ebs构建器有一个名为ami_regions的配置参数,它接受一个将ami复制到的区域数组。您可以通过使用一个变量来参数化它,该变量是一个区域列表,并加上一个,。例如:
{
"variables": {
"destination_regions": "us-west-1,us-west-2"
},
"builders": [
{
"ami_name": "packer-qs-{{timestamp}}",
"instance_type": "t2.micro",
"region": "us-east-1",
"source_ami_filter": {
"filters": {
"name": "ubuntu-xenial-16.04-amd64-server-",
"root-device-type": "ebs",
"virtualization-type": "hvm"
},
"most_recent": true,
"owners": ["099720109477"]
},
"ami_regions": "{{user destination_regions}}",
"ssh_username": "ubuntu",
"type": "amazon-ebs"
}
]
}

Setting Variables 设置变量

现在我们已经介绍了如何在模板中定义和使用用户变量,接下来的重点是如何实际设置这些变量。
Packer公开了两种设置用户变量的方法:从命令行或从文件。

From the Command Line 从命令行

要从命令行设置用户变量,-var标志被用作打包器构建(以及其他一些命令)的参数。
继续上面的例子,我们可以使用下面的命令构建模板。
为了便于阅读,命令被拆分为多行,但当然也可以是单行。
packer build
-var 'aws_access_key=foo'
-var 'aws_secret_key=bar'
template.json
如您所见,为了设置多个变量,可以多次指定-var标志。此外,稍后在命令行上设置的变量会覆盖任何早期的同名设置变量。
警告如果您从cmd.exe调用Packer,则应该对变量进行双引号引用,而不是单引号引用。例如:
packer build -var "aws_secret_key=foo" template.json

From a File 从文件

也可以从外部JSON文件设置变量。var文件标志读取一个包含变量到值的键/值映射的文件,并设置这些变量。
示例JSON文件可能如下所示:
{
"aws_access_key": "foo",
"aws_secret_key": "bar"
}
它是一个JSON对象,其中键是变量,值是变量值。假设这个文件在variables.json中,我们可以使用以下命令构建模板:
On Linux :
$ packer build -var-file=variables.json template.json
On Windows :
packer build -var-file variables.json template.json
可以多次指定-var文件标志,并读取和应用多个文件中的变量。正如您所期望的,从稍后指定的文件中读取的变量会覆盖先前设置的变量。

将-var和-var文件标志组合在一起也可以按照预期工作。稍后在命令中设置的变量将替代先前设置的变量。因此,例如,在下面的命令中使用上面的variables.json文件:
packer build
-var 'aws_access_key=bar'
-var-file=variables.json
-var 'aws_secret_key=baz'
template.json
导致以下变量:
Variable Value
aws_access_key foo
aws_secret_key baz

Sensitive Variables 敏感变量

如果您使用环境来设置敏感的变量,您可能不希望将该变量打印到Packer日志中。您可以通过将敏感变量添加到Packer模板中的“敏感变量”列表来确保敏感变量不会打印到日志中:
{
"variables": {
"my_secret": "{{env MY_SECRET}}",
"not_a_secret": "plaintext",
"foo": "bar"
},

"sensitive-variables": ["my_secret", "foo"],
...
}
上面的代码片段将与您没有设置“敏感变量”的情况完全相同,只是Packer UI和日志将用替换“bar”的所有实例以及“my_secret”的值。
这可以让您确信,您不会意外地将机密以明文打印到我们的日志中。

Recipes 步骤

使provisioner步骤以变量的值为条件

根据变量的值,Packer模板中没有特定的语法用于使provisioner步骤具有条件。
但是,您可以通过在执行的命令中引用变量来实现这一点。
例如,以下是如何使shell本地provisioner仅在do_nexpose_scan变量为非空时运行。
{
"type": "shell-local",
"command": "if [ ! -z "{{user do_nexpose_scan}}" ]; then python -u trigger_nexpose_scan.py; fi"
}

Using HOME Variable 使用HOME变量

为了使用$HOME变量,您可以在Packer中创建一个HOME变量:
{
"variables": {
"home": "{{env HOME}}"
}
}
这将可用于模板的其余部分,即:
{
"builders": [
{
"type": "google",
"account_file": "{{ user home }}/.secrets/gcp-{{ user env }}.json"
}
]
}

posted on 2024-03-13 10:58  鸟叔书  阅读(36)  评论(0编辑  收藏  举报