镜像制作
准备
安装必要工具
yum install -y genisoimage pykickstart syslinux isomd5sum
验证命令是否可用
genisoimage --version
isohybrid -V
md5sum --version
ksvalidator -h
挂载操作系统镜像
ls -l
mkdir cdrom
mount -o loop Kylin-Server-V10-SP3-General-Release-2212-X86_64.iso cdrom
创建镜像文件临时目录,复制镜像内容
mkdir iso
cp -rf cdrom/. ./iso
检查
ls -l -a iso
取消挂载
umount cdrom
定制启动菜单
接下来尝试修改下启动候选项以及背景图片
编辑 isolinux/isolinux.cfg 文件
cd iso/isolinux/
chmod u+rw isolinux.cfg
vi isolinux.cfg
这里修改一下开机候选项的标题 menu title ,也可调整下 timeout 时间,这里默认是60s自动选择,一般自动安装不需要这么长6秒就可以。
删除一些启动项
BIOS引导,只保留开启启动项,注意这里的 LABEL 字段Kylin-Server-10
, 请记住该字段在打包镜像时需要-V指定该名字,否则后出现启动找不到镜像问题 。[4]
移除可写入权限
chmod u-w isolinux.cfg
调整EFI引用启动项,则需要编辑 EFI/BOOT/grub.cfg 文件,删除相应的启动项,同样的也可调整超时时间 set timeout=60 。
cd ../EFI/BOOT/
chmod u+rw grub.cfg
vi grub.cfg
若修改了镜像名称,则还需调整 LABEL
chmod u-w grub.cfg
制作一张张与 isolinux/splash.png
一样尺寸的图片,替换原有的splash.png作为启动项的背景图,如下:
构建镜像
完成所有准备,开始打包镜像,切换目录至创建的iso根目录
构建镜像,注意请保证当前工作目录在镜像解压后的根目录中!
genisoimage -o HelloWorldV10.iso \
-b isolinux/isolinux.bin \
-c isolinux/boot.cat \
-no-emul-boot -boot-info-table -boot-load-size 4 \
-V "Kylin-Server-10" \
-input-charset utf-8 \
-R -J -v -T ./
构建成功
参数比较多 [5] ,大多只是写开关参数,重点关注 -V
其他保持默认:
-o
设置输出镜像位置和文件名。-V "Kylin-Server-10"
,设置卷标Volume ID。-b isolinux.bin
指定开机映像文件。-c isolinux/boot.cat
制作启动光盘时,mkisofs会将开机映像文件中的文件名写入到boot.cat文件中,这样在启动光盘时,就可以通过boot.cat文件找到开机映像文件中的文件名,从而找到开机映像文件中的文件。-no-emul-boot
,非模拟模式启动。-boot-load-size 4
设置加载映像的扇区数。-boot-info-table
生成启动信息表。-input-charset utf-8
输入字符集类型设置。-joliet-long
生成长文件名。-R
使用Rock Ridge Extensions,是用于linux环境下的光盘,文件名区分大小写同时记录文件长度。-J
使用Joliet格式的目录与文件名称,Jolient是windows下使用的光盘。-v
执行时显示详细的信息。-T
,建立文件名的转换表,适用于不支持Rock Ridge Extensions的系统。
查看构建的镜像
ls -l -a
将ISO镜像转换为可在BIOS和UEFI两种模式下启动的混合镜像
isohybrid HelloWorldV10.iso
写入镜像的md5值
implantisomd5 HelloWorldV10.iso
验证镜像完整性,过程需要花费一些时间
checkisomd5 HelloWorldV10.iso
启动验证
使用虚拟机 启动刚才制作的镜像 VirtualBox 为例。
启动时可以看到背景图片、标题、启动选项都已经更改。
选择 Install … 进入安装流程。
在稍等片刻后将会引导系统进入Anaconda安装界面,如下:
若系统未能进入Anaconda安装界面 请检查 genisoimage -V 参数是否与 isolinux.cfg 启动项 中的相同。
Kickstart自动化
概述
上一步中我们成功的构建了一个自定义的镜像,但是在启动后仍然需要通过Anaconda界面配置主机名、语言、时区、分区、用户口令等操作,接下来章节将进入自动化安装选项。
kickstart是一种无人值守的安装方式。它的工作原理是在安装过程中记录典型的需要人工干预填写的各种参数,并生成一个配置文件(ks.cfg),在安装过程中,安装程序首先会去查找ks配置文件,如果找到合适的参数,就采用所找到的参数;如果没有找到合适的参数,便需要安装者手动设定。所以,如果kickstart文件涵盖了安装过程中需要设定的所有参数,安装者只需要告诉安装程序从何处取ks.cfg文件,就能实现系统安装的自动化。[3]
Anaconda会在/root目录下创建一个 anaconda-ks.cfg
该文件记录我们手动安装系统时的各项参数,因此可以直接从已经安装的系统中获取的 /root/anaconda-ks.cfg 与 /root/initial-setup-ks.cfg ,并在这个基础上编辑修改。[7]
Kickstart 文件主要分为 命令部分(Command)、依赖包部分、运行阶段部分,各部分通过 %XXX
开启 %end
关闭,更多资料见 [8]
我们很多需要关注的命令段命令详见 [9]
KS文件详解
下面以一个实例和注释的方式进行讲解
在镜像制作的根目录创建文件ks.cfg
touch ks.cfg
ls -a -l
从已经完成安装系统中复制出 /root/initial-setup-ks.cfg 并按照需求修改文件,然后将修改后的内容写入 ks.cfg 文件中。
ks.cfg 文件内容如下:
#
# Command section 命令段
#
#version=DEVEL
# License agreement 同意许可协议
eula --agreed
# Use graphical install 图形化安装
graphical
# 安装时不跳过操作步骤,并截图把每个步骤的截图保存到/root/anaconda-screenshots
# DEBUG: 为了方便调试,可以注释掉
# autostep --autoscreenshot
# 在系统安装成功后,弹出安装介质,自动重启(不需要手动确认)
reboot --eject
# Network information 网络信息 仅设置主机名
# network --bootproto=dhcp --device=enp0s3 --onboot=off --ipv6=auto --no-activate
network --hostname=kkk
# Use CDROM installation media 使用镜像安装
# cdrom
# 使用URL指定安装源,防止Ventoy类的引导无法识别到镜像
url --url=file:///run/install/repo
# Run the Setup Agent on first boot 是否在第一次启动时弹出引导提示
firstboot --disable
# 关闭selinux
selinux --disabled
# 不启用任何防火墙规则
firewall --disable
# System services 系统服务控制
services --enabled=chronyd
# Partition clearing information 清除指定设备上的所有分区
# clearpart --all --initlabel
# 清除第一块磁盘所有分区,防止将安装盘分区删除
clearpart --drives=sda --all
# 安装到第一块磁盘
ignoredisk --only-use=sda
# Disk partitioning information 磁盘分区,默认在第一块sda磁盘上进行分区
# 使用全部空间 使用 --size=1 --grow
# 使用所有剩余空间 --percent=100
# - /boot: 1024MB
# - /boot/efi: 200MB
# - swap: 按照内存自动分配
# - /tmp: 5G
# - /home: 5G
# - /: 剩余所有容量
part /boot --fstype="xfs" --ondisk=sda --size=1024
part /boot/efi --fstype="efi" --ondisk=sda --size=200 --fsoptions="umask=0077,shortname=winnt"
part swap --recommended
# 创建LVM分区
part pv.777 --fstype "lvmpv" --ondisk=sda --size=1 --grow
# 创建卷组
volgroup kl_local --pesize=4096 pv.777
# 对卷组划分空间
logvol /tmp --fstype="xfs" --size=5120 --name=tmp --vgname=kl_local
logvol /home --fstype="xfs" --size=5120 --name=home --vgname=kl_local
logvol / --fstype="xfs" --percent=100 --name=root --vgname=kl_local
# Keyboard layouts 键盘
keyboard --xlayouts='cn'
# System language 系统语言
lang zh_CN.UTF-8
# System timezone 时区
timezone Asia/Shanghai --utc
# Root password
# 直接使用明文:
# rootpw 123qwe
# SM3加盐Hash 123qwe 口令 sm3算法 JoxCGbA0uAwp2qye 盐值 生成方式如下:
# perl -e 'print crypt("123qwe",q($sm3$JoxCGbA0uAwp2qye)),"\n"'
rootpw --iscrypted $sm3$JoxCGbA0uAwp2qye$3rGGveX/D0t4tfYzmz3dbAOS.JoyXexZkbdN4UAHBCD
# 创建用户 口令生成方式同上
# - user1: sudo权限的用户
# - user2: 普通用户
user --name=user1 --groups=wheel --password=$sm3$JoxCGbA0uAwp2qye$3rGGveX/D0t4tfYzmz3dbAOS.JoyXexZkbdN4UAHBCD --iscrypted
user --name=user2 --password=$sm3$JoxCGbA0uAwp2qye$3rGGveX/D0t4tfYzmz3dbAOS.JoyXexZkbdN4UAHBCD --iscrypted
#
# POST section 安装后操作段
# 在 nochroot 下可以访问到镜像中的文件,用于执行一些拷贝任务
# 在这个阶段中
# - ISO镜像根目录挂载于: /dev/cdrom
# - 操作系统根目录挂载于: /mnt/sysimage
#
# 例如: cp /dev/cdrom/ks.cfg /mnt/sysimage/root/ks.cfg
%post --nochroot
#####copy kyinfo and LICENSE
if [ -e /tmp/.kyinfo ];then
echo y | cp -a /tmp/.kyinfo $ANA_INSTALL_PATH/etc/
fi
if [ -e /tmp/LICENSE ];then
echo y | cp -a /tmp/LICENSE $ANA_INSTALL_PATH/etc/
fi
if [ -e /run/install/repo/.kyinfo ];then
echo y | cp -a /run/install/repo/.kyinfo $ANA_INSTALL_PATH/etc/
fi
if [ -e /run/install/repo/LICENSE ];then
echo y | cp -a /run/install/repo/LICENSE $ANA_INSTALL_PATH/etc/
fi
##### kylin postaction
## cdrom install, copy .kylin-post-actions
if [ -e /run/install/repo/.kylin-post-actions ];then
echo y | cp -a /run/install/repo/.kylin-post-actions /tmp/.kylin-post-actions
echo "repo=/run/install/repo" > /tmp/.kylin-repo
fi
## copy kylin post scripts in new os
if [ -e /tmp/.kylin-post-actions ];then
echo y | cp -a /tmp/.kylin-post-actions $ANA_INSTALL_PATH/bin
fi
if [ -e /tmp/.kylin-repo ];then
echo y | cp -a /tmp/.kylin-repo $ANA_INSTALL_PATH/tmp/
fi
## copy and run .kylin-post-actions-nochroot
if [ -e /run/install/repo/.kylin-post-actions-nochroot ];then
echo y | cp -a /run/install/repo/.kylin-post-actions-nochroot /tmp/.kylin-post-actions-nochroot
fi
if [ -e /tmp/.kylin-post-actions-nochroot ];then
/bin/bash -x /tmp/.kylin-post-actions-nochroot &> $ANA_INSTALL_PATH/var/log/.kylin-post-actions-nochroot.log
fi
%end
#
# Post install section 安装后操作段,可以在这里进行一些初始化操作
# 这里的权限为root权限,无法访问到cdrom中的文件,但是可以访问到安装后的文件
#
# 将一些初始化操作放到这里,该阶段的日志将通过 --log 输出到指定文件中,这在调试时候非常有用
%post --log=/root/kickstart-post.log
systemctl disable systemd-networkd-wait-online.service
systemctl disable multipathd.service
systemctl disable firewalld.service
systemctl stop firewalld.service
systemctl disable rpcbind.service
# 设置文件打开上限
cat >> /etc/security/limits.conf <<EOF
* soft nproc 65536
* hard nproc 65536
* soft nofile 65536
* hard nofile 65536
EOF
### do kylin post action
if [ -e /bin/.kylin-post-actions ];then
/bin/bash -x /bin/.kylin-post-actions &> /var/log/.kylin-post-actions.log
fi
%end
#
# Package install section 软件包安装段
#
%packages
@^minimal-environment
%end
%addon ADDON_placeholder --enable --reserve-mb=1024M
%end
# 设置用户密码策略
%anaconda
pwpolicy root --minlen=8 --minquality=1 --strict --nochanges --notempty
pwpolicy user --minlen=8 --minquality=1 --strict --nochanges --emptyok
pwpolicy luks --minlen=8 --minquality=1 --strict --nochanges --notempty
%end
如果需要执行一些初始化脚本操作可以在
%post
阶段进行。需要从用镜像中复制文件可以在%post --nochroot
阶段进行。
检查ks脚本是否正确 (需要安装 pykickstart)
ksvalidator ks.cfg
启动项加入KS脚本
增加 BIOS启动项
编辑 isolinux/isolinux.cfg 文件
cd isolinux/
chmod u+rw isolinux.cfg
vi isolinux.cfg
操作如下:
- 复制一遍原来的启动项作为新的自动安装启动项。
- 修改启动项标题 和 原启动项作出区分,名字可以自定义。
- 在 append 中加入命令
inst.ks=cdrom:/ks.cfg
。 - 移除原启动的
menu default
。
label linux
menu default
menu label ^Auto Install Kylin Linux Advanced Server V10
kernel vmlinuz
append initrd=initrd.img inst.stage2=hd:LABEL=Kylin-Server-10 inst.ks=cdrom:/ks.cfg quiet
label linux
menu label ^Install Kylin Linux Advanced Server V10
kernel vmlinuz
append initrd=initrd.img inst.stage2=hd:LABEL=Kylin-Server-10 quiet
添加EFI启动项
cd ../EFI/BOOT/
chmod u+rw grub.cfg
vi grub.cfg
操作如下:
- 复制一遍原来的启动项作为新的自动安装启动项,并且放置到第一个。
- 修改启动项标题 和 原启动项作出区分,名字可以自定义。
- 在 linuxefi 命令中加入参数
inst.ks=cdrom:/ks.cfg
。
menuentry 'Auto Install Kylin Linux Advanced Server V10' --class fedora --class gnu-linux --class gnu --class os {
linuxefi /images/pxeboot/vmlinuz inst.stage2=hd:LABEL=Kylin-Server-10 inst.ks=cdrom:/ks.cfg quiet
initrdefi /images/pxeboot/initrd.img
}
接下来进入打包环节 详见前面章节中的 构建镜像
genisoimage -o HelloWorldV10.iso \
-b isolinux/isolinux.bin \
-c isolinux/boot.cat \
-no-emul-boot -boot-info-table -boot-load-size 4 \
-V "Kylin-Server-10" \
-input-charset utf-8 \
-R -J -v -T ./
isohybrid HelloWorldV10.iso
implantisomd5 HelloWorldV10.iso
启动验证
使用虚拟机启动验证
启动项
提示Kickstart加载
稍等片刻后将自动配置
进入安装界面
定制软件
安装必要工具
安装制作工具
yum install -y createrepo comps-extras
软件源配置说明
回到镜像根路径
- Packages/ 目录用于存放所有需要安装RPM的软件安装包。
- repoddata/ 用于存放软件清单和安装规则,以及一些校验文件。
在repoddata/目录中我们只需要关心软件清单文件,其余文件都是仓库生成,软件清单通常以 ***-comps-***.xml
的格式出现在repoddata/目录中。
软件清单文件 comps.xml 是用来告知安装程序anaconda,用户选择了某个组是应该有哪些包需要安装,定义了在安装过程中,包是如何被捆绑在一起的。 [17]
在进入如何定制软件之前,先了解一下 comps.xml 文件。
一个简单comps.xml 文件示例如下:
<?xml version="1.0" encoding="UTF-8"?>
<!-- 省略 <group><id>base</id> ... </group> -->
<!-- 省略 <group><id>core</id> ... </group> -->
<!-- 省略 <group><id>debugging</id> ... </group> -->
<!-- 软件包组:这里用于描述需要安装的一组软件 -->
<group>
<!-- 软件组ID -->
<id>hello-world</id>
<!-- 软件组名称 -->
<name>hello world software group</name>
<name xml:lang="zh_CN">HelloWorld软件组</name>
<!-- 软件组描述 -->
<description>this is hello world software group.</description>
<description xml:lang="zh_CN">这是HelloWorld软件组。</description>
<!-- 是否是默认组,true时若该组没有被选中则默认安装 -->
<default>true</default>
<!-- 是否显示在安装选项中 -->
<uservisible>false</uservisible>
<!-- 软件包列表 -->
<packagelist>
<!-- 类型: default(默认)、mandatory(必须)、optional(可选) 通常需要安装的软件包默认选择 mandatory(必须) -->
<packagereq type="mandatory">tcpdump</packagereq>
<packagereq type="mandatory">iptables</packagereq>
</packagelist>
</group>
<!-- 安装环境,这里用于描述需要安装的多组软件 -->
<environment>
<!-- 环境ID -->
<id>hello-world-environment</id>
<!-- 环境名称 -->
<name>hello world environment</name>
<name xml:lang="zh_CN">HelloWorld运行环境</name>
<!-- 环境描述 -->
<description>this is hello world environment.</description>
<description xml:lang="zh_CN">这是HelloWorld运行环境。</description>
<!-- 显示顺序 -->
<display_order>5</display_order>
<!-- 是否是默认环境,true时若该环境没有被选中则默认安装 -->
<default>true</default>
<!-- 待安装软件组 -->
<grouplist>
<groupid>base</groupid>
<groupid>core</groupid>
<groupid>hello-world</groupid>
</grouplist>
<!-- 可选软件组列表 -->
<optionlist>
<groupid>debugging</groupid>
</optionlist>
</environment>
</comps>
注:
<category>
已经过时,目前都采用<environment>
定义安装环境。
接下来我们看一个最小安装的实例
软件清单上的文件是如何与 Packages/ 目录关联?
<packagereq>tcpdump<packagereq>
指定的是需要安装软件的包名,通常来说RPM安装包会以 软件包名-版本号.发行版本.指令集.rpm 命名,如下所示:
除了需要安装的软件包外,待安装的软件包所依赖的软件包也需要放入到 Packages/ 目录中,依赖关系将在安装时被自动解决类似于YUM。
定制软件
追加新软件:
- 将需要软件安装包放入
Packages/
目录中。 - 修改comps.xml 文件:
- 创建新的
<group>
,并在其中描述追加的软件。 - 创建新的
<environment>
在<grouplist>
中加入刚才创建的group。
- 创建新的
修改软件版本:
- 将老版本软件从
Packages/
目录中删除。 - 将新版软件安装包放入
Packages/
目录中。 - 视情况修改comps.xml 文件,若软件安装包名称变更,则修改软件安装包名称。
最佳实践:
- 复制最小安装环境。
- 修改安装环境名称描述等。
- 在最小环境中
<grouplist>
中加入需要安装的软件。
进入ISO镜像制作根目录
从原 repodata/ 目录中复制 comps.xml 文件至镜像根目录,并命名为 comps.xml
cp repodata/*-comps-*.xml comps.xml
ls -l
编辑 comps.xml 文件,复制一个加入软件组和环境。
vi comps.xml
例如上文见中 hello-world-environment 环境,
<group>
<id>hello-world</id>
<name>hello world software group</name>
<description>this is hello world software group.</description>
<default>true</default>
<uservisible>false</uservisible>
<packagelist>
<packagereq type="mandatory">tcpdump</packagereq>
<packagereq type="mandatory">iptables</packagereq>
</packagelist>
</group>
<environment>
<id>hello-world-environment</id>
<name>hello world environment</name>
<description>this is hello world environment.</description>
<display_order>5</display_order>
<default>true</default>
<grouplist>
<groupid>base</groupid>
<groupid>core</groupid>
<groupid>hello-world</groupid>
</grouplist>
<optionlist>
<groupid>debugging</groupid>
</optionlist>
</environment>
删除原 repodata/
rm -rf repodata/
在镜像的根目录生成新的 repodata/ 目录
createrepo -g comps.xml .
检查新文件目录
ls -l -a repodata/
KS自动安装软件
如果需要ks自动安装刚才添加的hello-world-environment环境中的所有软件,需要修改位于镜像根目录的ks.cfg文件
vi ks.cfg
在 %packages 阶段中加入我们需要的环境,规则如下 [9] :
@^
前缀 指定 环境,例如:@^minimal-environment
。@
前缀 指定 软件组,支持通配符*
,例如:@standard
。- 没有 前缀 指定软件,支持通配符
*
,例如:sqlite
。 -
前缀排除,支持通配符*
,例如:-tomcat*
、-@web-server
。
接下来和之前一样 构建镜像就可以。
createrepo -g comps.xml . ;\
genisoimage -o HelloWorldV10.iso \
-b isolinux/isolinux.bin \
-c isolinux/boot.cat \
-no-emul-boot -boot-info-table -boot-load-size 4 \
-V "Kylin-Server-10" \
-input-charset utf-8 \
-R -J -v -T ./ ; \
isohybrid HelloWorldV10.iso ; \
implantisomd5 HelloWorldV10.iso
启动验证
启动虚拟机验证安装环境是否加入,请暂时移除ks文件,否则进入自动安装无法查看。
在软件选择界面中已经可以看到helloworld环境,选中后可以看到可选项的 调试工具 。
参考文献
[1]. 博客园 . CentOS 6.5 iso系统定制 . 8年扛枪梦 . 2016.05 . https://www.cnblogs.com/appresearch/p/5484450.html
[2]. 黑马程序员 . kickstart网络部署教程【运维自动化】. 2019.10 . https://www.itheima.com/news/20191008/165847.html
[3]. openEuler . 使用kickstart自动化安装 . https://docs.openeuler.org/zh/docs/20.03_LTS/docs/Installation/%E4%BD%BF%E7%94%A8kickstart%E8%87%AA%E5%8A%A8%E5%8C%96%E5%AE%89%E8%A3%85.html
[4]. 腾讯云 . 从 1 到 0 构建博客项目(2) – 操作系统篇(2)–定制Centos . 大大刺猬 . 2020.09 . https://cloud.tencent.com/developer/article/1700557
[5]. die.net . genisoimage(1) - Linux man page . https://linux.die.net/man/1/genisoimage
[6]. Applenice 博客 . CentOS 7 ISO镜像定制内核版本 . Applenice . 2023.12 https://www.applenice.net/2023/12/30/CentOS-Customized-Kernel-Version/
[7]. CSDN . 银河麒麟服务器操作系统V10SP1基于Kickstart无人值守安装 . 月亮打烊了+ . 2022.08 . https://blog.csdn.net/weixin_54752007/article/details/126037635
[8]. github . Kickstart Documentation . pykickstart . https://github.com/pykickstart/pykickstart/blob/master/docs/kickstart-docs.rst
[9]. redhat . 27.3. Kickstart Syntax Reference . https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/7/html/installation_guide/sect-kickstart-syntax
[10]. 看云 . 定制CentOS7镜像 . https://www.kancloud.cn/hali90s/admin/1250445
[11]. github . CentOS iso 镜像定制 .hlyani . https://hlyani.github.io/notes/linux/diy_centos_iso.html
[12]. zhaowenyu博客 . CentOS全自动安装镜像制作 . zhaowenyu . https://www.zhaowenyu.com/linux-doc/centos-autoinstall.html
[13]. 博客园 . Linux中的wheel用户组是什么? . OpsDrip . 2019.04 . https://www.cnblogs.com/opsprobe/p/10781620.html
[14]. serverfault . CentOS/RHEL 7 LVM Partitioning in Kickstart? . Michael Hampton . 2017.01 . https://serverfault.com/questions/826006/centos-rhel-7-lvm-partitioning-in-kickstart
[15]. Redhat . How to create custom package groups from a custom yum repository? . 2022.03 . https://access.redhat.com/solutions/42196
[16]. fedoraproject . How to use and edit comps.xml for package groups . 2022.08 . https://fedoraproject.org/wiki/How_to_use_and_edit_comps.xml_for_package_groups
[17]. 51CTO博客 . rshare . comps.xml文件定制 . 2017.09 .https://blog.51cto.com/u_1364952/1968947
[18]. CSDN . ks.cfg 怎么读取光盘 (cdrom) 上的文件并执行对应的脚本 . freeabc . 2022.06 . https://blog.csdn.net/freeabc/article/details/124915720
[19]. 博客园 . Linux 操作系统安装盘的定制 . chinaunixzcx . 2008-08-31 . http://m.blog.chinaunix.net/uid-20489809-id-1665907.html
[20]. Redhat . 自定义 Anaconda . https://access.redhat.com/documentation/zh-cn/red_hat_enterprise_linux/8/html-single/customizing_anaconda
[21]. 博客园 . 定制Centos8的图形用户界面之定制图形元素 . 一只小麻瓜 . 2022.11 . https://www.cnblogs.com/xiaomagua/p/16900385.html