本文以centos 7.6ISO为例,构建了用于自动化安装的ISO

构建基础环境

(1)下载centos7.6iso文件

1
2
# cd ~
# wget -c http://mirrors.163.com/centos/7.6.1810/isos/x86_64/CentOS-7-x86_64-DVD-1810.iso

(2)挂载到/mnt目录下

1
# mount -o loop /root/CentOS-7-x86_64-DVD-1810.iso /mnt

(3)在$HOME目录下创建如下目录

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# cd ~/BuildISO/
# tree
.
|-- all_rpms
|-- ISO
|   |-- images
|   |-- isolinux
|   |-- LiveOS
|   |-- Packages
|   `-- repodata
`-- utils

创建目录的命令如下:

1
2
3
4
5
6
# mkdir ~/BuildISO
# cd ~/BuildISO
# mkdir  all_rpms  ISO  utils
# cd ~/BuildISO/ISO
# mkdir  images isolinux LiveOS Packages repodata
# cd ~

(4)从/mnt挂载目录下拷贝CentOS_buildTag EFI EULA GPL RPM-GPG-KEY-CentOS-7 RPM-GPG-KEY-CentOS-Testing-7 TRANS.TBL文件到~/BuildISO/ISO/目录

1
# cp -r /mnt/CentOS_BuildTag /mnt/EFI /mnt/EULA /mnt/GPL /mnt/RPM-GPG-KEY-CentOS-* /mnt/TRANS.TBL ~/BuildISO/ISO/

(5)拷贝/mnt/images/目录下的所有内容到~/BuildISO/ISO/images/,拷贝/mnt/isolinux/下的所有内容到~/BuildISO/ISO/isolinux/目录,拷贝/mnt/LiveOS/目录下所有内容到~/BuildISO/ISO/LiveOS目录中

1
2
3
# cp -r /mnt/images/* ~/BuildISO/ISO/images/
# cp -r /mnt/isolinux/* ~/BuildISO/ISO/isolinux/
# cp -r /mnt/LiveOS/* ~/BuildISO/ISO/LiveOS/

(6)拷贝/mnt/repodata/aced7d22b338fdf7c0a71ffcf32614e058f4422c42476d1f4b9e9364d567702f-c7-x86_64-comps.xml~/BuildISO/中,并重命名为comps.xml

1
# cp /mnt/repodata/aced7d22b338fdf7c0a71ffcf32614e058f4422c42476d1f4b9e9364d567702f-c7-x86_64-comps.xml ~/BuildISO/comps.xml

(7)拷/mnt/Packages/目录下的所有RPM包到~/BuildISO/all_rpms目录中

1
 cp -r /mnt/Packages/* ~/BuildISO/all_rpms/

(8)拷贝生产系统中/root/anaconda-ks.cfg~/BuildISO/isolinux/目录,并重命名为ks.cfg,并对其内容进行修改,修改后内容如下代码所示:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
#version=DEVEL
# System authorization information
auth --enableshadow --passalgo=sha512

# Install OS instead of upgrade
install

# Use CDROM installation media
cdrom

# Use text mode install
text

# Use graphical install
#graphical

# Run the Setup Agent on first boot
firstboot --disable

# Partition clearing information
ignoredisk --only-use=sda

# Keyboard layouts
keyboard --vckeymap=us --xlayouts='us'

# System language
lang en_US.UTF-8

# License agreement
eula --agreed

firewall --service=ssh
logging --level=info

# Reboot after installation
reboot

# Network information
network  --bootproto=dhcp --device=enp0s3 --onboot=off --ipv6=auto --no-activate
network  --hostname=localhost.localdomain

# Root password
rootpw --plaintext test
user --groups=wheel --name=test --password=test --gecos="test" --plaintext

# SELinux configuration
selinux --disabled
# System timezone
timezone America/New_York --isUtc
# X Window System configuration information
xconfig  --startxonboot
# System bootloader configuration
bootloader --append=" crashkernel=auto" --location=mbr --boot-drive=sda
# Clear the Master Boot Record
zerombr
autopart --type=lvm
# Partition clearing information
clearpart --all --initlabel --drives=sda

%packages
@core
@base
@development
@additional-devel
@debugging
@java-platform
@network-file-system-client
@performance
@perl-runtime
kexec-tools

%end

%addon com_redhat_kdump --enable --reserve-mb='auto'

%end

确定需要安装的软件包

通过运行~/BuildISO/utils/gather_packages.pl脚本来拷贝所有软件包:

1
# ~/BuildISO/utils/gather_packages.pl ~/BuildISO/comps.xml ~/BuildISO/all_rpms ~/BuildISO/ISO/Packages x86_64 development additional-devel debugging java-platform network-file-system-client performance perl-runtime

解决RPM依赖问题

现在已经将所有需要的组的RPM包拷贝到了~/BuildISO/ISO/Packages目录中,接下来就要检查此目录中的RPM包是否还缺少依赖的RPM包。我们可以通过脚本~/BuildISO/utils/resove_deps.pl来完成检查拷贝工作。

1
# ~/BuildISO/utils/resolve_deps.pl ~/BuildISO/all_rpms  ~/BuildISO/ISO/Packages  x86_64

现在我们已经得到了所需要的RPM包,现在需要测试一下RPM包的依赖关系

1
2
3
4
cd ~/BuildISO/ISO/Packages
mkdir /tmp/testdb
rpm --initdb --dbpath /tmp/testdb
rpm --test --dbpath /tmp/testdb -Uvh *.rpm

命令执行完,输出如下:

1
2
3
4
5
6
7
# rpm --test --dbpath /tmp/testdb -Uvh *.rpm
warning: abattis-cantarell-fonts-0.0.25-1.el7.noarch.rpm: Header V3 RSA/SHA256 Signature, key ID f4a80eb5: NOKEY
error: Failed dependencies:
	/usr/sbin/cgrulesengd is needed by cgdcbxd-1.0.2-7.el7.x86_64
	/usr/bin/fipscheck is needed by fipscheck-lib-1.4.1-6.el7.x86_64
	/usr/bin/db_stat is needed by rpm-4.11.3-35.el7.x86_64
	/usr/bin/fusermount is needed by xdg-desktop-portal-1.0.2-1.el7.x86_64

说明还缺少一些依赖,可以通过命令yum provides cgrulesengd来查找所需的RPM包:

1
2
3
4
yum provides cgrulesengd 
yum provides fipscheck 
yum provides db_stat 
yum provides fusermount

需要手动从~/BuildISO/all_rpms拷贝相应的包到目录~/BuildISO/ISO/Packages中,然后再次运行rpm --test --dbpath /tmp/testdb -Uvh *.rpm直到输出如下信息为止:

1
2
3
# rpm --test --dbpath /tmp/testdb -Uvh *.rpm
warning: abattis-cantarell-fonts-0.0.25-1.el7.noarch.rpm: Header V3 RSA/SHA256 Signature, key ID f4a80eb5: NOKEY
Preparing...                          ################################# [100%]

此外,还需拷贝如下两个软件包

1
2
# cp ~/BuildISO/all_rpms/newt-python-0.52.15-4.el7.x86_64.rpm  ~/BuildISO/ISO/Packages/
# cp ~/BuildISO/all_rpms/authconfig-6.2.8-30.el7.x86_64.rpm  ~/BuildISO/ISO/Packages/

生成RPM repository

1
2
# cd ~/BuildISO/ISO/
# createrepo -g ~/BuildISO/comps.xml .

生成ISO镜像

修改~/BuildISO/ISO/isolinux/isolinux.cfg如下

1
2
3
4
5
6
label linux
  menu label ^Install CentOS 7
  kernel vmlinuz
  #去掉quiet,增加inst.ks=cdrom:/dev/cdrom:/isolinux/ks.cfg内容
  #append initrd=initrd.img inst.stage2=hd:LABEL=CentOS\x207\x20x86_64 quiet
 append initrd=initrd.img inst.stage2=hd:LABEL=CentOS\x207\x20x86_64  inst.ks=cdrom:/dev/cdrom:/isolinux/ks.cfg

制作ISO镜像

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
mkisofs -U -r -v -T -J -joliet-long \
    -V "CentOS 7 x86_64" \
    -volset "CentOS 7 x86_64" \
    -A "CentOS 7 x86_64" \
    -input-charset utf-8 \
    -b isolinux/isolinux.bin \
    -c isolinux/boot.cat -no-emul-boot \
    -boot-load-size 4 -boot-info-table \
    -eltorito-alt-boot -e images/efiboot.img \
    -no-emul-boot -o /root/CENTOS7.6-AUTO-INSTALL-ISO.iso \
    ~/BuildISO/ISO/

测试ISO镜像

将制作好的ISO镜像用VirtualBox安装测试,确认制作的ISO能够正常运行。

定制自己的功能并制作ISO

在上面已经创建出了能够正常运行的ISO镜像,下面就是在上述ISO中添加自己的功能。

为添加自己定制的功能,我们需要使用postinstall script,即在ks.cfg中增加%post区域。

ks.cfg配置文件中,%post域的命令在anaconda安装完成后开始执行。默认情况下,%post区域的命令运行在一个chroot环境下,此时/mnt/sysimage作为/目录,这样允许用户像访问正常目录一样进行访问,例如:如果要使用/etc目录,则应该使用/etc而不是/mnt/sysimage/etc。在chroot环境下最主要的缺点是无法访问安装介质。

为了解决这个问题,这里将postinstall script分两个阶段来处理:

第一阶段

告诉anaconda不要去chroot,将需要的文件从安装介质(ISO)中拷贝到磁盘中:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
%post --nochroot

#!/bin/bash

set -x -v
exec 1> /mnt/sysimage/root/kickstart-stage1.log 2>&1

echo "==> copying files from media to install drive..."

cp -r /run/install/repo/postinstall /mnt/sysimage/root

%end

此次ISO镜像中定制安装文件放到了~/BuildISO/ISO/目录下的postinstall目录中。制作ISO镜像时的~/BuildISO/ISO/对应于安装介质的根目录,同时安装介质挂载在/run/install/repo目录下。所以~/BuildISO/ISO/postinstall可以通过/run/install/repo/postinstall获取。我们从安装介质上拷贝postinstall目录到新系统硬盘的/root/postinstall目录

第二阶段

安装定制的功能

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
%post
#!/bin/bash

set -x -v

exec 1>/root/kickstart-stage2.log 2>&1

ls -l /root/postinstall

echo "===> install test..."
%end

具体操作流程

(1)在~/BuildISO/ISO中创建postinstall目录,并在其下创建相关目录:

1
mkdir -p ~/BuildISO/ISO/postinstall/app/test

(2)将test相关RPM包上传到test目录中 (3)修改ks.cfg,通过两个%post来实现RPM包拷贝和RPM包的安装,具体如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
%post --nochroot

#!/bin/bash

set -x -v
exec 1> /mnt/sysimage/root/kickstart-stage1.log 2>&1

echo "==> copying files from media to install drive..."

cp -r /run/install/repo/postinstall /mnt/sysimage/root

%end

%post
#!/bin/bash

set -x -v

exec 1>/root/kickstart-stage2.log 2>&1

ls -l /root/postinstall

echo "===> install test..."
yum install /root/postinstall/test/test.rpm    

%end

(4)制作ISO镜像

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
mkisofs -U -r -v -T -J -joliet-long \
    -V "CentOS 7 x86_64" \
    -volset "CentOS 7 x86_64" \
    -A "CentOS 7 x86_64" \
    -input-charset utf-8 \
    -b isolinux/isolinux.bin \
    -c isolinux/boot.cat -no-emul-boot \
    -boot-load-size 4 -boot-info-table \
    -eltorito-alt-boot -e images/efiboot.img \
    -no-emul-boot -o /root/ISO-CM.iso \
    ~/BuildISO/ISO/

测试ISO镜像

安装测试ISO,并测试定制安装的功能是否能正常工作。

代码

参考文章