当前位置: 首页 > 虚拟化 > 使用Packer构建虚拟机模版-Ubuntu18.04/19.10/20.04

使用Packer构建虚拟机模版-Ubuntu18.04/19.10/20.04

虚拟化 0条评论 2020-7-21 968 views

概述

前面我们制作了Windows Server 2016/2019和CentOS7的模版,还差一个主流的Linux发行版-Ubuntu,今天有时间把18.04、19.10和20.04三个版本的模版制作完成,并且升级到最新的Packer 1.6.0版本和vSphere7.0版本,希望对大家有帮助。

本示例对Ubuntu模版进行了如下的特性定制:

  1. 使用VMware准虚拟SCSI控制器(SCSI);
  2. 添加中文支持;
  3. 配置中国时区;
  4. 更改为Ubuntu中国源;
  5. 启用Root账户和Root账户SSH登录;
  6. 创建Ops运维账户;
  7. 基于LVM进行分区,并采用xfs分区格式;
  8. 安装常用工具和VMware Tools;
  9. 更改ens192为eth0;
  10. 清理Machine-id;

提示,由于Packer示例中,模版名是以日期作为后缀的,所以每天只会产生一个模版,同时如果做计划任务,每天都会有一个模版,要注意清理,避免过度占用磁盘空间。

相关工具:

Packer是一个开源的自动化虚拟机模版构建工具,支持私有云和公有云,几乎涵盖所有的环境。 vSphere是VMware企业级虚拟化软件,被企业客户广泛使用,具备稳定性高、性能好、安全性高和易使用的特点。

Ubuntu18.04相关代码中包含Packer所需的json文件和Ubuntu18.04的preseed.cfg文件 Ubuntu19.10相关代码中包含Packer所需的json文件和Ubuntu19.10的preseed.cfg文件 Ubuntu20.04相关代码中包含Packer所需的json文件和Ubuntu20.04的preseed.cfg文件

preseed语法参考中详细说明了preseed的语法

VMware虚拟机硬件版本中详细列出了vSphere对虚拟机硬件版本的支持

使用时请根据实际环境进行修改,我采用最新的vSpehre7.0版本。


环境需求:

  1. 一台Windows/Linux/MacOS电脑,能够连接vCenter Server;
  2. Packer程序:https://packer.io/downloads.html
  3. Ubuntu 18.04 ISO:http://cdimage.ubuntu.com/releases/18.04/release/
  4. Ubuntu 19.10 ISO:http://cdimage.ubuntu.com/releases/19.10/release/
  5. Ubuntu 20.04 ISO:http://cdimage.ubuntu.com/ubuntu-legacy-server/releases/20.04/release/

Packer安装

Packer采用GO语言编写,安装非常简单,只需要将解压后的packer文件拷贝到系统bin目录下即可,下面是在Linux下的安装方式:

wget https://releases.hashicorp.com/packer/1.6.0/packer_1.6.0_linux_amd64.zip
unzip packer_1.6.0_linux_amd64.zip
cp packer /usr/loca/bin
chmod +x /usr/local/bin
packer version

Ubuntu的Packer模版

我们需要两个基础文件,用于使用Packer在vSphere环境中构建Ubuntu模版:

  1. ubuntu-vsphere.json文件(Packer模版);
  2. preseed.cfg文件(Ubuntu无人值守安装文件);

推荐下载仓库的文件,避免拷贝粘贴可能造成的字符问题;packer-vsphere

ubuntu-vsphere.json文件说明

variables段落,用于定义vCenter的相关信息和虚拟机配置,其会在Builders段落引用,注意虚拟机文件夹需要预先创建好。

  1. vm-name:定义虚拟机模版基础名称,在build阶段会自己增加日期后缀,以方便却别版本;
  2. vm-version:定义虚拟机使用什么硬件版本,当前vSphere6.7U3使用15,其他版本请查询相关工具中心的VMware虚拟机硬件版本
  3. vm-folder:定义虚拟机模版保存在哪个文件夹中;
  4. vm-cpu-num:定义虚拟机模版配置的CPU数量,通过模版再进行部署时可以修改;
  5. vm-mem-size:定义虚拟机模版配置的内存容量(MB单位),通过模版进行部署时可以修改;
  6. vm-disk-size:定义虚拟机磁盘容量(MB单位),后续的preseed会基于此容量进行分区,/boot、swap、/var/log、/分区是固定的配置(通过修改preseed.cfg更改),/app-date用于存放应用,会使用所有剩余空间;
  7. iso_url:指定系统安装光盘位置,本示例使用vSphere环境构建,所以指定共享存储的路径;
  8. vm-video-ram:指定虚拟机显存大小(只有这个选项是KB单位,其他都是MB单位)

提示1:为保证ISO文件有效,可以通过参数(iso_checksum、iso_checksum_type和iso_checksum_url)验证ISO是否完成; 提示2:变量部分可以独立为var.json文件,在build时单独指定;

  "variables": {
    "iso_url": "[SSD_DATASTORE] 0-ISO/ubuntu-18.04.4-server-amd64.iso",
    "vm-cpu-num": "2",
    "vm-disk-size": "81920",
    "vm-folder": "Templates",
    "vm-mem-size": "4096",
    "vm-name": "Ubuntu1804-T",
    "vm-version": "17",
    "vm-video-ram": "16384",
    "vsphere-cluster": "DC02-Cluster",
    "vsphere-datacenter": "Labs-DC02",
    "vsphere-datastore": "SSD_DATASTORE",
    "vsphere-network": "vlan100",
    "vsphere-password": "VMware1!",
    "vsphere-server": "vcenter.corp.local",
    "vsphere-user": "administrator@vsphere.local"
  }

builders段落,用于真正的构建配置,本示例中将经常需要改变的部分通过variables定义,并在此阶段引用。

  1. vm_name:我们采用variables中的名字和日期进行组合,isotime会获取当前日期;
  2. notes:显示在虚拟机的备注属性中,用于查看模版具体的构建时间;
  3. guest_os_type:定义虚拟机客户机操作系统,可以通VMware官方文档或者创建虚拟机后查询.vmx文件获得正确的客户机操作系统代码;
  4. ssh_username:定义provisioners阶段连接模版虚拟机的口令,此口令来自ks.cfg中的配置;
  5. disk_controller_type:定义虚拟机的SCSI控制器类型,这里采用更高性能的VMware准虚拟;
  6. disk_thin_provisioned:定义虚拟机是否使用精简磁盘;
  7. network_card:网卡类型,这里选择了性能最好的vmxnet3;
  8. video_ram:显卡显存;
  9. convert_to_template:定义是否自动转换成模版,请根据需要选择,如果虚拟机部署编排工具不支持从模版克隆,就需要配置为false;
  10. floppy_files:定义Ubuntu无人值守安装的preseed文件;
  "builders": [
    {
      "CPUs": "{{user `vm-cpu-num`}}",
      "RAM": "{{user `vm-mem-size`}}",
      "RAM_reserve_all": false,
      "boot_command": [
        "<enter><wait><f6><wait><esc><wait>",
        "<bs><bs><bs><bs><bs><bs><bs><bs><bs><bs>",
        "<bs><bs><bs><bs><bs><bs><bs><bs><bs><bs>",
        "<bs><bs><bs><bs><bs><bs><bs><bs><bs><bs>",
        "<bs><bs><bs><bs><bs><bs><bs><bs><bs><bs>",
        "<bs><bs><bs><bs><bs><bs><bs><bs><bs><bs>",
        "<bs><bs><bs><bs><bs><bs><bs><bs><bs><bs>",
        "<bs><bs><bs><bs><bs><bs><bs><bs><bs><bs>",
        "<bs><bs><bs><bs><bs><bs><bs><bs><bs><bs>",
        "<bs><bs><bs>",
        "/install/vmlinuz",
        " initrd=/install/initrd.gz",
        " priority=critical",
        " locale=en_US",
        " interface=eth0",
        " file=/media/preseed.cfg",
        "<enter>"
      ],
      "cluster": "{{user `vsphere-cluster`}}",
      "convert_to_template": "true",
      "datacenter": "{{user `vsphere-datacenter`}}",
      "datastore": "{{user `vsphere-datastore`}}",
      "disk_controller_type": "pvscsi",
      "floppy_files": ["./preseed.cfg"],
      "folder": "{{user `vm-folder`}}",
      "guest_os_type": "ubuntu64Guest",
      "insecure_connection": "true",
      "iso_paths": [
        "{{user `iso_url`}}"
      ],
      "network_adapters": [
        {
          "network": "{{user `vsphere-network`}}",
          "network_card": "vmxnet3"
        }
      ],
      "video_ram": "{{user `vm-video-ram`}}",
      "password": "{{user `vsphere-password`}}",
      "ssh_password": "VMware1!",
      "ssh_username": "root",
      "storage": [
        {
          "disk_size": "{{user `vm-disk-size`}}",
          "disk_thin_provisioned": true
        }
      ],
      "type": "vsphere-iso",
      "username": "{{user `vsphere-user`}}",
      "vcenter_server": "{{user `vsphere-server`}}",
      "vm_name": "{{user `vm-name`}}"
    }
  ],

provissioners段落,用于系统自动化安全完成后的自定义操作,例如:更新系统补丁,清理模版等,本示例中进行了模版清理和主机名配置。

  "provisioners": [
    {
      "type": "shell",
      "inline": [
        "truncate -s 0 /etc/machine-id",
        "rm /var/lib/dbus/machine-id",
        "ln -s /etc/machine-id /var/lib/dbus/machine-id",
        "rm -rf /tmp/* /var/tmp/*",
        "hostnamectl set-hostname {{user `vm-name`}}"
      ]
    }
  ],

preseed.cfg文件说明

preseed文件的介绍很多,这里不进行详细介绍,可以参考官方文档说明,下面仅针对我定制化的内容进行说明;

  1. 第16行,添加中文支持;
  2. 第30行和144行,该更更新源;
  3. 第35-38行,设定root账户密码;
  4. 第40-50行,添加新用户;
  5. 第55行,设定亚洲/上海时区;
  6. 第57行,设定NTP服务器;
  7. 第61-131行,配置LVM,并基于LVM创建分区;
  8. 第149行,添加中文支持;
  9. 第154-164行,添加软件包;
  10. 第168行,允许Root登录;
  11. 第169-173行,更改ens192为eth0,禁用IPV6;

本示例中的密码均为VMware1!,请注意自行修改。

### Preseed for Ubuntu 18.04
### Author:Guoqiang Li
# Derived from: https://help.ubuntu.com/lts/installation-guide/example-preseed.txt

### Usage
# We recommend to use the build-iso.sh script to build an image with embedded
# preseed and other required files. In that case the preseed file gets loaded
# automatically and all additional files are available to the installer.

### Unattended Installation
d-i auto-install/enable boolean true
d-i debconf/priority select critical

### Localization
d-i debian-installer/locale string en_US.UTF-8
d-i localechooser/supported-locales multiselect en_US.iso88591, en_US.UTF-8, zh_CN.gb18030, zh_CN.utf8
d-i console-setup/ask_detect boolean false
d-i keyboard-configuration/xkb-keymap select GB

### Network configuration
d-i /choose_interface select auto
# d-i netcfg/hostname string device
d-i netcfg/get_hostname string unassigned-hostname
d-i netcfg/get_domain string unassigned-domain
d-i hw-detect/load_firmware boolean true

### Mirror settings
d-i mirror/country string manual
d-i mirror/http/hostname string cn.archive.ubuntu.com
d-i mirror/http/directory string /ubuntu
d-i mirror/http/proxy string

### Account setup
d-i passwd/root-login boolean true
d-i passwd/root-password password VMware1!
d-i passwd/root-password-again password VMware1!
d-i passwd/make-user boolean false

# The root password is disabled by default.

# Create ops user account.
d-i passwd/user-fullname string ops
d-i passwd/username string ops
d-i passwd/user-password password VMware1!
d-i passwd/user-password-again password VMware1!
d-i user-setup/allow-password-weak boolean true
d-i user-setup/encrypt-home boolean false
d-i passwd/user-default-groups ops sudo
d-i passwd/user-uid string 90

### Clock and time zone setup
d-i clock-setup/utc boolean true
d-i time/zone string Asia/Shanghai
d-i clock-setup/ntp boolean true
d-i clock-setup/ntp-server ntp.ubuntu.com

### Partitioning
d-i preseed/early_command string umount /media || true
d-i partman-auto/method string lvm
d-i partman-auto-lvm/guided_size string max
d-i partman-lvm/device_remove_lvm boolean true
d-i partman-lvm/confirm boolean true
d-i partman-lvm/confirm_nooverwrite boolean true
d-i partman-auto-lvm/new_vg_name string main
d-i partman-md/device_remove_md boolean true
d-i partman-md/confirm boolean true
d-i partman-partitioning/confirm_write_new_label boolean true
d-i partman/choose_partition select finish
d-i partman/confirm boolean true
d-i partman/confirm_nooverwrite boolean true
d-i partman-basicmethods/method_only boolean false

### Partitioning
d-i partman-auto/method string lvm
d-i partman-lvm/device_remove_lvm boolean true
d-i partman-lvm/confirm boolean true
d-i partman-lvm/confirm_nooverwrite boolean true

### EFI
d-i partman-efi/non_efi_system boolean true

### Grub
d-i grub-installer/only_debian boolean true
d-i grub-installer/with_other_os boolean true

### Disk layout
d-i partman-auto-lvm/new_vg_name string vg-root
d-i partman-auto/expert_recipe string                         \
      boot-root ::                                            \
              1 1 1 free method{ biosgrub } .                 \
              500 500 500 ext4                                \
                      $primary{ } $bootable{ }                \
                      method{ format } format{ }              \
                      use_filesystem{ } filesystem{ ext4 }    \
                      mountpoint{ /boot }                     \
              .                                               \
              100% 4096 100% linux-swap                       \
                      lv_name{ swap }                         \
                      method{ swap } format{ }                \
                      $lvmok{ }                               \
              .                                               \
              4096 4096 4096 xfs                              \
                      lv_name{ log }                          \
                      method{ lvm } format{ }                 \
                      use_filesystem{ } filesystem{ xfs }     \
                      mountpoint{ /var/log }                  \
                      $lvmok{ }                               \
              .                                               \
              20480 20480 20480 xfs                           \
                      lv_name{ root }                         \
                      method{ lvm } format{ }                 \
                      use_filesystem{ } filesystem{ xfs }     \
                      mountpoint{ / }                         \
                      $lvmok{ }                               \
              .                                               \
              1024 1024 -1 xfs                                \
                      lv_name{ app-data }                     \
                      method{ lvm } format{ }                 \
                      use_filesystem{ } filesystem{ xfs }     \
                      mountpoint{ /app-data }                 \
                      $lvmok{ }                               \
              .
# Write and configure LVM
d-i partman-lvm/confirm boolean true
d-i partman-lvm/confirm_nooverwrite boolean true
d-i partman/choose_partition select finish
d-i partman/confirm_write_new_label boolean true
d-i partman-auto-lvm/guided_size string max

### Base system installation
d-i base-installer/install-recommends boolean true
d-i base-installer/kernel/image string linux-generic
d-i debconf debconf/frontend select Noninteractive

### Apt setup
d-i apt-setup/restricted boolean true
d-i apt-setup/universe boolean true
d-i apt-setup/backports boolean true
d-i apt-setup/use_mirror boolean false
d-i apt-setup/services-select multiselect security, updates
d-i apt-setup/security_host string cn.security.ubuntu.com
d-i apt-setup/security_path string /ubuntu

### Package selection
d-i tasksel/first multiselect none
d-i pkgsel/language-packs multiselect en, zh
d-i pkgsel/upgrade select full-upgrade
d-i pkgsel/update-policy select unattended-upgrades

# Individual additional packages to install
d-i pkgsel/include string openssh-server \
    vim \
    git \
    tmux \
    build-essential \
    open-vm-tools \
    telnet \
    wget \
    curl \
    python \
    net-tools

### Finishing up the installation
d-i preseed/late_command string \
in-target sed -i 's/#PermitRootLogin .*/PermitRootLogin yes/' /etc/ssh/sshd_config; \
in-target sed -ie 's/GRUB_CMDLINE_LINUX="\(.*\)"/GRUB_CMDLINE_LINUX="quiet net.ifnames=0 biosdevname=0 ipv6.disable=1\1"/g' /etc/default/grub; \
in-target grub-mkconfig -o /boot/grub/grub.cfg; \
in-target sed -i "s/dhcp6: yes/dhcp6: no/g" /etc/netplan/01-netcfg.yaml; \
in-target sed -i "s/ens192/eth0/g" /etc/netplan/01-netcfg.yaml; \
in-target update-grub
d-i debian-installer/splash boolean false
d-i cdrom-detect/eject boolean true

### Reboot or Shutdown machine
d-i finish-install/reboot_in_progress note
#d-i debian-installer/exit/poweroff boolean true

Packer验证配置

完成配置文件的准备后,我们需要验证packer的配置文件是否正确,使用以下命令:

packer validate ubuntu-vsphere.json

Packer执行构建

packer build ubuntu-vsphere.json

如果第一次构建成功,并且虚拟机名称是固定的(本示例是基于日期的)下一次构建时可以增加-force参数覆盖上一次模版;

packer build -froce ubuntu-vsphere.json

检查构建结果

构建完成后,命令行如下提示;

登陆到vSpehre中可以看到模版:

完成

至此我们通过Packer实现了vSphere环境下Ubuntu多个版本的虚拟机模版的创建,Debian系统和Ubuntu的构建方法相同,您可以自己尝试制作一个。


发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注