PXE系列文章(12)- 构建内存 OS (基于 CentOS)
在前面, 我们已经使用 debootstrap
构建基于Ubuntu的内存OS, 但是业界常用的更多的是CentOS,所以一直在尝试使用CentOS来构建内存OS.
CentOS 7 root filesystem on tmpfs这篇文章中的方案可行, 我们不使用的原因是流程构建太长, 外部依赖太多,冗余的内容太多,也不够精简.
所以我们希望尝试的方案是类似 Ubuntu
的 debootstrap
的工具. yum
本身是可以将对应包安装到指定目录,直到看到下面这篇日本同行写的文章,让这个过程更加清晰了.
宿主环境中,我们需要有 yum
rpm
等工具命令的支持,在各个发行版中均可以安装这两个包, 当然宿主机器本身就是CentOS那就不需要在独立安装了.
- ubuntu
apt -y install yum
- gentoo
USE="python lua" emerge yum rpm
定位 centos-release
包在远程仓库中的位置, 我们这里使用 CentOS 7, 架构选择 x86_64, 镜像源地址我们选择清华大学的公开镜像站, 如果更好的选择也可以选择其他镜像站, 比如网易的 <mirrors.163.com>.
https://mirrors.tuna.tsinghua.edu.cn/centos/7/os/x86_64/Packages/centos-release-7-6.1810.2.el7.centos.x86_64.rpm
接下来准备下工作根目录, 我这里选择 $HOME/work/chroot
作为我们的工作环境
mkdir -p $HOME/work/chroot/var/lib/rpm
初始化rpm的工作环境以及目标系统安装 centos-release
包
rpm --root $HOME/work/chroot/ --initdb
rpm -ivh --nodeps --root $HOME/work/chroot/ https://mirrors.tuna.tsinghua.edu.cn/centos/7/os/x86_64/Packages/centos-release-7-6.1810.2.el7.centos.x86_64.rpm
目标系统安装yum工具
yum --nogpgcheck --installroot $HOME/work/chroot -y install yum
日本同行在介绍的过程中, 在这里忽略了一个细节, 需要将宿主环境的 /dev
绑定到目标系统的 /dev
目录下
mount -o bind /dev $HOME/work/chroot/dev
如果不执行上述绑定,将导致chroot后无法执行yum命令, 错误提示信息如下:
error: Failed to initialize NSS library
There was a problem importing one of the Python modules
required to run yum. The error leading to this problem was:
cannot import name ts
Please install a package which provides this module, or
verify that the module is installed correctly.
It's possible that the above module doesn't match the
current version of Python, which is:
2.7.5 (default, Jun 20 2019, 20:27:34)
[GCC 4.8.5 20150623 (Red Hat 4.8.5-36)]
If you cannot solve this problem yourself, please go to
the yum faq at:
http://yum.baseurl.org/wiki/Faq
紧接着安装内核:
yum --nogpgcheck --installroot $HOME/work/chroot -y install kernel
安装必要的工具集:
yum --nogpgcheck --installroot $HOME/work/chroot -y install @core
在真正chroot到目标目录之前,我们还需要配置下目标系统的 DNS
信息, 直接将宿主环境的 /etc/resolv.conf
文件拷贝到 $HOME/work/chroot/etc/
cp /etc/resolv.conf $HOME/work/chroot/etc/
到这里,我们就可以直接切换到目标系统中工作啦
chroot $HOME/work/chroot
紧接着执行一次 yum
验证下环境执行是否成功?
(virtualenv) root@server:/# yum
Loaded plugins: fastestmirror
You need to give some command
Usage: yum [options] COMMAND
List of Commands:
check Check for problems in the rpmdb
check-update Check for available package updates
clean Remove cached data
deplist List a package's dependencies
distribution-synchronization Synchronize installed packages to the latest available versions
downgrade downgrade a package
erase Remove a package or packages from your system
fs Acts on the filesystem data of the host, mainly for removing docs/lanuages for minimal hosts.
fssnapshot Creates filesystem snapshots, or lists/deletes current snapshots.
groups Display, or use, the groups information
help Display a helpful usage message
history Display, or use, the transaction history
info Display details about a package or group of packages
install Install a package or packages on your system
list List a package or groups of packages
load-transaction load a saved transaction from filename
makecache Generate the metadata cache
provides Find what package provides the given value
reinstall reinstall a package
repo-pkgs Treat a repo. as a group of packages, so we can install/remove all of them
repolist Display the configured software repositories
search Search package details for the given string
shell Run an interactive yum shell
swap Simple way to swap packages, instead of using shell
update Update a package or packages on your system
update-minimal Works like upgrade, but goes to the 'newest' package match which fixes a problem that affects your system
updateinfo Acts on repository update information
upgrade Update packages taking obsoletes into account
version Display a version for the machine and/or available repos.
我们在任何其他操作前需要将系统整体更新到最新, 执行 yum -y update
.
yum -y update
激活系统环境信息
source /etc/profile
基础系统初始化完成之后,清理一下不必要的数据文件
yum clean all
到此, 我们目标系统的根盘内容就构建完成了,删掉之前配置的 /etc/resolv.conf
文件, 剩下的内容就和之前构建基于 Ubuntu
的内存镜像的操作流程一样, 退出 chroot
环境.
根盘文件系统好了之后, 需要将其压缩打包:
cd ~/work/chroot
time tar -cf - . | xz -v --threads=24 > ~/work/initramfs/rootfs.tar.xz
接下来我们需要下载 busybox
来作为执行环境, 减少 init 脚本的编写成本
wget -O ~/work/initramfs/bin/busybox https://busybox.net/downloads/binaries/1.21.1/busybox-x86_64
编写 init 文件内容(这里可以可以参考各个发行版本的 iso 中的 init 工具的编写方式, 大同小异)
vim ~/work/initramfs/init
~/work/initramfs/init文件的内容如下:
#!/bin/busybox sh
# Dump to sh if something fails
error() {
echo "Jumping into the shell..."
setsid cttyhack sh
}
# Populate /bin with binaries from busybox
/bin/busybox --install /bin
mkdir -p /proc
mount -t proc proc /proc
mkdir -p /sys
mount -t sysfs sysfs /sys
mkdir -p /sys/dev
mkdir -p /var/run
mkdir -p /dev
mkdir -p /dev/pts
mount -t devpts devpts /dev/pts
# Populate /dev
echo /bin/mdev > /proc/sys/kernel/hotplug
mdev -s
echo "mount rootfs... "
mkdir -p /newroot
mount -t tmpfs -o size=80% tmpfs /newroot || error
xz -d -c -f rootfs.tar.xz | tar -x -f - -C /newroot || error
mount --move /sys /newroot/sys
mount --move /proc /newroot/proc
mount --move /dev /newroot/dev
exec switch_root /newroot /sbin/init || error
到此整个 initramfs 的内容,我们就构建完成了.最终需要输出为cpio文档格式.
cd ~/work/initramfs
find . -print0 | cpio --null -ov --format=newc | gzip -9 > ~/work/build/initramfs.gz
最终生成的 initramfs 文件为 ~/work/build/initramfs.gz
, 将其拷贝到 PXE Server 的 /var/lib/tftpboot/ubuntu-installer/amd64/
, 接下来你就可以去我们的 PXE 环境调试下, 将 PXE Server 的 `/var/lib/tftpboot/ubuntu-installer/amd64/boot-screens/txt.cfg 中的内容调整为如下:
default install
label install
menu label ^Automatically Install Ubuntu 16.04
kernel ubuntu-installer/amd64/linux
append vga=788 initrd=ubuntu-installer/amd64/initramfs.gz
然后启动一下 PXE Client 虚拟机, 看看是否启动了一个完整的 OS.