如何構建一台網路引導伺服器(一)
有些計算機網路需要在各個物理機器上維護相同的軟體和配置。學校的計算機實驗室就是這樣的一個環境。 網路引導 伺服器能夠被配置為基於網路去提供一個完整的操作系統,以便於客戶端計算機從一個中央位置獲取配置。本教程將向你展示構建一台網路引導伺服器的一種方法。
本教程的第一部分將包括創建一台網路引導伺服器和鏡像。第二部分將展示如何去添加 Kerberos 驗證的家目錄到網路引導配置中。
初始化配置
首先去下載 Fedora 伺服器的 netinst 鏡像,將它刻錄到一張光碟上,然後用它引導伺服器來重新格式化。我們只需要一個典型的 Fedora Server 的「最小化安裝」來作為我們的開端,安裝完成後,我們可以使用命令行去添加我們需要的任何額外的包。
注意:本教程中我們將使用 Fedora 28。其它版本在「最小化安裝」中包含的包可能略有不同。如果你使用的是不同的 Fedora 版本,如果一個預期的文件或命令不可用,你可能需要做一些調試。
最小化安裝的 Fedora Server 運行起來之後,以 root 用戶登入:
$ sudo -i
並設置主機名字:
$ MY_HOSTNAME=server-01.example.edu
$ hostnamectl set-hostname $MY_HOSTNAME
注意:Red Hat 建議靜態和臨時名字應都要與這個機器在 DNS 中的完全合格域名相匹配,比如 host.example.com(了解主機名字)。
注意:本指南為了方便「複製粘貼」。需要自定義的任何值都聲明為一個
MY_*
變數,在你運行剩餘命令之前,你可能需要調整它。如果你註銷之後,變數的賦值將被清除。注意:Fedora 28 Server 在默認情況下往往會轉儲大量的日誌到控制台上。你可以通過運行命令:
sysctl -w kernel.printk=0
去禁用控制台日誌輸出。
接下來,我們需要在我們的伺服器上配置一個靜態網路地址。運行下面的一系列命令將找到並重新配置你的默認網路連接:
$ MY_DNS1=192.0.2.91
$ MY_DNS2=192.0.2.92
$ MY_IP=192.0.2.158
$ MY_PREFIX=24
$ MY_GATEWAY=192.0.2.254
$ DEFAULT_DEV=$(ip route show default | awk '{print $5}')
$ DEFAULT_CON=$(nmcli d show $DEFAULT_DEV | sed -n '/^GENERAL.CONNECTION:/s!.*:s*!! p')
$ nohup bash << END
nmcli con mod "$DEFAULT_CON" connection.id "$DEFAULT_DEV"
nmcli con mod "$DEFAULT_DEV" connection.interface-name "$DEFAULT_DEV"
nmcli con mod "$DEFAULT_DEV" ipv4.method disabled
nmcli con up "$DEFAULT_DEV"
nmcli con add con-name br0 ifname br0 type bridge
nmcli con mod br0 bridge.stp no
nmcli con mod br0 ipv4.dns $MY_DNS1,$MY_DNS2
nmcli con mod br0 ipv4.addresses $MY_IP/$MY_PREFIX
nmcli con mod br0 ipv4.gateway $MY_GATEWAY
nmcli con mod br0 ipv4.method manual
nmcli con up br0
nmcli con add con-name br0-slave0 ifname "$DEFAULT_DEV" type bridge-slave master br0
nmcli con up br0-slave0
END
注意:上面最後的一組命令被封裝到一個
nohup
腳本中,因為它將臨時禁用網路。這個nohup
命令可以讓nmcli
命令運行完成,即使你的 SSH 連接斷開。注意,連接恢復可能需要 10 秒左右的時間,如果你改變了伺服器 IP 地址,你將需要重新啟動一個新的 SSH 連接。注意:上面的網路配置在默認的連接之上創建了一個 網橋,這樣我們在後面的測試中就可以直接運行一個虛擬機實例。如果你不想在這台伺服器上去直接測試網路引導鏡像,你可以跳過創建網橋的命令,並直接在你的默認網路連接上配置靜態 IP 地址。
安裝和配置 NFS4
從安裝 nfs-utils 包開始:
$ dnf install -y nfs-utils
為發布 NFS 去創建一個頂級的 偽文件系統,然後在你的網路上共享它:
$ MY_SUBNET=192.0.2.0
$ mkdir /export
$ echo "/export -fsid=0,ro,sec=sys,root_squash $MY_SUBNET/$MY_PREFIX" > /etc/exports
SELinux 會干擾網路引導伺服器的運行。為它配置例外規則超出了本教程中,因此我們這裡直接禁用它:
$ sed -i '/GRUB_CMDLINE_LINUX/s/"$/ audit=0 selinux=0"/' /etc/default/grub
$ grub2-mkconfig -o /boot/grub2/grub.cfg
$ sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/sysconfig/selinux
$ setenforce 0
注意:應該不需要編輯 grub 命令行,但我們在測試過程中發現,直接編輯
/etc/sysconfig/selinux
被證明重啟後是無效的,因此這樣做再次確保設置了selinux=0
標誌。
現在,在本地防火牆中為 NFS 服務添加一個例外規則,然後啟動 NFS 服務:
$ firewall-cmd --add-service nfs
$ firewall-cmd --runtime-to-permanent
$ systemctl enable nfs-server.service
$ systemctl start nfs-server.service
創建網路引導鏡像
現在我們的 NFS 伺服器已經啟動運行了,我們需要為它提供一個操作系統鏡像,以便於它提供給客戶端計算機。我們將從一個非常小的鏡像開始,等一切順利之後再添加。
首先,創建一個存放我們鏡像的新目錄:
$ mkdir /fc28
使用 dnf
命令在新目錄下用幾個基礎包去構建鏡像:
$ dnf -y --releasever=28 --installroot=/fc28 install fedora-release systemd passwd rootfiles sudo dracut dracut-network nfs-utils vim-minimal dnf
在上面的命令中省略了很重要的 kernel
包。在它們被安裝完成之前,我們需要去調整一下 initramfs
鏡像中包含的驅動程序集,kernel
首次安裝時將自動構建這個鏡像。尤其是,我們需要禁用 hostonly
模式,以便於 initramfs
鏡像能夠在各種硬體平台上正常工作,並且我們還需要添加對網路和 NFS 的支持:
$ echo 'hostonly=no' > /fc28/etc/dracut.conf.d/hostonly.conf
$ echo 'add_dracutmodules+=" network nfs "' > /fc28/etc/dracut.conf.d/netboot.conf
現在,安裝 kernel
包:
$ dnf -y --installroot=/fc28 install kernel
設置一個阻止 kernel
包被更新的規則:
$ echo 'exclude=kernel-*' >> /fc28/etc/dnf/dnf.conf
設置 locale:
$ echo 'LANG="en_US.UTF-8"' > /fc28/etc/locale.conf
注意:如果 locale 沒有正確配置,一些程序(如 GNOME Terminal)將無法正常工作。
設置客戶端的主機名字:
$ MY_CLIENT_HOSTNAME=client-01.example.edu
$ echo $MY_CLIENT_HOSTNAME > /fc28/etc/hostname
禁用控制台日誌輸出:
$ echo 'kernel.printk = 0 4 1 7' > /fc28/etc/sysctl.d/00-printk.conf
定義網路引導鏡像中的本地 liveuser
用戶:
$ echo 'liveuser:x:1000:1000::/home/liveuser:/bin/bash' >> /fc28/etc/passwd
$ echo 'liveuser::::::::' >> /fc28/etc/shadow
$ echo 'liveuser:x:1000:' >> /fc28/etc/group
$ echo 'liveuser:!::' >> /fc28/etc/gshadow
允許 liveuser
使用 sudo
:
$ echo 'liveuser ALL=(ALL) NOPASSWD: ALL' > /fc28/etc/sudoers.d/liveuser
啟用自動創建家目錄:
$ dnf install -y --installroot=/fc28 authselect oddjob-mkhomedir
$ echo 'dirs /home' > /fc28/etc/rwtab.d/home
$ chroot /fc28 authselect select sssd with-mkhomedir --force
$ chroot /fc28 systemctl enable oddjobd.service
由於多個客戶端將會同時掛載我們的鏡像,我們需要去配置鏡像工作在只讀模式中:
$ sed -i 's/^READONLY=no$/READONLY=yes/' /fc28/etc/sysconfig/readonly-root
配置日誌輸出到內存而不是持久存儲中:
$ sed -i 's/^#Storage=auto$/Storage=volatile/' /fc28/etc/systemd/journald.conf
配置 DNS:
$ MY_DNS1=192.0.2.91
$ MY_DNS2=192.0.2.92
$ cat << END > /fc28/etc/resolv.conf
nameserver $MY_DNS1
nameserver $MY_DNS2
END
繞開編寫本教程時存在的根目錄只讀掛載的 bug(BZ1542567):
$ echo 'dirs /var/lib/gssproxy' > /fc28/etc/rwtab.d/gssproxy
$ cat << END > /fc28/etc/rwtab.d/systemd
dirs /var/lib/systemd/catalog
dirs /var/lib/systemd/coredump
END
最後,為我們鏡像創建 NFS 文件系統,並將它共享到我們的子網中:
$ mkdir /export/fc28
$ echo '/fc28 /export/fc28 none bind 0 0' >> /etc/fstab
$ mount /export/fc28
$ echo "/export/fc28 -ro,sec=sys,no_root_squash $MY_SUBNET/$MY_PREFIX" > /etc/exports.d/fc28.exports
$ exportfs -vr
創建引導載入器
現在,我們已經有了可以進行網路引導的操作系統,我們需要一個引導載入器去從客戶端系統上啟動它。在本教程中我們使用的是 iPXE。
注意:本節和接下來的節使用 QEMU 測試,也能在另外一台單獨的計算機上來完成;它們並不需要在網路引導伺服器上來運行。
安裝 git
並使用它去下載 iPXE:
$ dnf install -y git
$ git clone http://git.ipxe.org/ipxe.git $HOME/ipxe
現在我們需要去為我們的引導載入器創建一個指定的啟動腳本:
$ cat << 'END' > $HOME/ipxe/init.ipxe
#!ipxe
prompt --key 0x02 --timeout 2000 Press Ctrl-B for the iPXE command line... && shell ||
dhcp || exit
set prefix file:///linux
chain ${prefix}/boot.cfg || exit
END
啟動 「file」 下載協議:
$ echo '#define DOWNLOAD_PROTO_FILE' > $HOME/ipxe/src/config/local/general.h
安裝 C 編譯器以及相關的工具和庫:
$ dnf groupinstall -y "C Development Tools and Libraries"
構建引導載入器:
$ cd $HOME/ipxe/src
$ make clean
$ make bin-x86_64-efi/ipxe.efi EMBED=../init.ipxe
記下新編譯的引導載入器的存儲位置。我們將在接下來的節中用到它:
$ IPXE_FILE="$HOME/ipxe/src/bin-x86_64-efi/ipxe.efi"
用 QEMU 測試
這一節是可選的,但是你需要去複製下面顯示在物理機器上的 EFI 系統分區 的布局,在網路引導時需要去配置它們。
注意:如果你想實現一個完全的無盤系統,你也可以複製那個文件到一個 TFTP 伺服器,然後從 DHCP 上指向那台伺服器。
為了使用 QEMU 去測試我們的引導載入器,我們繼續去創建一個僅包含一個 EFI 系統分區和我們的啟動文件的、很小的磁碟鏡像。
從創建 EFI 系統分區所需要的目錄布局開始,然後把我們在前面節中創建的引導載入器複製進去:
$ mkdir -p $HOME/esp/efi/boot
$ mkdir $HOME/esp/linux
$ cp $IPXE_FILE $HOME/esp/efi/boot/bootx64.efi
下面的命令將識別我們的引導載入器鏡像正在使用的內核版本,並將它保存到一個變數中,以備後續的配置命令去使用它:
$ DEFAULT_VER=$(ls -c /fc28/lib/modules | head -n 1)
定義我們的客戶端計算機將使用的引導配置:
$ MY_DNS1=192.0.2.91
$ MY_DNS2=192.0.2.92
$ MY_NFS4=server-01.example.edu
$ cat << END > $HOME/esp/linux/boot.cfg
#!ipxe
kernel --name kernel.efi ${prefix}/vmlinuz-$DEFAULT_VER initrd=initrd.img ro ip=dhcp rd.peerdns=0 nameserver=$MY_DNS1 nameserver=$MY_DNS2 root=nfs4:$MY_NFS4:/fc28 console=tty0 console=ttyS0,115200n8 audit=0 selinux=0 quiet
initrd --name initrd.img ${prefix}/initramfs-$DEFAULT_VER.img
boot || exit
END
注意:上面的引導腳本展示了如何使用 iPXE 去網路引導 Linux 的最小示例。還可以做更多更複雜的配置。值得注意的是,iPXE 支持互動式引導菜單,它可以讓你配置默認選項和超時時間。比如,一個更高級一點 iPXE 腳本可以默認從本地磁碟引導一個操作系統,如果在倒計時結束之前用戶按下了一個鍵,才會去網路引導一個操作系統。
複製 Linux 內核並分配 initramfs 給 EFI 系統分區:
$ cp $(find /fc28/lib/modules -maxdepth 2 -name 'vmlinuz' | grep -m 1 $DEFAULT_VER) $HOME/esp/linux/vmlinuz-$DEFAULT_VER
$ cp $(find /fc28/boot -name 'init*' | grep -m 1 $DEFAULT_VER) $HOME/esp/linux/initramfs-$DEFAULT_VER.img
我們最終的目錄布局應該看起來像下面的樣子:
esp
├── efi
│ └── boot
│ └── bootx64.efi
└── linux
├── boot.cfg
├── initramfs-4.18.18-200.fc28.x86_64.img
└── vmlinuz-4.18.18-200.fc28.x86_64
要讓 QEMU 去使用我們的 EFI 系統分區,我們需要去創建一個小的 uefi.img
磁碟鏡像來包含它,然後將它連接到 QEMU 作為主引導驅動器。
開始安裝必需的工具:
$ dnf install -y parted dosfstools
現在創建 uefi.img
文件,並將 esp
目錄中的文件複製進去:
$ ESP_SIZE=$(du -ks $HOME/esp | cut -f 1)
$ dd if=/dev/zero of=$HOME/uefi.img count=$((${ESP_SIZE}+5000)) bs=1KiB
$ UEFI_DEV=$(losetup --show -f $HOME/uefi.img)
$ parted ${UEFI_DEV} -s mklabel gpt mkpart EFI FAT16 1MiB 100% toggle 1 boot
$ mkfs -t msdos ${UEFI_DEV}p1
$ mkdir -p $HOME/mnt
$ mount ${UEFI_DEV}p1 $HOME/mnt
$ cp -r $HOME/esp/* $HOME/mnt
$ umount $HOME/mnt
$ losetup -d ${UEFI_DEV}
注意:在物理計算機上,你只需要從
esp
目錄中複製文件到計算機上已存在的 EFI 系統分區中。你不需要使用uefi.img
文件去引導物理計算機。注意:在一個物理計算機上,如果文件名已存在,你可以重命名
bootx64.efi
文件,如果你重命名了它,就需要去編輯計算機的 BIOS 設置,並添加重命令後的 efi 文件到引導列表中。
接下來我們需要去安裝 qemu 包:
$ dnf install -y qemu-system-x86
允許 QEMU 訪問我們在本教程「初始化配置」一節中創建的網橋:
$ echo 'allow br0' > /etc/qemu/bridge.conf
創建一個 OVMF_VARS.fd
鏡像的副本去保存我們虛擬機的持久 BIOS 配置:
$ cp /usr/share/edk2/ovmf/OVMF_VARS.fd $HOME
現在,啟動虛擬機:
$ qemu-system-x86_64 -machine accel=kvm -nographic -m 1024 -drive if=pflash,format=raw,unit=0,file=/usr/share/edk2/ovmf/OVMF_CODE.fd,readonly=on -drive if=pflash,format=raw,unit=1,file=$HOME/OVMF_VARS.fd -drive if=ide,format=raw,file=$HOME/uefi.img -net bridge,br=br0 -net nic,model=virtio
如果一切順利,你將看到類似下圖所示的結果:
你可以使用 shutdown
命令關閉虛擬機回到我們的伺服器上:
$ sudo shutdown -h now
注意:如果出現了錯誤或虛擬機掛住了,你可能需要啟動一個新的 SSH 會話去連接伺服器,使用
kill
命令去終止qemu-system-x86_64
進程。
鏡像中添加包
鏡像中添加包應該是一個很簡單的問題,在伺服器上 chroot
進鏡像,然後運行 dnf install <package_name>
。
在網路引導鏡像中並不限制你能安裝什麼包。一個完整的圖形化安裝應該能夠完美地工作。
下面是一個如何將最小化安裝的網路引導鏡像變成完整的圖形化安裝的示例:
$ for i in dev dev/pts dev/shm proc sys run; do mount -o bind /$i /fc28/$i; done
$ chroot /fc28 /usr/bin/bash --login
$ dnf -y groupinstall "Fedora Workstation"
$ dnf -y remove gnome-initial-setup
$ systemctl disable sshd.service
$ systemctl enable gdm.service
$ systemctl set-default graphical.target
$ sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/sysconfig/selinux
$ logout
$ for i in run sys proc dev/shm dev/pts dev; do umount /fc28/$i; done
可選地,你可能希望去啟用 liveuser
用戶的自動登錄:
$ sed -i '/daemon/a AutomaticLoginEnable=true' /fc28/etc/gdm/custom.conf
$ sed -i '/daemon/a AutomaticLogin=liveuser' /fc28/etc/gdm/custom.conf
via: https://fedoramagazine.org/how-to-build-a-netboot-server-part-1/
作者:Gregory Bartholomew 選題:lujun9972 譯者:qhwdw 校對:wxy
本文轉載來自 Linux 中國: https://github.com/Linux-CN/archive