系统基础优化
# 系统版本
Centos8
#关闭防火墙
systemctl stop firewalld.service
systemctl disable firewalld.service
#关闭selinux
sed -i 's/^SELINUX=.*/SELINUX=disabled/g' /etc/selinux/config
setenforce 0
#无盘服务器网络环境
192.168.50.0/24
必要软件包安装
# Centos7.9必要软件包
yum install -y tftp-server xinetd dhcp syslinux-tftpboot dracut-network nfs-utils
# Centos8.3必要软件包
yum install -y tftp-server dhcp-server syslinux-tftpboot dracut-network nfs-utils
# 配置dracut-network
echo 'add_dracutmodules+="nfs"' >> /etc/dracut.conf
配置tftp服务
cat << EOF | tee /etc/xinetd.d/tftp
service tftp
{
socket_type = dgram
protocol = udp
wait = yes
user = root
server = /usr/bin/in.tftpd
server_args = -s /var/lib/tftpboot # -s 表示用/var/lib/tftpboot作为tftp服务的根目录
disable = no # 要修改成no,以便启动
per_source = 11
cps = 100 2
flags = IPv4
}
EOF
开启 tftp 服务
systemctl enable --now tftp.service
配置DHCP
cat << EOF | tee /etc/dhcp/dhcpd.conf
# 全局配置
ddns-update-style none;
ignore client-updates;
default-lease-time -1;
max-lease-time -1;
authritative;
# 设置地址范围
subnet 192.168.50.0 netmask 255.255.255.0 {
range 192.168.50.50 192.168.50.100; # 地址池范围
option routers 192.168.50.2; # 网关
option domain-name-servers 114.114.114.114; # DNS地址
option broadcast-address 192.168.50.255; # 广播地址
}
# 配置 tftp 启动文件
allow booting;
allow bootp;
class "pxeclients" {
match if substring(option vendor-class-identifier, 0, 9) = "PXEClient";
next-server 192.168.50.128;
filename "pxelinux.0";
}
# 设定客户端计算机名称并且绑定 IP 地址
host dlclient1{
option host-name "dlclient1";
hardware ethernet 00:0C:29:AF:52:BD;
fixed-address 192.168.50.51;
}
EOF
启动服务
systemctl enable --now dhcpd.service
为无盘客户端配置文件系统
配置 NFS 存储
mkdir -p /var/lib/tftpboot/centos8/root
vim /etc/exports
/var/lib/tftpboot/centos8/root 192.168.50.0/24(rw,no_root_squash)
systemctl enable --now nfs-server.service
exportfs -ra
构建无盘文件系统
yum groups -y install "Minimal Install" --releasever=8 --installroot=/var/lib/tftpboot/centos8/root/
yum -y install "lvm2" --releasever=8 --installroot=/var/lib/tftpboot/centos8/root/
yum -y install "kernel-modules-4.18.0-305.3.1.el8.x86_64" --releasever=8 --installroot=/var/lib/tftpboot/centos8/root/
cat << EOF | tee /var/lib/tftpboot/centos8/root/usr/lib/modules-load.d/boot.conf
xfs
ext4
EOF
示例
#客户节点系统添加软件
yum install -y software_name --installroot=/var/lib/tftpboot/centos8/root/ --releasever=8
#客户节点系统删除软件
yum erase -y software_name --installroot=/var/lib/tftpboot/centos8/root/ --releasever=8
为无盘客户端配置启动内核
cp /boot/vmlinuz-4.18.0-305.3.1.el8.x86_64 /var/lib/tftpboot/centos8/
# 这里也可以从 CentOS 官网下载内核 http://mirror.centos.org/centos/8/BaseOS/x86_64/os/images/pxeboot/
dracut -f --add "nfs" --add-drivers "xfs" /var/lib/tftpboot/centos8/initrd.img 4.18.0-305.3.1.el8.x86_64
chmod 644 /var/lib/tftpboot/centos8/initrd.img
为无盘客户端配置启动引导文件
mkdir /var/lib/tftpboot/pxelinux.cfg
cp /usr/share/syslinux/pxelinux.0 /var/lib/tftpboot/
vim /var/lib/tftpboot/pxelinux.cfg/default
default CentOS8
label CentOS8
kernel centos8/vmlinuz-4.18.0-305.3.1.el8.x86_64
append initrd=centos8/initrd.img root=nfs:192.168.50.128:/var/lib/tftpboot/centos8/root rw selinux=0
配置无盘系统密码
# 切换文件系统到无盘
chroot /var/lib/tftpboot/centos8/root/
# 设置无盘系统root密码
passwd root
#解决无盘命令提示符显示-bash-4.2
cp /etc/root/.bashrc /var/lib/tftpboot/centos8/root
cp /etc/root/.bash_profile /var/lib/tftpboot/centos8/root
# 退出无盘系统
exit
实际应用
Centos 7 LVM xfs文件系统修复
ls -l /dev/mapper
xfs_repair /dev/mapper/centos-root
xfs_repair -L /dev/mapper/centos-root
reboot
centos 8 救援模式挂载lvm出错
vgchange -ay
2 logical volume(s) in volume group "cl" now active
lvdisplay
--- Logical volume ---
LV Path /dev/cl/swap
LV Name swap
VG Name cl
LV UUID VXpVHT-E2B0-0rhV-dqCn-zhRd-NGtr-t5zqLe
LV Write Access read/write
LV Creation host, time dlclient1, 2021-09-24 04:29:25 +0000
LV Status available
# open 0
LV Size 2.00 GiB
Current LE 512
Segments 1
Allocation inherit
Read ahead sectors auto
- currently set to 8192
Block device 253:0
--- Logical volume ---
LV Path /dev/cl/root
LV Name root
VG Name cl
LV UUID 41BUbP-QIs1-DVOw-OCxD-9kt5-7GTC-yjA9M5
LV Write Access read/write
LV Creation host, time dlclient1, 2021-09-24 04:29:25 +0000
LV Status available
# open 1
LV Size <17.00 GiB
Current LE 4351
Segments 1
Allocation inherit
Read ahead sectors auto
- currently set to 8192
Block device 253:1
lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda 8:0 0 20G 0 disk
|-sda1 8:1 0 1G 0 part
`-sda2 8:2 0 19G 0 part
|-cl-swap 253:0 0 2G 0 lvm
`-cl-root 253:1 0 17G 0 lvm /mnt
sr0 11:0 1 7G 0 rom
xfs_repair -L /dev/cl/root # 修复xfs文件系统逻辑卷
mount /dev/cl/root /mnt
然后可以备份文件等操作
心得
# 查看 grouplist
yum grouplist
Available Environment Groups:
Server with GUI
Minimal Install
Workstation
KDE Plasma Workspaces
Virtualization Host
Custom Operating System
Installed Environment Groups:
Server
Installed Groups:
Container Management
Headless Management
Available Groups:
.NET Core Development
RPM Development Tools
Development Tools
Graphical Administration Tools
Legacy UNIX Compatibility
Network Servers
Scientific Support
Security Tools
Smart Card Support
System Tools
Fedora Packager
Xfce
# 查看内核模块
lsmod
# 查看 mod 具体信息
modinfo
# 动态加载模块
modprobe ext4
modprobe xfs
modprobe --show-depends ext4 # 显示ext4内核模块的依赖关系
--remove 移除模块
# 内核模块开机自动加载
cat > /etc/sysconfig/modules/ipvs.modules <<EOF
modinfo modulename >& dev/null
if [[ $? == 0 ]];then
modprobe -- ip_vs
modprobe -- ip_vs_rr
modprobe -- ip_vs_wrr
modprobe -- ip_vs_sh
modprobe -- nf_conntrack
fi
EOF
chmod 755 /etc/sysconfig/modules/ipvs.modules
# Systemd 内核模块自动加载
/etc/modules-load.d/*.conf 中每行写入加载的内核模块
/usr/lib/modules-load.d/*.conf 中每行写入加载的内核模块
上面两个目录下 *.conf文件的的加载需要依靠systemd-modules-load.service,内核模块需要执行权限
# 查看加载的内核模块
cut -f1 -d' ' /proc/modules | grep -e ip_vs -e nf_conntrack
# pxe diskless 系统缺少 xfs 和 ext4 文件系统支持
yum -y install "kernel-modules-4.18.0-305.3.1.el8.x86_64" --releasever=8 --installroot=/var/lib/tftpboot/centos8/root/
modporbe xfs
modprobe ext4
从无盘启动看Linux启动原理
- BIOS启动,完成自检,选择启动硬件
- 如果是磁盘系统读取MBR
- 从MBR指示,找到GRUB所在分区,加载GRUB显示菜单
- 加载Linux内核到内存中
- 执行INIT程序
- 进入用户界面
由于我需要从网络启动,过程会变得复杂一些,主要变化如下
- 在MBR引导前,需要执行一系列的PXE流程,目的是挂载iscsi磁盘。
- 在加载linux内核后,由于之前iPXE固件已经退出,还需要再次挂载iscsi磁盘。
无盘启动并不是说完全没有磁盘,只是客户端本身没有磁盘,我们需要在远端给机器提供一种文件存储和磁盘共享的方案。 我这里选择的是iscsi共享,相比于NFS和samba共享,它更底层,对系统的兼容性更好。
iSCSI利用了TCP/IP作为沟通的渠道。透过两部计算机之间利用iSCSI的协议来交换SCSI命令,让计算机可以透过高速的局域网集线来把SAN模拟成为本地的储存设备。
关于iscsi的配置不是本文重点,这里就不详细描述了,要完成iscsi磁盘的挂载需要接信息。
iscsi服务器地址:我这里是nas服务的地址192.168.3.5
target名称:这个是服务端用来区分目标的,通常一个target服务一个客户端,并关联一块共享存储,例如:iqn.2005-10.org.freenas.ctl:yong-pc.volumio
initiator名称:这个是客户端名称,用来告诉服务端谁来请求了。
BIOS和UEFI
准备工作做完,我们先来了解一下计算机的启动原理,这里就要说到BIOS和UEFI,他们是计算机按下电源后最先被执行的程序。
BIOS (Basic Input/Output System)
上个世纪70年代初,"只读内存"(read-only memory,缩写为ROM)发明,开机程序被刷入ROM芯片,计算机通电后,第一件事就是读取它。这块芯片里的程序叫做"基本输入输出系统"(Basic Input/Output System),简称为BIOS。
BIOS程序首先检查,计算机硬件能否满足运行的基本条件,这叫做"硬件自检"(Power-On Self-Test),缩写为POST。 硬件自检完成后,BIOS把控制权转交给下一阶段的启动程序。
这时,BIOS需要知道,"下一阶段的启动程序"具体存放在哪一个设备。也就是说,BIOS需要有一个外部储存设备的排序,排在前面的设备就是优先转交控制权的设备。这种排序叫做"启动顺序"(Boot Sequence)。
UEFI (Unified Extensible Firmware Interface)
不知道大家是否发现,这些年已经很难看到BIOS的身影了。
ROM的存储能力有限,BIOS能驱动的硬件类型和数量大大受限。导致大量新硬件无法在PC启动时被加载。最明显就是你无法在BIOS时使用鼠标。此外BIOS的代码历史悠久难以维护。
在2005年年中时候,包括BIOS供应商、OS供应商、系统制造商以及芯片生产公司在内的行业参与者统一建立了统一的EFI联盟(UEFI,Unified Extensible Firmware Interface)并在2006年一月发行了UEFI规范2.0。
从此你可以愉快的在PC启动初期使用鼠标,甚至像苹果一样加载网络,实现联网下载并安装操作系统。
UEFI的启动流程和BIOS的启动流程不同
- 系统开机 - 上电自检(Power On Self Test 或 POST)。
- UEFI 固件被加载,并由它初始化启动要用的硬件。
- 固件读取其引导管理器以确定从何处(比如,从哪个硬盘及分区)加载哪个 UEFI 应用。
- 固件按照引导管理器中的启动项目,加载UEFI应用。
- 已启动的 UEFI 应用还可以启动其他应用(对应于 UEFI shell 或 rEFInd之类的引导管理器的情况)或者启动内核及initramfs(对应于GRUB之类引导器的情况),这取决于 UEFI 应用的配置
PXE
上电自检完成后BIOS按照设置的启动顺序应该交棒磁盘,但是这个机器没有硬盘,也没有插入U盘,找不到任何启动设备的BIOS将控制权交给了网卡,BIOS光荣退场进入了PXE阶段。
预启动执行环境(Preboot eXecution Environment,PXE,也被称为预执行环境) 提供了一种使用网络接口启动计算机的机制。这种机制让计算机的启动可以不依赖本地数据存储设备(如硬盘)或本地已安装的操作系统。
PXE原理
- Client向 DHCP 发送IP地址请求消息,DHCP返回Client的IP地址,同时将启动文件(如:pxelinux.0)的位置信息(通常是TFTP路径)一并传送给Client
- Client向TFTP发送获取启动文件请求消息,TFTP接收到消息之后再向Client发送启动文件大小信息,试探Client是否满意,当TFTP收到Client发回的同意大小信息之后,正式向Client发送启动文件Client执行接收文件
- Client向TFTP发送针对本机的配置信息文件请求,TFTP将配置文件发回Client,继而Client根据配置文件执行后续操作。
- Client会加载启动文件,之后根据配置执行动作。这里有多重方案进行下一步操作。
可以直接通过Http协议获取Linux kernel和ramdisk然后启动
或者加载一块iscsi磁盘,将linux kernel和ramdisk等信息放在iscsi磁盘中,走正常磁盘引导。我用的是这种方案
iPXE
上面说到了启动文件,普通的pxe启动文件功能有限,通常只能从tftp服务器上获取文件,不支持HTTP协议和其他共享协议,更别说我们要支持的iscsi磁盘挂载了。这里推荐一个高端开源pxe启动文件:iPXE(https://ipxe.org/)。 它支持从HTTP、iscsi SAN、 Fibre Channel SAN、AoE SAN等多种方式启动,甚至还支持无线网卡。此外它还可以定制一个启动脚本和菜单。
iPXE需要根据自己硬件对应的平台进行编译,编译前需要搞清楚几个要点:
- 启动方式:BIOS或者EFI前面已经说了。
- 平台:X86或ARM,如果用树莓派等产品就是ARM,PC是x86
- CPU位:32或64,32位机器只支持32位固件,64位机器可以兼容32位和64位固件。注意:如果使用64位固件需要保证后续所有环节使用兼容64位的软件,我就遇到了 SysLinux不支持64位,导致卡死的问题。
使用如下命令编译
git clone git://git.ipxe.org/ipxe.git
make [platform]/[driver].[extension]
Driver:主要选择支持的网卡驱动类型,一般选ipxe(表示所有支持的网卡,但可能导致生成的启动文件过大,如果过大可以酌情选其它)
Boot type:和启动方式、启动介质有关,参考下表:
编译时添加 EMBED={脚本名称} 可以关联一个启动脚本。推荐一个大佬做好的脚本 http://boot.netboot.xyz/menu.ipxe 可以直接使用。
最终命令如下:
git clone git://git.ipxe.org/ipxe.git
cd ./ipxe/src
wget http://boot.netboot.xyz/menu.ipxe
make bin-i386-pcbios/ipxe.pxe EMBED=menu.ipxe
完成之后在/data/ipxe/src/bin-i386-pcbios/ipxe.pxe可以拿到最终的启动文件。
分区:MBR和GPT
MBR
说了这么多还是没说明白到底计算机怎么从磁盘上找到引导程序。答案是:它被固定写死在了 0柱面,0磁头,1扇区的位置通常是512byte,这个位置被称为主扇区(Master Boot Record, MBR)。
MBR主要包含如下数据:
- 主引导记录(bootloader),负责从活动分区加载并运行系统引导程序。446字节
- 硬盘分区表项(DPT——disk partition table),由四个分区表项组成,负责记录磁盘的分区情况。64字节。
- 硬盘有效标志(magic number),代表引导扇区结束,占用2字节。
Bootloader: 这部分记录了一段较小引导代码,用于去启动硬盘其他分区位置上更大的引导文件,例如linux操作系统的grub目录。
我们知道一个硬盘的每个分区的第一个扇区叫做boot sector,这个扇区存放的就是操作系统的loader。如上图,第一个分区的boot sector存放着windows的loader,第二个分区放着Linux的loader,第三个第四个由于没有安装操作系统所以空着。至于MBR的bootloader是干嘛呢, bootloader有三个功能:
- 提供选单:让用户选择进入哪个系统。
- 读取内核文件:默认启动的loader会被拷贝一份到MBR中,这样就可以直接读取内核了,图中1部分
- 转交给其他loader:图中2,3部分
Disk Partition table: 这一部分64字节大小被均分为4份,每份大小16字节,每当我们在硬盘上创建出一个新的主分区或者扩展分区时,便会占用1个16字节的大小用于记录这个分区的相关信息(例如起始和截止柱面位置、分区文件系统类型等等)。这就是为什么mbr分区模式最多只能有4个主分区的原因。
MBR的局限
- 最多只支持4个主分区,超过4个就需要使用扩展分区。
- 磁盘的最大容量只能到2.2TB
如今我家的硬盘都4T了,MBR早就不能满足需求了。你也不能怪MBR,毕竟人家1983年就提出了,比我的年纪还大。
GPT
为了解决MBR的问题,GPT分区诞生,GPT全称Globally Unique Identifier Partition Table,也叫GUID分区表,它是UEFI规范的一部分(但这并不是说它只支持UEFI,它也支持BIOS方式的引导)。
GPT分区结构如下:
- Protective MBR:GPT分区表的最前面部分也保存了和MBR相同的格式和内容称为Protective MBR,这极大的提高了GPT分区表的兼容性。
- 主GPT Header:这里记录了分区表项目数和每项目大小。
- 主GPT分区表:包含分区的类型GUID,名称,起始终止位置,该分区的GUID以及分区属性
- 实际分区
- 备份GPT分区表: 用于提高安全性,防止主GPT分区表损坏
- 备份GPT Header: 用于提高安全性,防止主GPT Header损坏
Bootloader写入
使用dd命令结合hexdump可以输出MBR信息
dd if=~/Desktop/volumio-2.799-2020-07-16-x86.img ibs=512 count=1 | hexdump -C
同样的使用dd命令可以拷贝MBR信息从img文件到物理磁盘。(之前我是分分区写入到磁盘的,导致MBR信息丢失无法引导)
dd if=~/Desktop/volumio-2.799-2020-07-16-x86.img ibs=512 count=1 of=/dev/sda
也可以使用下载的syslinux中的mbr.bin写入
dd bs=440 count=1 conv=notrunc if=/usr/lib/syslinux/bios/mbr.bin of=/dev/sda //MBR分区表
dd bs=440 count=1 conv=notrunc if=/usr/lib/syslinux/bios/gptmbr.bin of=/dev/sda //GPT分区表
内核:vmlinuz和initrd
引导加载程序交棒之后系统进入内核引导阶段。这一步会在内存中运行系统内核和根文件系统。之后根目录下的init shell会被调用执行,完成进一步的初始化操作。
vmlinuz和initrd
vmlinuz是可引导的、压缩的内核。“vm”代表“Virtual Memory”。Linux能够使用硬盘空间作为虚拟内存,因此得名“vm”。vmlinuz是可执行的Linux内核。
initrd是“initial ramdisk”的简写。initrd一般被用来临时的引导硬件到实际内核vmlinuz能够接管并继续引导的状态。initrd 字面上的意思就是"boot loader initialized RAM disk",换言之,这是一块特殊的RAM disk,在载入Linux kernel前,由boot loader予以初始化,启动过程会优先执行initrd的init程序,initrd完成阶段性目标后,kernel 会挂载真正的root file system ,并执行/sbin/init程序。
- vmlinuz指的是内核,作用:进程管理、内存管理、文件管理、驱动管理、网络管理。
- initrd.img是一个小的映象, 放的是和启动相关的驱动模块。通常的步骤是先启动内核,然后内核挂载initrd.img,并执行里面的脚本来进一步挂载各种各样的模块。其中最重要的就是根文件系统驱动模块,有了它才能挂载根文件系统,继而运行用户空间的第一个应用程序init或者systemd,完成系统后续的启动
参考
https://blog.csdn.net/qq_41938046/article/details/118417901
http://hmli.ustc.edu.cn/doc/linux/centos7.6-diskless/