使用packer 打包qemu kvm系统镜像

首先是安装packer

在随便一个64位的机器上

$ curl -sLO https://releases.hashicorp.com/packer/1.4.3/packer_1.4.3_linux_amd64.zip
$ unzip packer_1.4.3_linux_amd64.zip
$ chmod +x packer
$ sudo mv packer /usr/local/bin/packer

注意:
因为有一个linux 包也叫packer ,所以安装前要确认一下

确认一下版本。以下多个命令都可以

$ packer -v
1.4.3
$ packer --version
1.4.3
$ packer -machine-readable version
1569220583,,version,1.4.3
1569220583,,version-prelease,
1569220583,,version-commit,613d8ef+CHANGES
1569220583,,ui,say,Packer v1.4.3

帮助的选项看以下

$ packer --help
Usage: packer [--version] [--help] <command> [<args>]

Available commands are:
    build       build image(s) from template
    console     creates a console for testing variable interpolation
    fix         fixes templates from old versions of packer
    inspect     see components of a template
    validate    check that a template is valid
    version     Prints the Packer version

几个细项的帮助
分别是 validate 验证模版

$ packer --help validate
Usage: packer validate [options] TEMPLATE

  Checks the template is valid by parsing the template and also
  checking the configuration with the various builders, provisioners, etc.

  If it is not valid, the errors will be shown and the command will exit
  with a non-zero exit status. If it is valid, it will exit with a zero
  exit status.

Options:

  -syntax-only           Only check syntax. Do not verify config of the template.
  -except=foo,bar,baz    Validate all builds other than these.
  -only=foo,bar,baz      Validate only these builds.
  -var 'key=value'       Variable for templates, can be used multiple times.
  -var-file=path         JSON file containing user variables.

验证模版创建的是否和预期一致
用法:

Usage: packer inspect TEMPLATE

Inspects a template, parsing and outputting the components a template
defines. This does not validate the contents of a template (other than
basic syntax by necessity).

Options:

-machine-readable Machine-readable output

build的帮助

$ packer --help build
Usage: packer build [options] TEMPLATE

  Will execute multiple builds in parallel as defined in the template.
  The various artifacts created by the template will be outputted.

Options:

  -color=false                  Disable color output. (Default: color)
  -debug                        Debug mode enabled for builds.
  -except=foo,bar,baz           Run all builds and post-procesors other than these.
  -only=foo,bar,baz             Build only the specified builds.
  -force                        Force a build to continue if artifacts exist, deletes existing artifacts.
  -machine-readable             Produce machine-readable output.
  -on-error=[cleanup|abort|ask] If the build fails do: clean up (default), abort, or ask.
  -parallel=false               Disable parallelization. (Default: true)
  -parallel-builds=1            Number of builds to run in parallel. 0 means no limit (Default: 0)
  -timestamp-ui                 Enable prefixing of each ui output with an RFC3339 timestamp.
  -var 'key=value'              Variable for templates, can be used multiple times.
  -var-file=path                JSON file containing user variables.

开启自动完成的功能

packer -autocomplete-install

packer的工作流程

Packer使用作为json文件的模板将配置携带到各种任务中。 核心任务是Build 。 在此阶段,Packer正在使用Builders为单个平台创建机器映像。 例如。 Qemu Builder创建一个kvm / xen虚拟机映像。 下一阶段是配置。 在此任务中, 预配器 (如ansible或shell脚本)在计算机映像内执行任务。 完成后, 后处理器将处理最终任务。 例如压缩虚拟映像或将其导入特定的应用程序。

模版

一个 json template file 包含:

builders (必需)
description (可选)
variables (可选)
min_packer_version (可选)
provisioners (可选)
post-processors (可选)

也可以把注释当做一个根键

{
  "_comment": "This is a comment",

  "builders": [
    {}
  ]
}

然后,我们需要配置一个跑qemu环境的机器
首先要安装qemu,因为centos自带的qemu太老,目前是1.5版本的,很多bug
所以我们要安装centos-release-qemu-ev 这个仓库

yum install -y centos-release-qemu-ev
yum install -y qemu-kvm-ev
/usr/libexec/qemu-kvm -version

模版

模版的例子
我们已qemu 为例,做一个简单的模版
以qemu_example.json为文件名,填充内容如下:

{
  "_comment": "This is a qemu builder example",

  "builders": [
    {
        "type": "qemu"
    }
  ]
}

然后我们从语法验证以下

[root@localhost ~]# packer validate -syntax-only  qemu.json
Syntax-only check passed. Everything looks okay.

然后我们用packer validate验证一下:

[root@localhost ~]# packer validate qemu_example.json
Template validation failed. Errors are shown below.

Errors validating build 'qemu'. 2 error(s) occurred:

* One of iso_url or iso_urls must be specified
* An ssh_username must be specified
  Note: some builders used to default ssh_username to "root".

语法是没有问题,但还是错误,通过packer validate这个命令的输出,可以看到有几个必须的值没有定义,
如果需要debug
可以将PACKER_LOG=1 注入到系统变量里:

export PACKER_LOG=1

然后我们可以再次验证一下

[root@localhost ~]# packer validate qemu_example.json
2019/09/23 04:19:18 [INFO] Packer version: 1.4.3
2019/09/23 04:19:18 Packer Target OS/Arch: linux amd64
2019/09/23 04:19:18 Built with Go Version: go1.12.8
2019/09/23 04:19:18 Detected home directory from env var: /root
2019/09/23 04:19:18 Using internal plugin for hyperv-vmcx
2019/09/23 04:19:18 Using internal plugin for lxc
2019/09/23 04:19:18 Using internal plugin for osc-chroot
2019/09/23 04:19:18 Using internal plugin for triton
2019/09/23 04:19:18 Using internal plugin for alicloud-ecs
2019/09/23 04:19:18 Using internal plugin for amazon-chroot
2019/09/23 04:19:18 Using internal plugin for amazon-instance
2019/09/23 04:19:18 Using internal plugin for hcloud
2019/09/23 04:19:18 Using internal plugin for parallels-pvm
2019/09/23 04:19:18 Using internal plugin for scaleway
2019/09/23 04:19:18 Using internal plugin for virtualbox-iso
2019/09/23 04:19:18 Using internal plugin for docker
2019/09/23 04:19:18 Using internal plugin for googlecompute
2019/09/23 04:19:18 Using internal plugin for oracle-classic
2019/09/23 04:19:18 Using internal plugin for osc-bsuvolume
2019/09/23 04:19:18 Using internal plugin for ncloud
2019/09/23 04:19:18 Using internal plugin for oneandone
2019/09/23 04:19:18 Using internal plugin for vmware-iso
2019/09/23 04:19:18 Using internal plugin for vmware-vmx
2019/09/23 04:19:18 Using internal plugin for hyperv-iso
2019/09/23 04:19:18 Using internal plugin for jdcloud
2019/09/23 04:19:18 Using internal plugin for oracle-oci
2019/09/23 04:19:18 Using internal plugin for ucloud-uhost
2019/09/23 04:19:18 Using internal plugin for amazon-ebsvolume
2019/09/23 04:19:18 Using internal plugin for azure-arm
2019/09/23 04:19:18 Using internal plugin for digitalocean
2019/09/23 04:19:18 Using internal plugin for file
2019/09/23 04:19:18 Using internal plugin for vagrant
2019/09/23 04:19:18 Using internal plugin for openstack
2019/09/23 04:19:18 Using internal plugin for osc-bsu
2019/09/23 04:19:18 Using internal plugin for profitbricks
2019/09/23 04:19:18 Using internal plugin for virtualbox-ovf
2019/09/23 04:19:18 Using internal plugin for hyperone
2019/09/23 04:19:18 Using internal plugin for proxmox
2019/09/23 04:19:18 Using internal plugin for null
2019/09/23 04:19:18 Using internal plugin for osc-bsusurrogate
2019/09/23 04:19:18 Using internal plugin for tencentcloud-cvm
2019/09/23 04:19:18 Using internal plugin for yandex
2019/09/23 04:19:18 Using internal plugin for amazon-ebs
2019/09/23 04:19:18 Using internal plugin for cloudstack
2019/09/23 04:19:18 Using internal plugin for linode
2019/09/23 04:19:18 Using internal plugin for lxd
2019/09/23 04:19:18 Using internal plugin for amazon-ebssurrogate
2019/09/23 04:19:18 Using internal plugin for parallels-iso
2019/09/23 04:19:18 Using internal plugin for qemu
2019/09/23 04:19:18 Using internal plugin for virtualbox-vm
2019/09/23 04:19:18 Using internal plugin for puppet-server
2019/09/23 04:19:18 Using internal plugin for shell-local
2019/09/23 04:19:18 Using internal plugin for windows-shell
2019/09/23 04:19:18 Using internal plugin for ansible-local
2019/09/23 04:19:18 Using internal plugin for inspec
2019/09/23 04:19:18 Using internal plugin for chef-client
2019/09/23 04:19:18 Using internal plugin for chef-solo
2019/09/23 04:19:18 Using internal plugin for puppet-masterless
2019/09/23 04:19:18 Using internal plugin for salt-masterless
2019/09/23 04:19:18 Using internal plugin for windows-restart
2019/09/23 04:19:18 Using internal plugin for ansible
2019/09/23 04:19:18 Using internal plugin for breakpoint
2019/09/23 04:19:18 Using internal plugin for powershell
2019/09/23 04:19:18 Using internal plugin for shell
2019/09/23 04:19:18 Using internal plugin for sleep
2019/09/23 04:19:18 Using internal plugin for converge
2019/09/23 04:19:18 Using internal plugin for file
2019/09/23 04:19:18 Using internal plugin for vagrant
2019/09/23 04:19:18 Using internal plugin for vsphere-template
2019/09/23 04:19:18 Using internal plugin for alicloud-import
2019/09/23 04:19:18 Using internal plugin for checksum
2019/09/23 04:19:18 Using internal plugin for digitalocean-import
2019/09/23 04:19:18 Using internal plugin for docker-import
2019/09/23 04:19:18 Using internal plugin for artifice
2019/09/23 04:19:18 Using internal plugin for compress
2019/09/23 04:19:18 Using internal plugin for docker-tag
2019/09/23 04:19:18 Using internal plugin for vsphere
2019/09/23 04:19:18 Using internal plugin for amazon-import
2019/09/23 04:19:18 Using internal plugin for googlecompute-export
2019/09/23 04:19:18 Using internal plugin for googlecompute-import
2019/09/23 04:19:18 Using internal plugin for vagrant-cloud
2019/09/23 04:19:18 Using internal plugin for shell-local
2019/09/23 04:19:18 Using internal plugin for docker-push
2019/09/23 04:19:18 Using internal plugin for docker-save
2019/09/23 04:19:18 Using internal plugin for exoscale-import
2019/09/23 04:19:18 Using internal plugin for manifest
2019/09/23 04:19:18 Detected home directory from env var: /root
2019/09/23 04:19:18 Attempting to open config file: /root/.packerconfig
2019/09/23 04:19:18 [WARN] Config file doesn't exist: /root/.packerconfig
2019/09/23 04:19:18 Packer config: &{DisableCheckpoint:false DisableCheckpointSignature:false PluginMinPort:10000 PluginMaxPort:25000 Builders:map[alicloud-ecs:/usr/local/bin/packer-PACKERSPACE-plugin-PACKERSPACE-packer-builder-alicloud-ecs amazon-chroot:/usr/local/bin/packer-PACKERSPACE-plugin-PACKERSPACE-packer-builder-amazon-chroot amazon-ebs:/usr/local/bin/packer-PACKERSPACE-plugin-PACKERSPACE-packer-builder-amazon-ebs amazon-ebssurrogate:/usr/local/bin/packer-PACKERSPACE-plugin-PACKERSPACE-packer-builder-amazon-ebssurrogate amazon-ebsvolume:/usr/local/bin/packer-PACKERSPACE-plugin-PACKERSPACE-packer-builder-amazon-ebsvolume amazon-instance:/usr/local/bin/packer-PACKERSPACE-plugin-PACKERSPACE-packer-builder-amazon-instance azure-arm:/usr/local/bin/packer-PACKERSPACE-plugin-PACKERSPACE-packer-builder-azure-arm cloudstack:/usr/local/bin/packer-PACKERSPACE-plugin-PACKERSPACE-packer-builder-cloudstack digitalocean:/usr/local/bin/packer-PACKERSPACE-plugin-PACKERSPACE-packer-builder-digitalocean docker:/usr/local/bin/packer-PACKERSPACE-plugin-PACKERSPACE-packer-builder-docker file:/usr/local/bin/packer-PACKERSPACE-plugin-PACKERSPACE-packer-builder-file googlecompute:/usr/local/bin/packer-PACKERSPACE-plugin-PACKERSPACE-packer-builder-googlecompute hcloud:/usr/local/bin/packer-PACKERSPACE-plugin-PACKERSPACE-packer-builder-hcloud hyperone:/usr/local/bin/packer-PACKERSPACE-plugin-PACKERSPACE-packer-builder-hyperone hyperv-iso:/usr/local/bin/packer-PACKERSPACE-plugin-PACKERSPACE-packer-builder-hyperv-iso hyperv-vmcx:/usr/local/bin/packer-PACKERSPACE-plugin-PACKERSPACE-packer-builder-hyperv-vmcx jdcloud:/usr/local/bin/packer-PACKERSPACE-plugin-PACKERSPACE-packer-builder-jdcloud linode:/usr/local/bin/packer-PACKERSPACE-plugin-PACKERSPACE-packer-builder-linode lxc:/usr/local/bin/packer-PACKERSPACE-plugin-PACKERSPACE-packer-builder-lxc lxd:/usr/local/bin/packer-PACKERSPACE-plugin-PACKERSPACE-packer-builder-lxd ncloud:/usr/local/bin/packer-PACKERSPACE-plugin-PACKERSPACE-packer-builder-ncloud null:/usr/local/bin/packer-PACKERSPACE-plugin-PACKERSPACE-packer-builder-null oneandone:/usr/local/bin/packer-PACKERSPACE-plugin-PACKERSPACE-packer-builder-oneandone openstack:/usr/local/bin/packer-PACKERSPACE-plugin-PACKERSPACE-packer-builder-openstack oracle-classic:/usr/local/bin/packer-PACKERSPACE-plugin-PACKERSPACE-packer-builder-oracle-classic oracle-oci:/usr/local/bin/packer-PACKERSPACE-plugin-PACKERSPACE-packer-builder-oracle-oci osc-bsu:/usr/local/bin/packer-PACKERSPACE-plugin-PACKERSPACE-packer-builder-osc-bsu osc-bsusurrogate:/usr/local/bin/packer-PACKERSPACE-plugin-PACKERSPACE-packer-builder-osc-bsusurrogate osc-bsuvolume:/usr/local/bin/packer-PACKERSPACE-plugin-PACKERSPACE-packer-builder-osc-bsuvolume osc-chroot:/usr/local/bin/packer-PACKERSPACE-plugin-PACKERSPACE-packer-builder-osc-chroot parallels-iso:/usr/local/bin/packer-PACKERSPACE-plugin-PACKERSPACE-packer-builder-parallels-iso parallels-pvm:/usr/local/bin/packer-PACKERSPACE-plugin-PACKERSPACE-packer-builder-parallels-pvm profitbricks:/usr/local/bin/packer-PACKERSPACE-plugin-PACKERSPACE-packer-builder-profitbricks proxmox:/usr/local/bin/packer-PACKERSPACE-plugin-PACKERSPACE-packer-builder-proxmox qemu:/usr/local/bin/packer-PACKERSPACE-plugin-PACKERSPACE-packer-builder-qemu scaleway:/usr/local/bin/packer-PACKERSPACE-plugin-PACKERSPACE-packer-builder-scaleway tencentcloud-cvm:/usr/local/bin/packer-PACKERSPACE-plugin-PACKERSPACE-packer-builder-tencentcloud-cvm triton:/usr/local/bin/packer-PACKERSPACE-plugin-PACKERSPACE-packer-builder-triton ucloud-uhost:/usr/local/bin/packer-PACKERSPACE-plugin-PACKERSPACE-packer-builder-ucloud-uhost vagrant:/usr/local/bin/packer-PACKERSPACE-plugin-PACKERSPACE-packer-builder-vagrant virtualbox-iso:/usr/local/bin/packer-PACKERSPACE-plugin-PACKERSPACE-packer-builder-virtualbox-iso virtualbox-ovf:/usr/local/bin/packer-PACKERSPACE-plugin-PACKERSPACE-packer-builder-virtualbox-ovf virtualbox-vm:/usr/local/bin/packer-PACKERSPACE-plugin-PACKERSPACE-packer-builder-virtualbox-vm vmware-iso:/usr/local/bin/packer-PACKERSPACE-plugin-PACKERSPACE-packer-builder-vmware-iso vmware-vmx:/usr/local/bin/packer-PACKERSPACE-plugin-PACKERSPACE-packer-builder-vmware-vmx yandex:/usr/local/bin/packer-PACKERSPACE-plugin-PACKERSPACE-packer-builder-yandex] PostProcessors:map[alicloud-import:/usr/local/bin/packer-PACKERSPACE-plugin-PACKERSPACE-packer-post-processor-alicloud-import amazon-import:/usr/local/bin/packer-PACKERSPACE-plugin-PACKERSPACE-packer-post-processor-amazon-import artifice:/usr/local/bin/packer-PACKERSPACE-plugin-PACKERSPACE-packer-post-processor-artifice checksum:/usr/local/bin/packer-PACKERSPACE-plugin-PACKERSPACE-packer-post-processor-checksum compress:/usr/local/bin/packer-PACKERSPACE-plugin-PACKERSPACE-packer-post-processor-compress digitalocean-import:/usr/local/bin/packer-PACKERSPACE-plugin-PACKERSPACE-packer-post-processor-digitalocean-import docker-import:/usr/local/bin/packer-PACKERSPACE-plugin-PACKERSPACE-packer-post-processor-docker-import docker-push:/usr/local/bin/packer-PACKERSPACE-plugin-PACKERSPACE-packer-post-processor-docker-push docker-save:/usr/local/bin/packer-PACKERSPACE-plugin-PACKERSPACE-packer-post-processor-docker-save docker-tag:/usr/local/bin/packer-PACKERSPACE-plugin-PACKERSPACE-packer-post-processor-docker-tag exoscale-import:/usr/local/bin/packer-PACKERSPACE-plugin-PACKERSPACE-packer-post-processor-exoscale-import googlecompute-export:/usr/local/bin/packer-PACKERSPACE-plugin-PACKERSPACE-packer-post-processor-googlecompute-export googlecompute-import:/usr/local/bin/packer-PACKERSPACE-plugin-PACKERSPACE-packer-post-processor-googlecompute-import manifest:/usr/local/bin/packer-PACKERSPACE-plugin-PACKERSPACE-packer-post-processor-manifest shell-local:/usr/local/bin/packer-PACKERSPACE-plugin-PACKERSPACE-packer-post-processor-shell-local vagrant:/usr/local/bin/packer-PACKERSPACE-plugin-PACKERSPACE-packer-post-processor-vagrant vagrant-cloud:/usr/local/bin/packer-PACKERSPACE-plugin-PACKERSPACE-packer-post-processor-vagrant-cloud vsphere:/usr/local/bin/packer-PACKERSPACE-plugin-PACKERSPACE-packer-post-processor-vsphere vsphere-template:/usr/local/bin/packer-PACKERSPACE-plugin-PACKERSPACE-packer-post-processor-vsphere-template] Provisioners:map[ansible:/usr/local/bin/packer-PACKERSPACE-plugin-PACKERSPACE-packer-provisioner-ansible ansible-local:/usr/local/bin/packer-PACKERSPACE-plugin-PACKERSPACE-packer-provisioner-ansible-local breakpoint:/usr/local/bin/packer-PACKERSPACE-plugin-PACKERSPACE-packer-provisioner-breakpoint chef-client:/usr/local/bin/packer-PACKERSPACE-plugin-PACKERSPACE-packer-provisioner-chef-client chef-solo:/usr/local/bin/packer-PACKERSPACE-plugin-PACKERSPACE-packer-provisioner-chef-solo converge:/usr/local/bin/packer-PACKERSPACE-plugin-PACKERSPACE-packer-provisioner-converge file:/usr/local/bin/packer-PACKERSPACE-plugin-PACKERSPACE-packer-provisioner-file inspec:/usr/local/bin/packer-PACKERSPACE-plugin-PACKERSPACE-packer-provisioner-inspec powershell:/usr/local/bin/packer-PACKERSPACE-plugin-PACKERSPACE-packer-provisioner-powershell puppet-masterless:/usr/local/bin/packer-PACKERSPACE-plugin-PACKERSPACE-packer-provisioner-puppet-masterless puppet-server:/usr/local/bin/packer-PACKERSPACE-plugin-PACKERSPACE-packer-provisioner-puppet-server salt-masterless:/usr/local/bin/packer-PACKERSPACE-plugin-PACKERSPACE-packer-provisioner-salt-masterless shell:/usr/local/bin/packer-PACKERSPACE-plugin-PACKERSPACE-packer-provisioner-shell shell-local:/usr/local/bin/packer-PACKERSPACE-plugin-PACKERSPACE-packer-provisioner-shell-local sleep:/usr/local/bin/packer-PACKERSPACE-plugin-PACKERSPACE-packer-provisioner-sleep windows-restart:/usr/local/bin/packer-PACKERSPACE-plugin-PACKERSPACE-packer-provisioner-windows-restart windows-shell:/usr/local/bin/packer-PACKERSPACE-plugin-PACKERSPACE-packer-provisioner-windows-shell]}
2019/09/23 04:19:18 Detected home directory from env var: /root
2019/09/23 04:19:18 Setting cache directory: /root/packer_cache
2019/09/23 04:19:18 Detected home directory from env var: /root
2019/09/23 04:19:18 Loading builder: qemu
2019/09/23 04:19:18 Plugin could not be found. Checking same directory as executable.
2019/09/23 04:19:18 Current exe path: /usr/local/bin/packer
2019/09/23 04:19:18 Creating plugin client for path: /usr/local/bin/packer
2019/09/23 04:19:18 Starting plugin: /usr/local/bin/packer []string{"/usr/local/bin/packer", "plugin", "packer-builder-qemu"}
2019/09/23 04:19:18 Waiting for RPC address for: /usr/local/bin/packer
2019/09/23 04:19:18 packer: 2019/09/23 04:19:18 [INFO] Packer version: 1.4.3
2019/09/23 04:19:18 packer: 2019/09/23 04:19:18 Packer Target OS/Arch: linux amd64
2019/09/23 04:19:18 packer: 2019/09/23 04:19:18 Built with Go Version: go1.12.8
2019/09/23 04:19:18 packer: 2019/09/23 04:19:18 Detected home directory from env var: /root
2019/09/23 04:19:18 packer: 2019/09/23 04:19:18 Attempting to open config file: /root/.packerconfig
2019/09/23 04:19:18 packer: 2019/09/23 04:19:18 [WARN] Config file doesn't exist: /root/.packerconfig
2019/09/23 04:19:18 packer: 2019/09/23 04:19:18 Packer config: &{DisableCheckpoint:false DisableCheckpointSignature:false PluginMinPort:10000 PluginMaxPort:25000 Builders:map[] PostProcessors:map[] Provisioners:map[]}
2019/09/23 04:19:18 packer: 2019/09/23 04:19:18 Detected home directory from env var: /root
2019/09/23 04:19:18 packer: 2019/09/23 04:19:18 Setting cache directory: /root/packer_cache
2019/09/23 04:19:18 packer: 2019/09/23 04:19:18 args: []string{"packer-builder-qemu"}
2019/09/23 04:19:18 packer: 2019/09/23 04:19:18 Detected home directory from env var: /root
2019/09/23 04:19:18 packer: 2019/09/23 04:19:18 Plugin minimum port: 10000
2019/09/23 04:19:18 packer: 2019/09/23 04:19:18 Plugin maximum port: 25000
2019/09/23 04:19:18 packer: 2019/09/23 04:19:18 Plugin address: unix /tmp/packer-plugin131147162
2019/09/23 04:19:18 packer: 2019/09/23 04:19:18 Waiting for connection...
2019/09/23 04:19:18 packer: 2019/09/23 04:19:18 Serving a plugin connection...
2019/09/23 04:19:18 Preparing build: qemu
2019/09/23 04:19:18 packer: 2019/09/23 04:19:18 use detected accelerator: tcg
2019/09/23 04:19:18 packer: 2019/09/23 04:19:18 MemorySize 0 is too small, using default: 512
2019/09/23 04:19:18 packer: 2019/09/23 04:19:18 CpuCount 0 too small, using default: 1
2019/09/23 04:19:18 Build 'qemu' prepare failure: 2 error(s) occurred:

* One of iso_url or iso_urls must be specified
* An ssh_username must be specified
  Note: some builders used to default ssh_username to "root".

* One of iso_url or iso_urls must be specified
* An ssh_username must be specified
  Note: some builders used to default ssh_username to "root".
2019/09/23 04:19:18 [INFO] (telemetry) Finalizing.
Template validation failed. Errors are shown below.

Errors validating build 'qemu'. 2 error(s) occurred:

* One of iso_url or iso_urls must be specified
* An ssh_username must be specified
  Note: some builders used to default ssh_username to "root".
2019/09/23 04:19:20 [WARN] (telemetry) Error finalizing report. This is safe to ignore. Post https://checkpoint-api.hashicorp.com/v1/telemetry/packer: context deadline exceeded
2019/09/23 04:19:20 waiting for all plugin processes to complete...
2019/09/23 04:19:20 /usr/local/bin/packer: plugin process exited

我们可以看到好多内置的插件,这里先略过。。

变量

在 packer template 定义变量非常简单

  "variables": {
    "centos_version":  "7.5",
  }    

然后用下面的方式使用刚刚定义的变量:

"{{user `centos_version`}}",

注释

我们可以在模板顶部添加描述声明:
"description": "Minimal CentOS 7 Qemu Imagen_____
然后可以用
packer inspect 来验证

QEMU BUILDER

然后我们用一段完整简单的packer 的json代码来做build的例子

$ cat qemu_example.json
{

  "_comment": "This is a CentOS 7.5 Qemu Builder example",

  "description": "Minimal CentOS 7 Qemu Imagen__________________________________________",

  "variables": {
    "7.5":      "1908",
    "checksum": "9a2c47d97b9975452f7d582264e9fc16d108ed8252ac6816239a3b58cef5c53d"
  },

  "builders": [
    {
        "type": "qemu",

        "iso_url": "https://mirrors.163.com/centos/7/isos/x86_64/CentOS-7-x86_64-Minimal-{{user `7.5`}}.iso",
        "iso_checksum": "{{user `checksum`}}",
        "iso_checksum_type": "sha256",

        "communicator": "none"
    }
  ]

}

然后验证一下

[root@localhost ~]# packer validate -syntax-only qemu_example.json
Syntax-only check passed. Everything looks okay.
[root@localhost ~]# packer validate qemu_example.json
Template validated successfully.

Communicator

有三个基本的选项:

none
Secure Shell (SSH)
WinRM

这个是在构建部分( provisioning ) 配置的需要配置的
通讯在构建部分上传文件或者执行脚本,如果不需要特别构建镜像时,可以使用none,而不是默认的ssh
来禁用这个选项

"communicator": "none"

iso_url
可以使用本地或者intelnet的地址,这个才调试的时候非常有用,可以避免经常从网上下载文件提高修复。

"iso_url": "/home/ebal/Downloads/CentOS-7-x86_64-Minimal-{{user `7.5`}}.iso"

如果在centos下面,使用packer 对qemu 进行打包时候,需要装qemu-system-x86这个包,否则会报错

[root@localhost ~]# packer build qemu_example.json
qemu output will be in this color.

Build 'qemu' errored: Failed creating Qemu driver: exec: "qemu-system-x86_64": executable file not found in $PATH

==> Some builds didn't complete successfully and had errors:
--> qemu: Failed creating Qemu driver: exec: "qemu-system-x86_64": executable file not found in $PATH

==> Builds finished but no artifacts were created.

然而这个包在epel库里,因此还需要安装epel的仓库。

继续,不出意外,应该还会出现另外一个错误

2019/09/24 00:40:45 packer: 2019/09/24 00:40:45 Qemu stderr:
2019/09/24 00:40:45 packer: 2019/09/24 00:40:45 Qemu stderr: (process:20773): GLib-WARNING **: 00:40:45.452: gmem.c:489: custom memory allocation vtable not supported
2019/09/24 00:40:45 packer: 2019/09/24 00:40:45 Qemu stderr: Could not initialize SDL(No available video device) - exiting
==> qemu: Error launching VM: Qemu failed to start. Please run with PACKER_LOG=1 to get more info.
2019/09/24 00:40:45 packer: 2019/09/24 00:40:45 failed to unlock port lockfile: close tcp 127.0.0.1:5957: use of closed network connection
==> qemu: Deleting output directory...
2019/09/24 00:40:45 [INFO] (telemetry) ending qemu
2019/09/24 00:40:45 machine readable: error-count []string{"1"}
==> Some builds didn't complete successfully and had errors:
Build 'qemu' errored: Build was halted.

这个手册里有写
请注意,如果要在没有X11的Linux服务器上运行Packer,则需要设置"headless": true ; 或者,如果您通过ssh连接到远程Linux服务器并且尚未启用X11转发( ssh -X )。

我们可以修改我们的配置文件来解决问题,但是实际上,我们需要打开一个虚拟机窗口,看看究竟发生了什么,因此我们选择安装一个图形环境
然后我们安装一个图形环境

yum -y groupinstall "Server with GUI

然后继续就可以了
我们当然想剩下的部分可以自动完成,
因此在linux部分,我们要引入linux的Kickstart来完成剩下的工作。

#version=CentOS-7

# Install OS instead of upgrade
install

# Text or Graphical mode ?
text

# Packages are on:
cdrom

# System keyboard
keyboard us

# System language
lang en_US.UTF-8

# TimeZone with NTP
timezone Asia/Shanghai --ntpservers=gr.pool.ntp.org

# SELinux - By default, selinux is enforcing
selinux --permissive

# Sets the system's root password to the password argument.
rootpw --plaintext password

# accept the End User License Agreement - rhel 7
## eula--agreed

# Do not Run the Setup Agent on first boot
firstboot --disabled

# Power Off the system when the install is complete
poweroff

# Partition Table
autopart --nohome --type=plain --fstype=ext4

bootloader --location=mbr

# Partition clearing information
clearpart --all --initlabel 
zerombr

%packages --excludedocs
@core
# Remove
-aic94xx-firmware
-alsa-*
-iwl*-firmware
-ivtv-firmware
-libertas-*-firmware
-btrfs-progs
-ModemManager-glib
-NetworkManager*
-wpa_supplicant
# Install
openssh-clients
%end

# Disable Kdump
%addon com_redhat_kdump --disable

%end

这是非常简单的一个kickstart文件,让我们把他保存为centos7.ks
然后我们修改我们的qemu_example.json文件
加入kickstart文件
添加字段

 "boot_command":[
    "<tab> text ",
    "ks=https://raw.githubusercontent.com/ebal/confs/master/Kickstart/CentOS7-ks.cfg ",
     "nameserver=9.9.9.9 ",
     "<enter><wait> "
],
  "boot_wait": "0s"

记得要在前面的选项结尾后加逗号 ,
修改后变成这样:

{

  "_comment": "This is a CentOS 7.5 Qemu Builder example",

  "description": "\tMinimal CentOS 7 Qemu Imagen\n__________________________________________",

  "variables": {
    "7.5":      "1908",
    "checksum": "9a2c47d97b9975452f7d582264e9fc16d108ed8252ac6816239a3b58cef5c53d"
  },

  "builders": [
    {
        "type": "qemu",

        "iso_url": "/root/CentOS-7-x86_64-Minimal-{{user `7.5`}}.iso",
        "iso_checksum": "{{user `checksum`}}",
        "iso_checksum_type": "sha256",
        "communicator": "none",
        "boot_command" :   [
        "<tab> text ",
          "console=ttyS0,115200n8 ",
          "ks=https://192.168.4.190/CentOS7-ks.cfg ",
          "nameserver=8.8.8.8",
          "<enter><wait> "
      ],
          "boot_wait": "0s",
          "shutdown_timeout": "30m"
    }
  ]
}

看到多了一行 "shutdown_timeout": "30m" 这个是解决安装过程中,如果超过5分钟,packer会报

Build 'qemu' errored: Failed to shutdown

原因是默认等待时间只有5分钟,所以我们要加长一点

http_directory
在没有Internet访问的环境中构建映像时,可以从Packer可以创建的内部HTTP服务器检索kickstast文件。 通过声明目录路径来启用此功能: http_directory

使用HTTP服务器提供服务的目录的路径。 该目录中的文件将通过HTTP可用,可从虚拟机请求该文件
上面的代码就要修改成这样

"http_directory": "/root/Downloads/",
  "http_port_min": "8090",
  "http_port_max": "8100",

"boot_command":[
    "<tab> text ",
    "ks=http://{{ .HTTPIP }}:{{ .HTTPPort }}/CentOS7.ks",
    "<enter><wait>"
],
    "boot_wait": "0s"

事先要把centos7.ks 放到/root/Downloads/
最后,我们得到了如下的json文件

{

  "_comment": "This is a CentOS 7.5 Qemu Builder example",

  "description": "tMinimal CentOS 7 Qemu Imagen__________________________________________",

  "variables": {
    "7.7":      "1908",
    "checksum": "9a2c47d97b9975452f7d582264e9fc16d108ed8252ac6816239a3b58cef5c53d"
  },

  "builders": [
    {
        "type": "qemu",

        "iso_url": "/root/CentOS-7-x86_64-Minimal-{{user `7.7`}}.iso",
        "iso_checksum": "{{user `checksum`}}",
        "iso_checksum_type": "sha256",

        "communicator": "none",

        "boot_command":[
          "<tab> text ",
          "ks=http://{{ .HTTPIP }}:{{ .HTTPPort }}/centos7.ks ",
          "nameserver=8.8.8.8 ",
          "<enter><wait> "
        ],
        "boot_wait": "0s",

        "http_directory": "/root/",
        "http_port_min": "8090",
        "http_port_max": "8100",

        "shutdown_timeout": "40m"

    }
  ]

}

然后我们重新build 一次镜像

packer build qemu_example.json

然后我们验证一下镜像

[root@localhost ~]# ls output-qemu/
packer-qemu
[root@localhost ~]# file output-qemu/packer-qemu
output-qemu/packer-qemu: QEMU QCOW Image (v3), 42949672960 bytes

因为默认的qemu-img 起的虚拟机,内存只给512m,cpu只给一个内核,跑起来非常慢,另外在纯qemu环境下,打包也是跑的非常慢,还有就是我们一般只有debug的时候需要起桌面,看看虚拟机到底跑的怎么样,其他的时候,我们不需要起桌面,这些都需要对配置进行一些优化。
然后就是下面的这样了

{

  "_comment": "This is a CentOS 7.5 Qemu Builder example",

  "description": "\tMinimal CentOS 7 Qemu Imageni\n__________________________________________",

  "variables": {
    "7.7":      "1908",
    "checksum": "9a2c47d97b9975452f7d582264e9fc16d108ed8252ac6816239a3b58cef5c53d",
    "virtual_name": "centos7min.qcow2",
    "virtual_dir":  "centos7",
    "virtual_size": "20480",
    "virtual_mem":  "4096",

    "Password": "password"
  },

  "builders": [
    {
        "type": "qemu",
        "headless": true,
        "iso_url": "/root/CentOS-7-x86_64-Minimal-{{user `7.7`}}.iso",
        "iso_checksum": "{{user `checksum`}}",
        "iso_checksum_type": "sha256",

        "communicator": "none",

        "ssh_username": "root",
        "ssh_password": "{{user `Password`}}",
        "ssh_timeout":  "3600s",

        "boot_command":[
          "<tab> text ",
          "console=ttyS0,115200n8 ",
          "ks=http://{{ .HTTPIP }}:{{ .HTTPPort }}/centos7.ks ",
          "nameserver=8.8.8.8 ",
          "<enter><wait> "
        ],
        "boot_wait": "0s",

        "http_directory": "/root/",
        "http_port_min": "8090",
        "http_port_max": "8100",

        "shutdown_timeout": "120m",

        "accelerator": "kvm",
    "format":      "qcow2",
    "qemuargs":[
           [ "-m", "2048" ],
           ["-smp", "2,sockets=2,cores=1,threads=1" ],
           [ "-serial", "file:serial.out" ]
    ]


    }
  ]

}
#Headless
打包程序无需使用显示器。 在远程计算机上运行打包程序时,这真的很有用。 尽管可以通过vnc连接并监视过程,但无需任何交互即可自动执行自动安装。
禁用x终端链接

"headless": true

另外如果要监看packer打包过程的话,需要下面的步骤

在boot_command 的选项里添加了

         "console=ttyS0,115200n8 ",

然后在

"qemuargs":[
[ "-serial", "file:serial.out" ]

这样我们等于在内核启动参数里,添加了通过serial口显示屏幕的一个后门,然后又被packer 重定向到当前目录下的serial.out 文件里,于是我们可以通过下面的命令来查看打包过程

tail -f serial.out

然后添加qmeu 优化的选项
首先添加变量

   "virtual_name": "centos7min.qcow2",
   "virtual_dir":  "centos7",
   "virtual_size": "20480",
   "virtual_mem":  "4096"

然后在下面的build 里面调用

  "accelerator": "kvm",
  "disk_size":   "{{ user `virtual_size` }}",
  "format":      "qcow2",
  "qemuargs":[
    [  "-m",  "{{ user `virtual_mem` }}" ]
  ],

  "vm_name":          "{{ user `virtual_name` }}",
  "output_directory": "{{ user `virtual_dir` }}"

也可以按

["-smp", "2,sockets=2,cores=1,threads=1" ],
           [ "-serial", "file:serial.out" ]

这样写。

特别说明"accelerator": "kvm",的 选项,如果是在kvm的主机里,并且没有开启嵌套虚拟化,加这个选项是会报错的,如果不加的话,就是纯qemu软件虚拟机,我打包一个简单的centos7的镜像花了将近1个小时,而我在真实物理机打包的时候只有5分钟左右,因此强烈不推荐在虚拟机上跑packer的打包程序。
最后的提示是这样的

time packer build qemu_example.json
qemu output will be in this color.

==> qemu: Retrieving ISO
==> qemu: Trying /root/CentOS-7-x86_64-Minimal-1908.iso
==> qemu: Trying /root/CentOS-7-x86_64-Minimal-1908.iso?checksum=sha256%3A9a2c47d97b9975452f7d582264e9fc16d108ed8252ac6816239a3b58cef5c53d
==> qemu: /root/CentOS-7-x86_64-Minimal-1908.iso?checksum=sha256%3A9a2c47d97b9975452f7d582264e9fc16d108ed8252ac6816239a3b58cef5c53d => /root/packer_cache/4643e65b1345d2b22536e5d371596b98120f4251.iso
==> qemu: Creating required virtual machine disks
==> qemu: Starting HTTP server on port 8092
==> qemu: Looking for available port between 5900 and 6000 on 127.0.0.1
==> qemu: Starting VM, booting from CD-ROM
    qemu: The VM will be run headless, without a GUI. If you want to
    qemu: view the screen of the VM, connect via VNC without a password to
    qemu: vnc://127.0.0.1:5961
==> qemu: Overriding defaults Qemu arguments with QemuArgs...
==> qemu: Connecting to VM via VNC (127.0.0.1:5961)
==> qemu: Typing the boot command over VNC...
==> qemu: Waiting for shutdown...
==> qemu: Converting hard drive...
Build 'qemu' finished.

==> Builds finished. The artifacts of successful builds are:
--> qemu: VM files in directory: centos7

real    5m4.663s
user    5m36.605s
sys     0m36.641s

后置处理

打包好的镜像就可以推送到云或者是压缩
我们这里简单写一个压缩的处理程序

"post-processors":[
      {
          "type":   "compress",
          "format": "lz4",
          "output": "{{.BuildName}}.lz4"
      }
  ]

PROVISIONERS

packer的文档是这样描述的
Provisioners use builtin and third-party software to install and configure the machine image after booting. Provisioners prepare the system for use, so common use cases for provisioners include:

installing packages
patching the kernel
creating users
downloading application code
These are just a few examples, and the possibilities for provisioners are endless.

打开文档,我们可以看到基本常见的iac工具都有了
ansible chef puppet inspec 等,,涵盖了从部署到测试验证的所有环节,
这里我们简单使用 PROVISIONERS 的ansible 插件
我们首先创建一个ansible role,名字叫test

ansible-galaxy init test
- test was created successfully

然后在tasks/main.yml 里面加入如下内容

---
  - name: Debug that our ansible role is working
    debug:
      msg: "It Works !"

  - name: Install the Extra Packages for Enterprise Linux repository
    yum:
      name: epel-release
      state: present

  - name: upgrade all packages
    yum:
      name: *
      state: latest

然后在packer的模版里面添加
变量部分修改

    "variables":{
        "playbook_name": "test.yml"
    },

下面是新添加的一个新角色


    "provisioners":[
        {
            "type":          "ansible",
            "playbook_file": "{{ user `playbook_name` }}"
        }
    ],

因为ansible 其实是本地ansible连接我们打包过程中起的虚拟机,我们还需要在打包过程中打开ssh端口,让ansible和打包过程中的虚拟机通讯

 "communicator": "ssh",

同时要添加用户和密码到模版里去

  "ssh_username": "root",
   "ssh_password": "password",
   "ssh_timeout":  "3600s",

后来我发现我这个如果用"communicator": "none", 可以跑,
不过ansible 是跑在packer这个打包机上的,
ssh一直连不上

如果用ansible_local,结果packer 直接报错退出了
然后看了一下文档,在packer的模块中,ansible 和 ansible_local 是两个完全不同的实现方式
ansible 模块是 由打包机的上执行ansible通过ssh连接到虚拟机上,执行playbook文件
ansible_local 模块是将打包机上的ansible 文件,同步到虚拟机上,然后在虚拟机上执行ansible文件
因此需要事先在虚拟机上安装ansible,才可以使用ansible_local的模块,或者在使用这个模块前,通过shell模块安装ansible ,就可以了

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容