Packer 现在支持 HCL2,所以我重写了现有的 JSON 格式代码。
![]()
我是基础设施工程师寺冈。Packer
终于迎来了期待已久的更新,
现在它支持 HCL2 了!
这次,我以 HCL2 为基础,重写了一些之前用 JSON 格式编写的代码,所以
我想比较和总结一下这两个版本的代码。
Packer是什么?
用于创建多云兼容黄金镜像的命令行工具。
用于创建此类黄金镜像的工具
非常适合不可变基础架构和蓝绿部署,并且
在服务器频繁创建和销毁的环境中(例如自动扩展)非常有价值。
该工具由 HashiCorp 公司继续开发,并使用 Golang 编写。
同样,Terraform 也是一款知名的工具,所以你们中的许多人可能都很熟悉它。
适用于主流云服务(例如 AWS、GCP 和 Azure)的镜像,以及
支持创建
它支持大量服务(在 Packer 中称为构建器),其
优势在于您可以使用适用于任何构建器的通用格式编写代码并描述处理过程。
此前仅支持 JSON 格式,但
1.5 版本新增了对 HCL2 格式的支持。
截至本文撰写之时(2020 年 3 月 31 日),该版本仍处于测试阶段,因此
最好在生产环境中使用前进行全面测试。
什么是HCL?
HCL 是 HashiCorp 配置语言的缩写,也由 HashiCorp 公司开发。
虽然它的实现与 JSON 兼容,但它是一种专有语言,语法与 JSON 完全不同。HCL
主要用于命令行工具,并且 Terraform 已经支持它一段时间了,因此
编写 Terraform 文件的人应该会比较熟悉它。
顺便一提,HCL 有两个版本:HCL1 和 HCL2,其中 HCL2 是当前的标准版本。
编写 Packer 模板(Json)
Packer 通过编写模板来创建镜像,
我们将使用 HCL2 编写模板内容,并将其与 JSON 格式进行比较。
首先,让我们看看 JSON 格式的模板内容是什么样的。
{ "builders": [ { "type": "amazon-ebs", "region": "{{user `region`}}", "source_ami_filter": { "filters": { "name": "{{user `ami_name`}}}*" }, "owners": [ "self" ], "most_recent": true }, "instance_type": "{{user `instance_type`}}", "ssh_username": "{{user `ssh_username`}}", "ami_name": "{{user `ami_name`}}_{{timestamp}}", "tags": { "Name": "{{user `ami_name`}}_{{timestamp}}" }, "iam_instance_profile": "{{user `iam_instance_profile`}}" } ], "provisioners": [ { "type": "shell", "inline": [ "sudo yum -y update" ] } ] }
类似 {{user `ami_name`}} 的部分是变量,
它们存储的值写在一个单独的文件中。
{ "ssh_username": "ec2-user", "region": "ap-northeast-1", "instance_type": "t3.micro", "ami_name": "ami-packer-test", "iam_instance_profile": "role-packer-test" }
使用此模板文件
$ packer build main.json -var-file=variables.json
通过执行该命令,
您可以在从 variables.json 文件中读取要存储在变量中的值的同时构建镜像。
如果您按照上述模板的内容进行构建,
- 使用 source_ami_filter 中写入的内容搜索基础 AMIID。
- 根据与搜索匹配的 AMI 启动构建过程。
- 从基础 AMI 启动一个新的 EC2 实例。
- 创建临时密钥对以登录您的 EC2 实例。
- 通过 SSH 登录到实例,并执行配置器中描述的过程。
- 停止 EC2 实例
- 从已停止的实例获取 AMI
- 收购完成后删除该实例
以下是执行的一系列流程。
获取 AMI 信息时,可以使用 IAM 角色,因此
在上面的示例中,执行 packer 命令的 EC2 实例
已预先配置了必要的 IAM 角色。IAM
角色所需的权限概述如下。
https://packer.io/docs/builders/amazon.html
编写 Packer 模板 (HCL2)
那么,如果我们用 HCL2 重写上面的 JSON 数据,它会是什么样子呢?
首先,我们将写入要存储在变量中的值。
我们将使用以下两个文件。
variables.pkrvars.hcl
ssh_username = "ec2-user" region = "ap-northeast-1" instance_type = "t3.micro" ami_name = "ami-packer-test" iam_instance_profile = "role-packer-test"
变量.pkr.hcl
变量 "ssh_username" { type = string description = "SSH 用户名" } 变量 "region" { type = string description = "AWS 区域" } 变量 "instance_type" { type = string description = "EC2 实例类型" } 变量 "ami_name" { type = string description = "EC2 AMI 名称" } 变量 "iam_instance_profile" { type = string description = "EC2 IAM 实例配置文件" }
要存储在变量中的值写入 variables.pkrvars.hcl 文件中。
在 JSON 中,格式为“值名称:值”,但在 HCL2 中,格式变为“值名称 = 值”。
在 HCL2 中,变量用 `variable` 表示。
与编程语言类似,HCL2 也存在类型概念,但
在这里,我们只使用字符串类型的变量。
此外,
- 数字类型
- 列表类型(列表)
- 地图类型(地图)
- 布尔类型(bool)
ETC。
接下来,我们将编写实际的构建处理代码。
我们将使用以下两个文件。
sources.pkr.hcl
## 源 source "amazon-ebs" "example" { region = var.region ami_name = "${var.ami_name}_{{timestamp}}" instance_type = var.instance_type iam_instance_profile = var.iam_instance_profile ssh_username = var.ssh_username source_ami_filter { owners = ["self"] most_recent = true filters { virtualization-type = "hvm" name = "${var.ami_name}*" root-device-type = "ebs" } } tags { Name = "${var.ami_name}_{{timestamp}}" } }
build.pkr.hcl
## 构建 build { sources = [ "source.amazon-ebs.example" ] provisioner "shell" { inline = [ "sudo yum -y update" ] } }
如您所见,原本以 JSON 格式写入一个文件的内容
可以拆分成两个单独的文件,分别命名为 source 和 build。
此外,HCL2 的一个关键特性是允许您在代码中间插入注释。
变量可以通过“var.variable_name”引用。
在 build.pkr.hcl 文件中,会读取源设置,
其中 provisioner 部分包含构建过程中要执行的进程。sources
部分的类型为列表,因此可以指定多个源,如下所示。
sources = [ "source.amazon-ebs.example", "source.amazon-ebs.example2" ]
运行构建时,请转到模板文件所在的目录并运行
$ packer build -var-file=variables.pkrvars.hcl ./
这将加载并执行当前目录中的所有文件。
当前问题
Packer 有一个用于语法检查的 validate 命令,但
在用 HCL 编写代码时无法使用。
希望这个问题能在未来的更新中得到解决。https
://github.com/hashicorp/packer/issues/8538
概括
Packer 是一个方便的工具,可用于使用云服务实现 DevOps。
它易于集成到 CI/CD 流程中,而且 Packer 本身的配置也非常简单,所以
我鼓励大家试用一下。
0
