构建BootOS系统

简介

  • 构建BootOS系统,基于内存的操作系统,可以通过PXE引导。
  • BootOS系统在内存中运行,不依赖磁盘设备,可以直接对硬件进行操作,升级BIOS,修改RAID,配置OOB,以及对磁盘分区和创建文件系统等。
  • BootOS系统允许内置Agent,与Server建立通讯,采集硬件信息,上报给Server端。

制作方法

squashfs

  • Ubuntu官方ISO中获取filesystem.squashfs并释放initramfs:
1
2
3
4
5
6
7
8
9
# 此处基于Ubuntu 19.10
mkdir -p /mnt/initramfs-eoan/{iso,output}
wget http://mirrors.ustc.edu.cn/ubuntu-releases/eoan/ubuntu-19.10-live-server-amd64.iso
mount -o loop /mnt/ubuntu-19.10-live-server-amd64.iso /mnt/initramfs-eoan/iso/

cd /mnt/initramfs-eoan
cp -a /mnt/initramfs-eoan/iso/casper/filesystem.squashfs /mnt/initramfs-eoan/
unsquashfs filesystem.squashfs
mv -f squashfs-root initramfs
  • 挂载设备:
1
2
mount --bind /dev initramfs/dev
mount --bind /run initramfs/run
  • 编辑initramfs
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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
chroot initramfs

mount none -t proc /proc
mount none -t sysfs /sys
mount none -t devpts /dev/pts
export HOME=/root
export LC_ALL=C

# resolv.conf
rm -f /etc/resolv.conf
echo "nameserver 114.114.114.114" >> /etc/resolv.conf

echo "deb http://mirrors.ustc.edu.cn/ubuntu/ eoan main restricted universe multiverse" > /etc/apt/sources.list
echo "deb http://mirrors.ustc.edu.cn/ubuntu/ eoan-security main restricted universe multiverse" >> /etc/apt/sources.list
echo "deb http://mirrors.ustc.edu.cn/ubuntu/ eoan-updates main restricted universe multiverse" >> /etc/apt/sources.list
echo "deb http://mirrors.ustc.edu.cn/ubuntu/ eoan-backports main restricted universe multiverse" >> /etc/apt/sources.list

# Disable Service
systemctl disable apt-daily.timer
systemctl disable apt-daily-upgrade.timer
systemctl disable apt-daily.service
systemctl disable apt-daily-upgrade.service

# Stop Service
systemctl stop apt-daily.timer
systemctl stop apt-daily-upgrade.timer
systemctl stop apt-daily.service
systemctl stop apt-daily-upgrade.service

# Uninstall Packages
apt purge -y ufw snapd apparmor cloud-init cloud-guest-utils git git-man pollinate && apt autoremove -y

# Upgrade System
apt update && apt dist-upgrade -y

# Disable installation of recommended packages
echo 'APT::Install-Recommends "false";' > /etc/apt/apt.conf.d/00-DisableInstallRecommends

apt install -y bash-completion ifupdown kmod vim ipmitool python3-distutils openssh-server

# vmlinuz
KERNEL_VERSION=$(apt-cache madison linux-image-generic | head -1 | awk '{print $3}' | awk -F '.' '{print $1"."$2"."$3"-"$4}')
apt download linux-image-${KERNEL_VERSION}-generic
dpkg -x $(find . -type f -name "linux-image-*.deb" | head -n 1) linux-image-${KERNEL_VERSION}
cp -af linux-image-${KERNEL_VERSION}/boot/vmlinuz-${KERNEL_VERSION}-generic /vmlinuz
chmod +r /vmlinuz
rm -rf linux-image-*

# 至关重要: 安装对应内核版本的 modules, 不然无网络接口
apt install -y $(apt search linux-modules | egrep -o "linux-modules-${KERNEL_VERSION}-generic")

# Set root password
echo "root:root" | chpasswd

# Set hostname
echo "BootOS" > /etc/hostname

# Set interfaces
echo "auto lo" > /etc/network/interfaces
echo "iface lo inet loopback" >> /etc/network/interfaces
echo "" >> /etc/network/interfaces
echo "auto eth0" >> /etc/network/interfaces
echo "iface eth0 inet dhcp" >> /etc/network/interfaces

# Set OpenSSH
sed -i '/pam_motd.so/d' /etc/pam.d/sshd
sed -i '/pam_mail.so/d' /etc/pam.d/sshd
echo "UseDNS no" >> /etc/ssh/sshd_config
echo "PermitRootLogin yes" >> /etc/ssh/sshd_config
echo " StrictHostKeyChecking no" >> /etc/ssh/ssh_config
echo " UserKnownHostsFile /dev/null" >> /etc/ssh/ssh_config

# Add Cron
crontab -e

SHELL=/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
* * * * * for i in $(seq 4); do /opt/agent.sh >/opt/agent.log 2>&1 && sleep 15; done

wget https://github.com/pypa/setuptools/archive/v46.0.0.tar.gz -O setuptools-46.0.0.tar.gz
tar -zxvf setuptools-46.0.0.tar.gz
cd setuptools-46.0.0/
python3 bootstrap.py
python3 setup.py build
python3 setup.py install
cd /root/
rm -rf setuptools-*

# PIP
wget -q https://bootstrap.pypa.io/get-pip.py && python3 get-pip.py && rm -f get-pip.py
pip3 install request

apt clean && apt autoclean && apt autoremove -y
rm -f /etc/resolv.conf

umount /proc
umount /sys
umount /dev/pts
export HISTSIZE=0
exit
1
2
umount initramfs/dev
umount initramfs/run
  • 添加init文件:
1
vim initramfs/init
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
#!/bin/sh

mount -t sysfs -o nodev,noexec,nosuid sysfs /sys
mount -t proc -o nodev,noexec,nosuid proc /proc
# Some things don't work properly without /etc/mtab.
ln -sf /proc/mounts /etc/mtab

mount -t devtmpfs -o mode=0755 udev /dev
if [ $? -ne 0 ]; then
mount -t tmpfs -o size=64k,mode=0755 tmpfs /dev
[ -e /dev/console ] || mknod -m 0600 /dev/console c 5 1
[ -e /dev/null ] || mknod /dev/null c 1 3
fi

mkdir /dev/pts
mount -t devpts -o noexec,nosuid,gid=5,mode=0620 devpts /dev/pts || true
mount -t tmpfs -o "noexec,nosuid,size=10%,mode=0755" tmpfs /run
mkdir /run/initramfs
# compatibility symlink for the pre-oneiric locations
ln -s /run/initramfs /dev/.initramfs

# Set modprobe env
export MODPROBE_OPTIONS="-qb"
find /sys/devices -name modalias | xargs -r cat | xargs -r modprobe -qa

# mdadm needs hostname to be set. This has to be done before the udev rules are called!
if [ -f "/etc/hostname" ]; then
/bin/hostname -b -F /etc/hostname 2>&1 1>/dev/null
fi

# Read the parameters of APPEND in pxelinux.cfg
if [[ -n "${SERVER_ADDR}" ]]; then
echo "${SERVER_ADDR}" > /opt/SERVER_ADDR
fi

exec /sbin/init
1
chmod +x initramfs/init
  • 添加agent.sh脚本:
1
vim initramfs/opt/agent.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#!/usr/bin/env bash

if [[ ! -f /etc/resolv.conf ]]; then
DHCLIENT_LEASES_FILE="/var/lib/dhcp/dhclient.eth0.leases"
DNS_SERVER=$(cat ${DHCLIENT_LEASES_FILE} | grep domain-name-servers | head -1 | awk '{print $3}' | sed 's/.$//')
if [[ -z ${DNS_SERVER} ]]; then
exit 1
fi
echo "nameserver ${DNS_SERVER}" > /etc/resolv.conf
fi

AGENT_FILE="/opt/agent.py"
SERVER_ADDR=$(cat /opt/SERVER_ADDR)

if [[ ! -f ${AGENT_FILE} ]] && [[ -n ${SERVER_ADDR} ]]; then
wget ${SERVER_ADDR}/bootos/agent.py -O ${AGENT_FILE}
chmod +x ${AGENT_FILE}
fi

# Auto Exec ${AGENT_FILE}
exec ${AGENT_FILE}
1
chmod +x initramfs/opt/agent.sh
  • 清理垃圾文件:
1
2
3
4
5
6
7
rm -rf initramfs/usr/share/locale/*
rm -rf initramfs/usr/share/man/*
rm -rf initramfs/usr/share/doc/*
rm -rf initramfs/var/log/*
rm -rf initramfs/var/lib/apt/lists/*
rm -rf initramfs/var/cache/*
rm -rf initramfs/root/.bash_history
  • 制作initramfs.gz:
1
2
3
cd initramfs/
mv -f vmlinuz ../output/
find . | cpio -o -H newc | gzip -9 > ../output/initramfs.gz
  • vmlinuzinitramfs.gz拷贝到服务端的/var/www/bootos/中。

使用方法

  • 添加配置文件:
1
vim /var/lib/tftpboot/pxelinux.cfg/default
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
MENU HSHIFT 0
MENU WIDTH 82
MENU TITLE Welcome to Custom PXE Server
MENU BACKGROUND splash.png
MENU COLOR border 0 #ffffffff #00000000
MENU COLOR sel 7 #ffffffff #ff000000
MENU COLOR title 0 #ffffffff #00000000
MENU COLOR tabmsg 0 #ffffffff #00000000
MENU COLOR unsel 0 #ffffffff #00000000
MENU COLOR hotsel 0 #ff000000 #ffffffff
MENU COLOR hotkey 7 #ffffffff #ff000000
MENU COLOR scrollbar 0 #ffffffff #00000000

DEFAULT BootOS

LABEL BootOS
MENU LABEL ^BootOS
MENU DEFAULT
KERNEL http://xiaocoder.com/bootos/vmlinuz
INITRD http://xiaocoder.com/bootos/initramfs.gz
APPEND biosdevname=0 net.ifnames=0 SERVER_ADDR=http://xiaocoder.com
IPAPPEND 2

MENU CLEAR

UI vesamenu.c32
PROMPT 0
TIMEOUT 50
  • 参数说明:
    • UI vesamenu.c32: 定义使用UI模块
      • vesamenu.c32menu.c32显示更加友好。
      • 依赖libutil.c32libcom32.c32模块。
    • TIMEOUT 50: 网络启动以后默认等待5秒钟自动进入BootOS系统。
    • DEFAULT: 默认启动的LABEL
    • 使用http方式加载BootOS,取代了传统的tftp加载方式,提高大文件加载效率。
    • 增加了biosdevname=0 net.ifnames=0参数,关闭了网卡自动命名的功能,使用ethX的命名规范。
    • SERVER_ADDR: 设置Server的地址,会自动下载/bootos/agent.py文件。
    • IPAPPEND 2: 当服务器有多个网络接口时,增加此参数,可以默认使用PXE启动的网卡作为eth0

请作者喝瓶肥宅快乐水