镜像制作工具diskimage-builder介绍
简介
diskimage-builder(简称dib)是一款用于构建系统镜像的工具,它被设计用于OpenStack的TripleO项目,支持qocw2、vhd、raw等主流镜像格式。
在众多系统镜像构建工具中,dib与众不同的地方在于其对元素(element)的设计。在dib中,所有想要构建的实体都被抽象为一个个的元素,元素与元素之间相互依赖,形成一种类似树的结构。dib拥有一些内置元素,位于diskimage-builder/elements
目录中,可以通过ELEMENTS_PATH
环境变量指定额外的元素目录。
例如:使用dib构建镜像时指定centos-minimal元素。
与yum包管理器中的rpm包类似,当构建系统镜像时指定centos-minimal元素时,dib会解析该元素的所有依赖元素,生成所有需要构建的元素,然后按顺序安装它们,最终生成一个完整的镜像。
概念
系统镜像
系统镜像指包含了可运行系统的虚拟磁盘文件。磁盘虚拟化是云计算的基础技术之一,dib支持的系统镜像格式有:qcow2,vhd,raw。在完成系统镜像构建后,dib会输出一个如上格式的虚拟磁盘文件,里面包含了构建好的系统。
如果要构建一个可启动的系统镜像,需要在构建时添加vm
元素:disk-image-create <distro> vm
。
元素
构建镜像需要给dib传递一系列的元素,这些元素决定了镜像该如何构建。
dib有着各种各样的元素。某些元素提供了一个root文件系统,例如ubuntu、fedora等等;另一些元素则在此基础上修改,并最终创建出我们需要的镜像;还有一些比较特殊的元素,例如vm,此元素会为镜像创建一个bootloader,确保镜像是可启动的。
输出格式
默认情况下dib会创建qcow2格式的镜像,可以通过-t <format>
参数指定需要的镜像格式,多种格式以逗号分隔。目前dib支持如下格式:
- qcow2:qemu支持的镜像格式之一,虚拟化中主流的镜像格式
- tar:归档格式
- tgz:归档与压缩结合的格式
- squashfs:基于Linux内核的压缩只读文件系统
- vhd:Hyper-V支持的一种镜像格式
- docker:docker支持的镜像格式,可被
docker import
导入 - raw:裸镜像格式
镜像布局
镜像文件与真正的硬盘一样,拥有分区、lvm、磁盘加密等等布局,这些布局在镜像构建的初始就应该做好,后续对镜像的改动也几乎不会去修改这些布局。
dib提供了一些针对镜像布局的元素,例如:vm
,当使用该元素时还需额外指定一个block-device-*
的元素,可选mbr、gpt以及efi,用来表示分区格式。如下命令创建了一个gpt格式的镜像文件。
disk-image-create -o centos vm block-device-gpt centos-minimal
默认情况下,定义镜像布局的配置位于各block-device-*
元素目录的block-device-default.yaml
文件中,如需额外配置,可以通过DIB_BLOCK_DEVICE_CONFIG
环境变量指定一个文件路径。
export DIB_BLOCK_DEVICE_CONFIG=file:///path/to/config
若构建镜像时不指定vm元素,那么镜像中将只包含root文件系统,没有分区信息。
镜像布局从上往下分为5个级别,分别代表着不同的布局划分步骤,以block-device-gpt元素的镜像布局配置文件为例:
- local_loop: # Level 0
name: image0
- partitioning: # Level 1
base: image0
label: gpt
partitions:
- name: BSP
type: 'EF02'
size: 8MiB
- name: root
flags: [ boot ]
size: 100%
mkfs: # Level 2
type: ext4
mount: # Level 3
mount_point: /
fstab: # Level 4
options: "defaults"
fsck-passno: 1
其中:
- Level 0
- Local Loop:该模块用于生成一个本地镜像文件
- name:镜像文件的名称,必选
- size:虚拟磁盘的大小,可选
- directory:镜像文件所在的位置,可选
- Local Loop:该模块用于生成一个本地镜像文件
- Level 1
- Partitioning:该模块用于为已有块设备生成分区
- base:块设备的名称,一般指定为Local Loop模块中镜像文件的名称,必选
- label:分区表类型,可选mbr或gpt,必选
- align:分区对齐,仅mbr分区需要,可选
- partitions:分区列表,每一个列表元素描述了一个分区
- name:分区的名称,必选
- flags:分区的标识,可选boot或primary,仅mbr分区需要,可选
- size:分区的大小,可选绝对值,如10GiB、1.75TB,或者相对值,如33%,相对值的话将依据剩余空闲空间计算,必选
- type:记录在分区表中的分区类型,MBR分区的默认值为0x83,GPT分区的默认值为8300,可选
- LVM:该模块用于为已有分区生成逻辑卷
- pvs:物理卷的列表,每个列表元素描述了一个物理卷(Physical Volume)
- name:物理卷的名称,必选
- base:分区的名称,LVM在此分区上创建物理卷,必选
- options:创建物理卷时的可选选项列表,即传递给pvcreate命令的参数列表,可选
- vgs:卷组的列表,每个列表元素描述了一个卷组(Volume Group)
- name:卷组的名称,必选
- base:物理卷的名称列表,LVM在这些物理卷上创建卷组,必选
- options:创建卷组时的可选选项列表,即传递给vgcreate命令的参数列表,可选
- lvs:逻辑卷的列表,每个列表元素描述了一个逻辑卷(Logical Volume)
- name:逻辑卷的名称,必选
- base:卷组的名称,LVM在此卷组上创建逻辑卷,必选
- size:逻辑卷的精确大小,与lvcreate命令的-L参数有着同样的语法,可选,size和extents参数必须二选一
- extents:逻辑卷的相对大小,与lvcreate命令的-l参数有着同样的语法,可选,size和extents参数必须二选一
- options:创建逻辑卷的可选选项列表,即传递给
lvcreate
命令的参数列表,可选
- pvs:物理卷的列表,每个列表元素描述了一个物理卷(Physical Volume)
- Partitioning:该模块用于为已有块设备生成分区
- Level 2
- Mkfs:该模块用于为已有分区创建文件系统
- base:分区的名称,Mkfs在此分区上创建文件系统,必选
- name:文件系统的名称,必选
- type:文件系统的类型,比如ext4或xfs,必选
- label:文件系统的标识,可被grub和fstab使用,默认和名称相同,可选
- opts:创建文件系统的可选选项列表,即传递给
mkfs
命令的参数列表,可选 - uuid:文件系统的uuid,目前支持ext2、ext3、ext4、xfs
- Mkfs:该模块用于为已有分区创建文件系统
- Level 3
- Mount:该模块用于挂载一个文件系统
- base:文件系统的名称,Mount会挂载此文件系统,必选
- name:挂载点的名称,必选
- mount_point:挂载点的路径,必选
- Mount:该模块用于挂载一个文件系统
- Level 4
- fstab:该模块用于创建fstab入口
- base:挂载点的名称,用于写入fstab,必选
- name:fstab入口的名称,必选
- options:特殊的挂载选项,对应fstab中的第四列,默认为
default
,可选 - dump-freq:文件系统是否需要导出,对应fstab的第五列,默认为
0
,可选 - fsck-passno:是否需要运行fsck,该工具用来检测/修复文件系统,对应fstab的第六列,默认为
2
,可选
- fstab:该模块用于创建fstab入口
执行阶段
每个元素下有许多目录,这些目录以阶段命名,dib会在不同的阶段执行这些目录下的脚本,这些脚本有着两位数数字的前缀,并会以数字的顺序执行。
dib共有如下阶段:
- root.d:初始化根文件系统,该阶段的主要工作是获取根文件系统的文件,并放置于工作区域($TARGET_ROOT)中。该阶段依赖于各发行版,也可以在已有镜像上定制。
- 运行于:chroot外面
- 输入:
- $ARCH=i386|amd64|armhf|arm64
- $TARGET_ROOT=/path/to/target/workarea
- extra-data.d:从宿主机环境中获取额外数据,这些数据会在镜像构建中使用。该阶段通常用来复制配置文件至工作区域($TMP_MOUNT_PATH)中,比如复制yum repo至
$TMP_MOUNT_PATH/etc/yum.repos.d
。- 运行于:chroot外面
- 输入:
- $TMP_HOOKS_PATH:表示chroot里面的/tmp/in_target.d目录
- pre-install.d:在chroot里面运行代码。该阶段用于在定制镜像之前做一些事先配置工作,比如说在配置dnf包管理工具、更新包缓存、安装python基础环境等等。
- 运行于:chroot里面
- install.d:运行于pre-install.d之后。该阶段用于安装包,也可以做一些镜像特定的操作。
- 运行于:chroot里面
- post-install.d:运行于install.d之后。该阶段往往用来做一些清理工作,比如说清理安装缓存。
- 运行于:chroot里面
- post-root.d:在chroot外面运行代码。该阶段用来执行一些不能在chroot里面做且需要在安装步骤之后做的事情,根文件系统位于
$TMP_BUILD_DIR/mnt
目录下。- 运行于:chroot外面
- block-device.d:自定义镜像所在的块设备。在目标树生成之后执行,该步骤暂时没看到元素在使用。
- 运行于:chroot外面
- 输入:
- $IMAGE_BLOCK_DEVICE=
- $TARGET_ROOT=
- 输出:
- $IMAGE_BLOCK_DEVICE=
- pre-finalise.d:该步骤用来重新挂载文件系统,到此步骤时根文件系统已经复制到最终的文件系统中,该文件系统位于
$TMP_BUILD_DIR/mnt
。- 运行于:chroot外面
- finalise.d:该步骤是根文件系统构建的最后一步,该步骤会运行chroot到最终的文件系统中,然后执行一些脚本。该步骤往往用来生成grub配置。
- 运行于:chroot里面
- cleanup.d:最后的清理工作作为收尾,该步骤用来清理一些临时配置。
- 运行于:chroot外面
- 输入:
- $ARCH=i386|amd64|armhf|arm64
- $TARGET_ROOT=/path/to/target/workarea
只有拥有可执行权限的文件才会执行,所以阶段目录中也可保存其他的文件,不过处于惯例,一般只在阶段目录中保存可执行脚本,数据保存在其他位置中。
除了这些阶段以外,元素还拥有其他特定的目录/文件:
- environment.d/:该目录用于存放环境变量,每个阶段执行前都会加载该目录下的环境变量文件。注意不要在文件中添加如
set -x
这样的全局标志,这样会影响到所有的脚本。 - element-deps:该文件用来保存依赖的元素列表,以换行符分隔。
- element-provides:该文件用来保存本元素的别名列表,以换行符分隔。举例说表示分区类型的元素有block-device-mbr、block-device-gpt等等,上层元素需要依赖mbr、gpt中的某个分区,却不知道到底依赖其中的哪一个,若mbr、gpt元素都在element-provides文件中写入名为block-device的别名,那么上层元素写入依赖的时候只需要指定block-device元素就可以了。最后在镜像构建时通过指定如
xxx block-device-mbr
、xxx block-device-gpt
的方式来真正区分时候哪一个分区。
安装类型
同一个软件,通常会有多种不同的安装方式,例如源代码安装、分发包安装、pip安装等等。在dib中,默认的软件安装方式是源代码安装(source),可以通过添加--install-type参数或DIB_DEFAULT_INSTALLTYPE环境变量修改。
dib中的元素可以定义不同的软件包安装方式,格式为<install-dir-prefix>-<install-type>-install
,以nova元素为例,该元素同时提供了source和package两种方式:
# package方式
nova/install.d/nova-package-install/74-nova
# source方式
nova/install.d/nova-source-install/74-nova
dib也可以针对单个元素的软件包安装方式进行修改,环境变量的格式为DIB_INSTALLTYPE_<install_dir_prefx>
,例如:
export DIB_INSTALLTYPE_nova=package
示例
centos7-minimal
docker run -it --rm --name dib --privileged -v /dev:/dev af.frankming.com.cn/docker-drpd/openstack/centos-binary-openstack-base:train bash
dnf install -y yum-utils e4fsprogs kpartx qemu-img gdisk
pip install ironic-python-agent-builder diskimage-builder
mkdir -p /tmp/repo
echo '[base]
name=CentOS-$releasever - Base
baseurl=http://10.1.14.235/centos/$releasever/os/$basearch/
gpgcheck=0
#released updates
[updates]
name=CentOS-$releasever - Updates
baseurl=http://10.1.14.235/centos/$releasever/updates/$basearch/
gpgcheck=0
#additional packages that may be useful
[extras]
name=CentOS-$releasever - Extras
baseurl=http://10.1.14.235/centos/$releasever/extras/$basearch/
gpgcheck=0
#additional packages that extend functionality of existing packages
[centosplus]
name=CentOS-$releasever - Plus
baseurl=http://10.1.14.235/centos/$releasever/centosplus/$basearch/
gpgcheck=0
enabled=0
[epel]
name=Extra Packages for Enterprise Linux 7 - $basearch
baseurl=http://10.1.14.235/epel/7/$basearch
enabled=1
gpgcheck=0
' > /tmp/repo/base.repo
export DIB_YUM_MINIMAL_BOOTSTRAP_REPOS=/tmp/repo
disk-image-create vm block-device-gpt centos-minimal
centos7
docker run -it --rm --name dib --privileged -v /dev:/dev af.frankming.com.cn/docker-drpd/openstack/centos-binary-openstack-base:train bash
dnf install -y yum-utils e4fsprogs kpartx qemu-img gdisk
pip install ironic-python-agent-builder diskimage-builder
export DIB_DISTRIBUTION_MIRROR=http://mirrors.frankming.com.cn/centos/
export DIB_CLOUD_IMAGES=/data/images/CentOS-7-x86_64-GenericCloud.qcow2
export DIB_LOCAL_IMAGE=/data/images/CentOS-7-x86_64-GenericCloud.qcow2
export IMAGE_NAME=centos7
export DIB_EPEL_MIRROR=http://mirrors.frankming.com.cn/epel
export DIB_EPEL_DISABLED=1
export DIB_CLOUD_INIT_DATASOURCES="ConfigDrive, OpenStack"
# /usr/local/lib/python3.9/site-packages/diskimage_builder/elements/yum/pre-install.d/01-00-centos-python3
# yum install -y http://10.33.41.25/CI/openstack-train/others/python36-PyYAML-3.13-1.el7.x86_64.rpm
disk-image-create centos7 vm cloud-init-datasources dhcp-all-interfaces iscsi-boot dracut-regenerate block-device-efi -o $IMAGE_NAME
centos8
docker run -it --rm --name dib --privileged -v /dev:/dev af.frankming.com.cn/docker-drpd/openstack/centos-binary-openstack-base:train bash
dnf install -y yum-utils e4fsprogs kpartx qemu-img gdisk
pip install ironic-python-agent-builder diskimage-builder
export DIB_YUM_MINIMAL_BOOTSTRAP_REPOS=/etc/yum.repos.d
export DIB_RELEASE=8
disk-image-create vm block-device-gpt centos-minimal
ipa-centos8
docker run -it --rm --name dib --privileged -v /dev:/dev af.frankming.com.cn/docker-drpd/openstack/centos-binary-openstack-base:train bash
dnf install -y yum-utils e4fsprogs kpartx qemu-img gdisk
pip install ironic-python-agent-builder diskimage-builder
export DIB_YUM_MINIMAL_BOOTSTRAP_REPOS=/etc/yum.repos.d
export DIB_RELEASE=8
export ELEMENTS_PATH=/usr/local/share/ironic-python-agent-builder/dib
export DIB_DEFAULT_INSTALLTYPE=package
export DIB_EPEL_MIRROR=http://mirrors.frankming.com.cn/epel
export DIB_EPEL_DISABLED=1
export DIB_DEV_USER_USERNAME=cloud
export DIB_DEV_USER_PWDLESS_SUDO=yes
export DIB_DEV_USER_PASSWORD=frankming@123++
disk-image-create -o ipa-centos8-stable-train ironic-python-agent-ramdisk centos-minimal devuser stable-interface-names
# ipa-arm64,arm64无biosdevname包,无法使用stable-interface-names元素
# disk-image-create -a aarch64 -o ipa-centos8-stable-train-aarch64 ironic-python-agent-ramdisk centos-minimal devuser
ipa-debian
docker run --privileged -it --rm --cap-add=SYS_ADMIN --device-cgroup-rule="b 7:* rmw" --name test af.frankming.com.cn/docker-drpd/openstack/debian-base:bullseye bash
pip install ironic-python-agent-builder
apt update && apt install -y qemu-utils sudo debootstrap git rsync cpio
export DIB_DISTRIBUTION_MIRROR=http://mirrors.frankming.com.cn/debian/
export DIB_DEBIAN_SECURITY_MIRROR=http://mirrors.frankming.com.cn/debian-security/
export DIB_DEFAULT_INSTALLTYPE=source
export DIB_DEV_USER_USERNAME=cloud
export DIB_DEV_USER_PWDLESS_SUDO=yes
export DIB_DEV_USER_PASSWORD=frankming@2022++
echo 'ironic-python-agent tar /tmp/ironic-python-agent http://10.33.41.25/CI/openstack-train/others/ironic-python-agent-train.tar.gz *' > /usr/local/share/ironic-python-agent-builder/dib/ironic-python-agent-ramdisk/source-repository-ironic-python-agent
echo 'ironic-lib tar /tmp/ironic-lib http://10.33.41.25/CI/openstack-train/others/ironic-lib-stable-train.tar.gz *' > /usr/local/share/ironic-python-agent-builder/dib/ironic-python-agent-ramdisk/source-repository-ironic-lib
echo 'requirements tar /tmp/requirements http://10.33.41.25/CI/openstack-train/others/requirements-stable-victoria.tar.gz *' > /usr/local/share/ironic-python-agent-builder/dib/ironic-python-agent-ramdisk/source-repository-requirements
ironic-python-agent-builder -o my-ipa debian -e devuser -e stable-interface-names
注意事项
Cannot open: https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm. Skipping.
centos7独有
文件位于diskimage_builder\elements\yum\pre-install.d\01-00-centos-python3
,内网环境需将该行注释,且配置DIB_YUM_MINIMAL_BOOTSTRAP_REPOS
环境变量需要有epel仓库
容器中运行需添加--privileged选项
mount -o size=20G -o remount /dev
mount -o size=20G -o remount /dev/shm
dib无法直接得知需要的程序依赖,可能出现构建到一半才报错无此命令的情况。如果通过pip安装,更是需要手动把所有的依赖程序都安装上。
理想的系统镜像构建工具还是得类似于docker那样,通过dockerfile直观、简便地构建。
二次开发后执行发现脚本没执行?
windows下文件无rwx权限管理,所有文件默认无w权限,所以dib执行时将脚本文件当成普通文件,跳过执行
cpio -idmv < xxx.cpio
同类型工具
Oz
image-bootstrap
imagefactory
参考文档
Tool support for image creation — Virtual Machine Image Guide documentation (openstack.org)
本文来自博客园,作者:frankming,转载请注明原文链接:https://www.cnblogs.com/frankming/p/16813610.html