Packer 现在支持 HCL2,所以我重写了现有的 JSON 格式代码。
![]()
我是基础设施工程师寺冈。Packer
迎来了期待已久的更新,
它终于支持 HCL2 了!
这次,我尝试用基于 HCL2 的 JSON 重写现有的代码,所以
我想在比较每个代码的同时进行总结。
Packer是什么?
用于创建多云兼容黄金镜像的命令行工具。
创建这种黄金镜像的工具
与不可变基础设施和蓝绿部署非常兼容,并且
在服务器频繁创建和销毁的环境中非常有用,例如使用自动扩展。
该项目仍在 HashiCorp 进行开发,使用 Golang 编写。Terraform
也是一个知名的工具,因此很多人可能都熟悉它。
不仅
支持
虽然它支持大量的服务(在 Packer 中称为构建器),但
它的优势在于可以使用通用格式编写代码来描述所有构建器中的流程。
之前仅支持 JSON 格式,但从
1.5 版本开始,已支持 HCL2 格式。
截至本文撰写之时(2020 年 3 月 31 日),该功能仍处于测试阶段,因此
最好在生产环境中使用前进行全面测试。
什么是HCL?
HCL是HashiCorp配置语言的缩写,也由HashiCorp公司开发。
虽然它的实现与Json兼容,但它是一种专有语言,允许使用与Json完全不同的独特描述。HCL
旨在与命令行工具配合使用,并且长期以来一直受到Terraform的支持,因此
任何编写过tf文件的人都可能对它感到熟悉。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
- 收购完成后删除该实例
这是一个流程。
由于可以使用 IAM 角色获取 AMI 信息,因此
执行所需的 IAM 角色已预先
在运行 packer 命令的 EC2 实例上角色所需的权限概述如下。
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 中,我们使用变量来表示变量。
就像编程语言一样,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 格式,
可以将一个文件中的内容拆分成单独的源文件和构建文件。HCL2
的另一个特性是允许您在代码中间插入注释。
变量可以使用“var.变量名”的方式引用。
在 build.pkr.hcl 文件中,会读取源设置
,而配置程序部分则会写入构建过程中要执行的进程。
源设置部分是一个列表类型,因此可以指定多个源,如下所示。
sources = [ "source.amazon-ebs.example", "source.amazon-ebs.example2" ]
运行构建时,请转到模板文件所在的目录并运行
$ packer build -var-file=variables.pkrvars.hcl ./
这将加载并执行当前目录中的所有文件。
当前问题
Packer 有一个验证命令可以检查语法,但
用 HCL 编写代码时无法使用该命令。
期待未来的更新。https
://github.com/hashicorp/packer/issues/8538
概括
Packer 是一个用于实践云服务 DevOps 的实用工具。
它很容易集成到您的 CI/CD 流程中,而且 Packer 本身的配置也非常简单,因此
我们鼓励大家试用一下。
0