Linux定制化镜像制作指南

image3

为什么需要定制化?

一款软件的正式发布,往往需要完善各个细节。其中安装部署是否方便友好很大程度上会影响到用户对该产品的易用性的评价。所以我们往往会看到软件厂商会给用户提供安装包,用户只需要一股脑儿的下一步,就可以完成垃圾软件的安装了。但一套大型的系统软件往往会有很多依赖,所以我们不仅要封装软件,最好连运行环境都要进行打包。于是现在很流行给用户提供一个Dockerfile或者docker-compose.yml,让用户开箱即用。但是如果用户需要从裸机开始部署呢?既然连系统都没有,当然是做成安装光盘。系统、软件、依赖环境一股脑全部部署。我们从头说起。

当我谈“定制化Linux安装镜像”,我在定制什么?

  • 安装界面定制化
    • 🎨 Boot Menu定制化
    • 🎨 Anaconda图形界面定制化
  • 📃 自定义安装信息收集
  • 📦 配套软件打包
  • 🤖️ 安装自动化

Linux安装光盘分析

在网上下载一个Linux系统安装镜像,这里我用的是CentOS-7-x86_64-Minimal-1511.iso,将镜像挂载到开发环境中

  • Linux:
1
2
mkdir /tmp/CentOS7
mount -t iso9660 ./CentOS-7-x86_64-Minimal-1511.iso /tmp/CentOS7
  • Mac:
1
2
3
mkdir /tmp/CentOS7
hdiutil attach -nomount ./CentOS-7-x86_64-Minimal-1511.iso
mount -t cd9660 /dev/disk4 /tmp/CentOS7

image1

上图即该镜像包含的所有文件,分别介绍一下:

  • EFI 负责引导的,包含bootloader
  • images PXE安装时需要的内核和引导程序(其实和isolinux中的内核及引导程序是相同的,不知道为啥放两个…)

image2

  • isolinux 系统内核及引导程序
  • LiveOS 包含了压缩的rootfs.img
  • Packages rpm包
  • repodata 安装包源信息

对于光盘的定制化,我们通常不需要对EFI/images进行任何操作,需要定制的是isolinux、LiveOS中的rootfs.img以及Packages,isolinux影响到进入安装的第一步,rootfs中包含的文件影响安装过程,Packages则是放我们所需要的第三方软件rpm安装包。


Linux安装流程分析

以下实验环境为CentOS(7.2.1511),其他发行版本可能略有区别

当我们启动安装光盘时,我们看到的是什么?
首先是ISOLINUX Boot Menu

image3

然后是Anaconda

Anaconda is the installer used by Red Hat Enterprise Linux, Fedora, and their derivatives.

image

从光盘加载到系统安装完成经历了什么呢?

  1. 开机
  2. BIOS检测(硬件检测、引导顺序等)
  3. 读取并运行装置内 MBR 的 boot Loader
  4. 加载内核
  5. 启动liveCD或Anaconda
  6. 由用户配置安装选项或解析kickstart配置
  7. 分区并挂载文件系统
  8. 完成安装,重启

NOTE: 步骤7时的rootfs是LiveOS/squashfs.img中的rootfs.img,而完成安装后的rootfs目前在/mnt/sysimage中

⚠️ 但是我们缺少了重要的“定制化安装信息收集”,从上面的流程分析可知,可以在Boot Menu和Anaconda之间插一脚(4~5步骤中增加一步),额外收集一些用户提供的安装信息。

我们需要先找到Anaconda的启动入口,上面已经介绍了如何挂载光盘,接下来我们需要把光盘里面的文件继续展开。因为挂载的ISO是只读的,所以我们需要将文件复制出来,分析修改完文件之后,再重新打包

1
2
3
4
5
6
7
8
9
10
11
# 挂载光盘💿
mkdir /tmp/CentOS7
hdiutil attach -nomount ./CentOS-7-x86_64-Minimal-1511.iso
mount -t cd9660 /dev/disk4 /tmp/CentOS7

# 复制文件
mkdir CentOS-7-x86_64-Minimal-1511
rsync -avz /tmp/CentOS7/ CentOS-7-x86_64-Minimal-1511

# 复制LiveOS
cp -r CentOS-7-x86_64-Minimal-1511/LiveOS ./LiveOS

现在得到了一个包含了squashfs.img的LiveOS文件夹,squashfs.img是干啥的?简单的说它是一个高压缩率的压缩文件,压缩了整个rootfs,看上去只有200多MB,实际上有2GB

Squashfs is a compressed read-only file system for Linux. Squashfs compresses files, inodes and directories, and supports block sizes up to 1 MB for greater compression. Several compression algorithms are supported. Squashfs is also the name of free software, licensed under the GPL, for accessing Squashfs filesystems.

执行命令解压开,你会得到一个包含了LiveOS/rootfs.img的名为squashfs-root的文件夹

1
unsquashfs squashfs.img

image
可以看到该文件其实是ext4的文件系统,启动一个Linux环境,挂载该文件,就能看到里面的所有东西了。这里我用docker启动了一个centos7环境
image
是不是跟Linux的根目录文件一样?这就是在安装时系统加载的rootfs,而Anaconda的入口文件就是usr/sbin/anaconda,这是一个Python脚本。我们打开它找到它的入口,在这里调用其他的脚本或者程序,就可以在Anaconda之前插一脚了。这里我自己写了一个小程序来收集用户的信息,在anaconda的入口处先调用这个程序。
image

修改完毕之后,我们需要重新压缩squashfs.img

1
mksquashfs squashfs-root squashfs.img -b 1024k -comp xz

把新的squashfs.img替换复制出来的光盘镜像文件中的squashfs.img。用dd命令将原来的iso引导信息导出

1
2
sudo cp squashfs.img CentOS-7-x86_64-Minimal-1511/LiveOS/
dd if=CentOS-7-x86_64-Minimal-1511.iso bs=512 count=1 of=boot.mbr

最后重新制作iso镜像,这里我用的是xorriso,命令如下:

1
xorriso -pathspecs as_mkisofs -as mkisofs -iso-level 3 -full-iso9660-filenames -volid "CentOS 7 x86_64" -appid  -publisher  -preparer "prepared by me" -eltorito-boot isolinux/isolinux.bin -eltorito-catalog isolinux/boot.cat -no-emul-boot -boot-load-size 4 -boot-info-table -isohybrid-mbr ../boot.mbr -eltorito-alt-boot -e images/efiboot.img -no-emul-boot -isohybrid-gpt-basdat -output ../repacked.iso .

现在让我们看看repacked.iso运行起来是什么样的吧:
image


界面定制化

Boot Menu定制

只需要修改isolinux/isolinux.cfg文件,文档参考:boot-menu-customization

Anaconda界面定制

Anaconda界面定制的修改稍微复杂一些,需要修改css文件,文档参考:customized-anaconda


自动化脚本(未完待续)

kickstart

程序部署脚本


参考资料

坚持原创技术分享,您的支持将鼓励我继续创作!