packer 学习笔记

前言

网上有一个老哥用 packer 制作镜像的博客里开篇就提到[1]

Failure is success in progress.
—— Albert Einstein

不要害怕失败,在用 packer 的过程中你可能会失败很多次。我就经历了 virtualbox 安装失败、启动不了虚拟机,provisioning 阶段失败,ks.cfg 找不到,安装系统的时候失败……
手动创建 Vagrant Base Box 我也经历了十几次失败,打包的镜像不能 add,识别不了系统,SSH连接不上……

参考资料

互联网上有一些好资源:

如果你想了解手动创建 Vagrant Base Box 的过程和注意事项请查看 Vagrant 的官方文档以及theurbanpenguin的视频教程:

如果你想学习 Packer,我推荐你阅读 packer 官方教程

缘起

用过 Vagrant 就不会再想重复在虚拟机里装系统了。只需要一条命令就能立刻启动一个刚安装好的虚拟机,这比手动配置虚拟机并安装操作系统要快多了。在 Vagrantfile 里面可以定义 Provision,初次启动虚拟机的时候配置好环境。在 Git 仓库里带上 Vagrantfile,大家就能一键启动一个一模一样的开发环境。

如果你想定制 Vagrant Box,或者你使用的操作系统没有网上公开的 Vagrant Box 可用,你要创建一个 Vagrant Base Box。vagrant package可以将虚拟机打包成一个 Vagrant Box,但是只支持 VirtualBox 和 Hyper-V。vagrant package需要你手动配置虚拟机并安装好操作系统,配置 SSH 等,要么你基于现有的 vagrant box 启动一个机器,做一点修改然后再重新打包。手动配置,必须基于现有的 vagrant box,只支持 virtualbox 和 hyperv,这些都是创建 Vagrant Box 的痛点。

Packer 支持各种机器,通过 HCL 配置文件自动化创建机器的镜像。

我首先通过 Vagrant 的官方文档和 Youtube 上的视频教程,以及网上的各种博客学会了手动创建 Vagrant Base Box

阅读 Packer 官方教程,通过 Packer Docker 镜像教程学习了 Packer 的基本概念。使用 VirtualBox-iso Builder 和 Packer 的 vagrant 插件,实现一键从 ISO 安装镜像到 Vagrant Box。

Packer 官方教程没有直接讲如何从 ISO 安装镜像到 Virtual Box 的 Vagrant Box。Bento 项目里有各种 Linux 发行版制作 Vagrant Box 的代码,这就是基础设施即代码(IaC)的好处,想知道别人怎么配的,看代码就行了。

使用 Packer 镜像构建过程透明可追溯,避免“黑盒”操作(如手动修改镜像后忘记记录)。写文档记录如何配置环境十分重要,光有如何配置环境的文档还不够,文档作者在写的过程中很容易出现疏漏。如果在环境配置过程中做了某个修改后忘记记录,别人就无法复现你的环境了。又或者有的人文档写得不太好,别人跟着他的文档操作根本不能成功(有的人写文档也没想要别人能成功复现)。换句话说,文档记录的配置过程只是你的一面之词。只有配置代码化,任何人都能通过你给的代码启动一个一模一样的环境。这才算是完全透明可追溯的环境。HCL 配置文件本身就是代码,支持 Git 管理、代码审查和迭代优化。将镜像构建过程代码化(HCL),实现一键生成标准化系统镜像。

从一个 template.pkr.hcl 开始

Docker 启动一个容器镜像比虚拟机快得多,学习 Packer 可以从定制 Docker 容器开始[2]

// teamplate.pkr.hcl
packer {
  required_plugins {
    docker = {
      version = ">= 1.0.8"
      source = "github.com/hashicorp/docker"
    }
  }
}

source "docker" "ubuntu" {
  image  = "ubuntu:jammy"
  commit = true
}

build {
  name    = "learn-packer"
  sources = [
    "source.docker.ubuntu"
  ]
}

使用 packer 你不需要知道所有的 HCL 语法细节[3]。通常 packer 的配置文件名以.pkr.hcl 结尾。HCL 的语法很简单,主要是块(blocks)参数(arguments)。我对 HCL 的了解有限,一对大括号就是一个块,大括号里面的叫做属性也被叫做参数。

packer 块声明一些需要的插件。在命令行下运行 packer init template.pkr.hcl 安装需要的插件。

Each builder has its own unique set of configuration attributes.

source 块是用来配置 builder 的。source 块后面带着的 "docker" 是 build_type,"ubuntu" 是名字。source 块里面有什么属性取决于 build_type。source 就是告诉 packer 从什么地方/文件/基础镜像启动一个新的机器或者容器source 块是 builder 的配置,有什么配置属性取决于 builder plugin

builder 负责创建机器并生成镜像。当然这里的机器也可以是容器,镜像也可以就是一个虚拟机的硬盘文件。Builder 插件是用来创建机器和把机器打包成镜像的

build 块定义具体要 packer 做什么。在 sources 引用之前定义的 source 块。在终端运行 packer build 命令创建镜像。

packer build template.pkr.hcl

实际上你已经学会用 Packer 了,只不过你还需要更复杂的配置。你需要安装系统后配置系统,得到的系统镜像打包成 Vagrant Box 或者 Docker 镜像。

Provison

provision 是动词:为...提供必须品。在计算机里面就是准备环境的意思,为了部署或者开发提供必须要安装的软件和配置,就是 provision

provisioner 就是安装软件和配置的方式。provisoner 有 shell,ansible 等等。

provisioning 是 provison 的动名词,就是搭建配置 IT 基础设施的意思。provisioning 通俗讲就是搭环境,或者配环境。

HCL 变量

template.pkr.hcl 的每一个属性都是写死的,那还叫什么模板呢?

packer 里的变量其实是常量,可以理解为参数。通过配置参数,使用同一个模板(template)构建不一样的镜像

在 HCL 文件里面使用变量块声明变量[4]

variable "docker_image" {
  type    = string
  default = "ubuntu:jammy"
}

在 HCL 文件的其他地方就可以使用这个变量。

source "docker" "ubuntu" {
-  image  = "ubuntu:jammy"
+  image  = var.docker_image
   commit = true
}

变量通常有默认值,也可以没有默认值。变量的值是可以通过命令行参数指定的,也可以从配置文件(.pkrvars.hcl)读取变量的值。正是因为属性的值是可以通过变量配置,所以 Packer 的配置文件被称为模板(packer template)。

多文件 Packer 模板

packer build 可以接收一个目录作为参数[5],目录里面以 .pkr.hcl 结尾的文件都会被 packer 分析。

以 Bento 项目为例,将模板分成 3 个文件。

pkr-variables.pkr.hcl
pkr-builder.pkr.hcl
pkr-sources.pkr.hcl

pkr-variables 里面放的全是变量的声明,pkr-sources 里面全是 source 块,pkr-builder 里面是 build 块和 packer 块。各自的文件里面使用 locals 块根据变量来决定使用哪些脚本做 provison。locals 块就是一个根据变量的值做判断和计算地地方,然后给计算得到的结果一个新的名字。

Packer 制作 Vagrant Box 踩坑记录

  • ks.cfg 文件的 EOL 必须是 LF('\n')。又多了一个不用 Windows 写代码的理由

总结

学习 packer 制作 Vagrant Box 的过程中经历了 virtualbox 不能安装、启动不了虚拟机,provisioning 阶段失败,ks.cfg 找不到,安装过程失败。

我真的有打算要放弃了。但是还有那么一丁点成功的希望,最后折腾了三四天还是成功了,我才明白 “Failure is success in progress” 的含义。

学一个东西带来的收获往往不止是这个学会这个东西本身。在学习的过程中会增长见识,也会有一些心态上的锻炼。学习也是一种修行。与其担心 AI 在各个方面都比我强,担心未来,不如去学一些自己不会的东西,自然就会有收获。

题外话:

原本想写个制作 Vagrant Box 的教程,但是心里很乱。不知道该怎么写起,写一个点就容易越写越深,介绍了 Packer 的好处才发现光顾着介绍使用 Packer 有啥好了。想录一个视频,似乎这也没什么好录的,既然我能在网上学会,别人也能,那我录一个视频也没什么太大的用。干脆写一个学习笔记吧。packer 其实很简单,只是不会的时候觉得难。


  1. https://medium.com/@maros.kukan/automating-golden-image-builds-with-packer-3b1c6010b467 ↩︎

  2. Docker | Packer | HashiCorp Developer ↩︎

  3. https://developer.hashicorp.com/packer/guides/hcl ↩︎

  4. Input and Local Variables guide | Packer | HashiCorp Developer ↩︎

  5. HCL Templates | Packer | HashiCorp Developer ↩︎

posted @ 2025-03-01 18:17  wngtk  阅读(95)  评论(0)    收藏  举报