目前,这更像是一次脑力倾泻,但我陷入了困境,如果能得到帮助我将非常感激!
我的 3 台服务器有一组非常复杂的限制,必须从 RAM 驱动器运行操作系统。长话短说,我有一组刀片服务器,每台服务器总共有 4 个硬盘。我需要在分布式模式下运行一个名为 MinIO 的服务器应用程序。对于分布式模式,MinIO 需要 3 个节点,每个节点有 4 个原始 HDD。这意味着,刀片中没有足够的 HDD。这种情况有解决方法,但由于我们不会在这里讨论的原因,我们不能这样做。我的任务是从 RAM 驱动器启动这些服务器...我最终使用 FOG 让它工作(基本上只是通过网络使用根文件系统进行 PXE 启动和加载 squashfs 文件)。
目前,最困难的部分已经完成。服务器启动,我正在查看它们用于配置 MinIO 的 squashfs 文件。不过,我遇到了一些持久设置问题。所以基本上,我需要一种方法让这三台服务器根据其网络控制器的 MAC 地址设置自己的静态 IP。
现在我知道我可以设置 DHCP 预留,并且对于有问题的 3 个网卡,我已经设置了!但是 3 个网卡位于公共网络上没有DHCP 服务器...这些网卡有动态设置静态 IP...是的...我似乎找不到一个好方法来做到这一点。
我将继续研究并尝试自己解决这个问题,但我会在这里发布我的进展。如果有人有想法,我非常愿意接受建议!
接下来是我在回顾迄今为止所做的事情时的心得。请注意,除 DHCP 部分之外的所有操作都是在 PXE 服务器本身上完成的。理论上,如果我做得对,除了启动之外,目标服务器上不需要做任何事情。
第一部分:穿过迷雾
已安装Debian 标准采用大多数默认选项,仅在tasksel中选择ssh服务器和核心组件
一些安装后修正和包安装:
$ su
# nano /etc/apt/sources.list # <--remove the line for the DVD
# apt-get update && apt-get install sudo neofetch apache2 bc build-essential cpp curl g++ gawk gcc genisoimage git gzip htmldoc isolinux lftp libapache2-mod-php7.3 libc6 libcurl4 liblzma-dev m4 mariadb-client mariadb-server net-tools nfs-kernel-server openssh-server php7.3 php7.3-bcmath php7.3-cli php7.3-curl php7.3-fpm php7.3-gd php7.3-json php7.3-ldap php7.3-mbstring php7.3-mysql php7.3-mysqlnd php-gettext sysv-rc-conf tar tftpd-hpa tftp-hpa unzip vsftpd wget xinetd zlib1g
# /usr/sbin/usermod -a -G sudo [username]
# exit
$ exec newgrp sudo
$ export PATH=$PATH:/usr/sbin
$ sudo export PATH=$PATH:/usr/sbin
设置网络配置并重新启动。
安装 FOG:
$ wget https://github.com/FOGProject/fogproject/archive/1.5.8.tar.gz
$ mv 1.5.8.tar.gz fogproject-1.5.8.tar.gz
$ sudo cp fogproject-1.5.8.tar.gz /tmp/
$ cd /tmp/
$ sudo tar -zxvf fogproject-1.5.8.tar.gz
$ cd fogproject-1.5.8/bin/
$ sudo ./installfog.sh
在 FOG 安装期间采用默认设置...
问题#1: 注意安装程序!!!如果 fog 在开始配置 MySQL 后出现任何错误或被取消,您不妨重新开始。修复 MySQL 登录问题(至少在我的环境中)比重新安装操作系统花费的时间更长。在安装即将结束时,FOG 指示我登录管理网站以完成配置...这很容易;只需打开浏览器,转到 fog 提供的 URL,单击“安装”,就大功告成了。
免责声明:我没有对网页使用 SSL,也没有配置防火墙。PXE 服务器不在公共网络上。此外,我们所在的网络已获得互联网访问权限仅限此安装。一切启动并运行后,PXE 服务器实际上已与互联网断开(完全拔掉电缆)。任何使用此指南进行实时 PXE 启动的人都应考虑设置 SSL,尤其是在有互联网连接的情况下!至少您应该设置防火墙并创建自签名证书!
第二部分:执行命令 66...和 67
DHCP 选项 66 和 67 指定 TFTP 服务器的位置和要提供的可启动文件。我有一个测试环境和生产环境。一个使用 edgerouter,而另一个仅使用 server2012 r2 提供 DHCP 和 DNS。我已经在这两个环境中构建了整个设置,因此一旦我在测试中将其全部启动并运行,我们就可以快速部署。
在 edgerouter 上我运行了以下命令:
set service dhcp-server shared-network-name VL1_dhcp subnet 10.10.10.0/24 tftp-server-name 10.10.10.100
set service dhcp-server shared-network-name VL1_dhcp subnet 10.10.10.0/24 bootfile-name ipxe.kpx
set service dhcp-server shared-network-name VL1_dhcp subnet 10.10.10.0/24 bootfile-server 10.10.10.100
在 Windows 服务器上我执行了以下操作:
- 打开 DHCP 控制台
- 深入研究相关范围
- 右键单击范围选项 -> 配置选项
- 向下滚动并检查数字 66。
- 输入 PXE 服务器的 IP 地址作为字符串值。其他在线说明说使用 PXE 服务器主机名。我们发现使用服务器 IP 地址更可靠。
- 向下滚动并检查数字 67。
- 输入字符串值“ipxe.kpxe”(不带引号)
- 套用並關閉。
此时,Fog 服务器已正常运行。私有网络中任何具有网络启动功能的计算机都可以启动到 FOG 菜单。我们甚至可以让 HyperV 中的虚拟机启动到该菜单,前提是我们先在测试虚拟机设置中设置一个旧版适配器。
看到“正在下载 filesystem.squashfs”,并且在 dmesg 中看到实际下载进度,感觉有点不真实,前看到“正在等待网络”。当我查看 lsblk! 时更是如此。在此之后,我所以准备构建一个恢复映像(想到了 knoppix)以供一般使用。不再需要拇指驱动器或刻录 DVD,只需启动网络并选择恢复选项即可!
第三部分:在热键盘前埋头苦干
这部分非常简单。我用本指南经过乔治1421让这一切成为现实...如果没有他的帮助就不会走到今天!
下载 Debian live 标准版:
$ sudo mkdir /ISO
$ cd /ISO
$ sudo wget https://cdimage.debian.org/debian-cd/current-live/amd64/iso-hybrid/debian-live-10.5.0-amd64-standard.iso
准备引导区域
$ sudo mkdir -p /images/os/debian/10.5L
$ sudo mkdir -p /tftpboot/debian/10.5L
$ sudo mkdir -p /var/www/html/os/debian/10.5L
$ sudo mount -o loop -t iso9660 /ISO/debian-live-10.5.0-amd64-standard.iso /mnt/loop
$ sudo cp -R /mnt/loop/* /images/os/debian/10.5L
$ sudo umount /mnt/loop
复制我们真正关心的唯一文件......
$ sudo cp /images/os/debian/10.5L/live/vmlinuz-4.19.0-10-amd64 /tftpboot/debian/10.5L/vmlinuz
$ sudo cp /images/os/debian/10.5L/live/initrd.img-4.19.0-10-amd64 /tftpboot/debian/10.5L/initrd
$ sudo cp /images/os/debian/10.5L/live/filesystem.squashfs /var/www/html/os/debian/10.5L
转到 fog webmanagement(就我而言http://10.10.10.100/fog/管理)FOG配置->iPXE新建菜单项菜单项:os.Debian10.5SL
说明:Debian 10.5 Standard Live
参数:
kernel tftp://${fog-ip}/debian/10.5L/vmlinuz-4.19.0-10-amd64
initrd tftp://${fog-ip}/debian/10.5L/initrd.img-4.19.0-10-amd64
imgargs vmlinuz boot=live vga=773 components fetch=http://${fog-ip}/os/debian/10.5L/filesystem.squashfs
boot || goto MENU
菜单展示:所有主持人
保存条目然后我们就可以开始球赛了。
第 4 部分:服务器不错……如果服务器重启了就太可惜了
为了构建自定义映像,我在 PXE 服务器上安装了 squashfs-tools,解压缩了实时 squashfs 文件并进行了 chrooted 以进行更改。
$ cd /var/www/html/os/debian/10.5L
$ sudo mkdir squashfs-temp
$ cd squashfs-temp
$ sudo unsquashfs /var/www/html/os/debian/10.5L/filesystem.squashfs
$ sudo chroot /var/www/html/os/debian/10.5L/squashfs-temp/squashfs-root/
我复制了上面提到的更改并在 chroot 中安装了一些东西:
# nano /etc/apt/sources.list # <--had to create a fresh sources.list
deb http://ftp.us.debian.org/debian/ buster main
deb-src http://ftp.us.debian.org/debian/ buster main
要使 DNS 在 chroot 中工作,您需要编辑 resolv.conf。此更改将被其他应用程序覆盖,但这并不重要。这仅适用于 chroot。
# nano /etc/resolv.conf #
nameserver 8.8.8.8
继续...
# apt-get update && apt-get install sudo neofetch ufw wget curl openssh-server # <- this is a good place to install any additional packages you might need on the client.
# adduser [username]
# /usr/sbin/usermod -a -G sudo [username]
# passwd
# su [username]
$ exec newgrp sudo
$ export PATH=$PATH:/usr/sbin
$ exit
# export PATH=$PATH:/usr/sbin
笔记:设置 root 密码会破坏镜像。系统启动后,您会看到一个闪烁的死亡光标。我们需要禁用自动登录。
# echo "live-config.noautologin" >> /etc/live/config.conf
接下来,我在 chroot 中设置防火墙规则(虽然 PXE 服务器没有互联网,但 PXE 客户端有)
# ufw allow in on enp0s10f0 to any port 22 # <--allow ssh over the private nic only
# ufw allow 80 <--allow port 80 over any network
# ufw allow 443 <--allow port 443 over any network
陷阱 #2除非您有服务器的物理访问权限(或有 IPMI),否则请勿在 chroot 中启用防火墙,防火墙实际上会阻止主机操作系统中的流量!目前还不确定如何解决这个问题……我们需要在启动时在客户端上启用防火墙。我最好的想法是在 chroot 中启用它,然后在主机防火墙做出反应之前立即退出 chroot 并重新启动 PXE 服务器。我相信有更优雅的解决方案,但目前我还没想出来。
若要对客户端进行微小更改而不必再次更新 squashfs 文件,请抛出一个脚本来执行更改。
# nano /etc/network/if-up.d/00-onboot
有问题的脚本:
#!/bin/sh
FLAGFILE=/var/lock/launch-script-complete
case "$IFACE" in
lo)
# The loopback interface does not count.
# only run when the any other interface comes up
# in theory, the first interface to actually come up will be the private interface...
exit 0
;;
*)
;;
esac
if [ -e $FLAGFILE ]; then
exit 0
else
touch $FLAGFILE
fi
wget http://10.10.10.100/os/debian/10.5L/launch.sh -O /var/run/launch.sh
sh /var/run/launch.sh
使其可执行
# chmod 755 /etc/network/if-up.d/00-onboot
您会注意到该脚本从 ifup 启动,并且只从 PXE 服务器下载另一个脚本?是的。这就是奇迹发生的地方!
最后,一些生活质量的变化(我们有一个非常具体的用例,这些变化是有意义的。YMMV,请谨慎行事)
# rm /lib/live/config/1160-openssh-server
第 5 部分:噢是的...现在一切都已经准备就绪。
退出 chroot,将临时文件夹压缩回 squashfs 文件,并替换原始文件:
# history -c # <--you dont need THIS history to persist over reboots.
# exit
$ cd /var/www/html/os/debian/10.5L/squashfs-temp
$ sudo mksquashfs squashfs-root/ filesystem.squashfs -noappend -always-use-fragments
$ cd ..
$ sudo mv filesystem.squashfs filesystem.squashfs.old # <-- OR: $ sudo rm filesystem.squashfs
$ sudo mv /var/www/html/os/debian/10.5L/squashfs-temp/filesystem.squashfs /var/www/html/os/debian/10.5L/filesystem.squashfs
就是这样!实时图像已准备好启动...但还有启动脚本...
第 6 部分:将牙膏放回管子里
编辑启动脚本:
$ sudo nano /var/www/html/os/debian/10.5L/launch.sh
这就是我被困住的地方(也许)...问题是,我有 3 台服务器,具有 3 个不同的公共 IP,还有 12 个驱动器,具有不同的 uuid!我该如何告诉脚本使用哪一个?
我认为脚本需要做的第一件事是查看客户端服务器上的网络控制器。使用 cat /sys/class/net/*/address 找到的硬件地址是服务器的文字指纹,因此查看那里是个好主意。我可以创建一个预期的硬件地址列表,并告诉脚本检查存在的地址并采取相应措施。但说实话,我不确定如何实现这一点。我的脚本知识很薄弱。见鬼,我上面放的脚本实际上是从这篇文章中复制而来的,但我认为它可以适用于这个……对吧?
此刻,我正在研究脚本,似乎我有一个解决方案!
免责声明:下面的脚本尚未测试...但它看起来非常简单和直接。
#!/bin/sh
# Commands placed here will be run on ALL clients regardless of actual purpose or identity.
echo "# file deleted on reboot" > /etc/network/interfaces
echo "# The loopback network interface" >> /etc/network/interfaces
echo "auto lo" >> /etc/network/interfaces
echo "iface lo inet loopback" >> /etc/network/interfaces
echo "# The private network interface" >> /etc/network/interfaces
echo "auto eth0" >> /etc/network/interfaces
echo "iface eth0 inet dhcp" >> /etc/network/interfaces
echo "" >> /etc/network/interfaces
# from here on, the script will check the mac ID of the first network card in the server for hardware identification, and run the appropriate section below.
MAC=`ifconfig eth1 | awk '$1 == "ether" {print $2}'`
case "$MAC" in
#mac address of private network card of the first server
"##:##:##:##:##:##" )
echo "# The public network interface" >> /etc/network/interfaces
echo "auto eth1" >> /etc/network/interfaces
echo "iface eth1 inet static" >> /etc/network/interfaces
echo "address 20.0.0.21" >> /etc/network/interfaces
echo "netmask 255.255.255.240" >> /etc/network/interfaces
echo "gateway 20.0.0.1" >> /etc/network/interfaces
echo "" >> /etc/network/interfaces
# additional commands to perform here
;;
#mac address of private network card of the second server
"##:##:##:##:##:##" )
echo "# The public network interface" >> /etc/network/interfaces
echo "auto eth1" >> /etc/network/interfaces
echo "iface eth1 inet static" >> /etc/network/interfaces
echo "address 20.0.0.22" >> /etc/network/interfaces
echo "netmask 255.255.255.240" >> /etc/network/interfaces
echo "gateway 20.0.0.1" >> /etc/network/interfaces
echo "" >> /etc/network/interfaces
# additional commands to perform here
;;
#mac address of private network card of the third server
"##:##:##:##:##:##" )
echo "# The public network interface" >> /etc/network/interfaces
echo "auto eth1" >> /etc/network/interfaces
echo "iface eth1 inet static" >> /etc/network/interfaces
echo "address 20.0.0.23" >> /etc/network/interfaces
echo "netmask 255.255.255.240" >> /etc/network/interfaces
echo "gateway 20.0.0.1" >> /etc/network/interfaces
echo "" >> /etc/network/interfaces
# additional commands to perform here
;;
esac
感谢@Brandon Xavier 的精彩建议。我为此大伤脑筋。老实说,这是 ifconfig 部分的问题,我试图使用ip a
... 获取相同的信息,如果它有效,我会将您的回复标记为解决方案。
答案1
考虑这样的事情:
echo "# file deleted on reboot" > /etc/network/interfaces
echo "# The loopback network interface" >> /etc/network/interfaces
echo "auto lo" >> /etc/network/interfaces
echo "iface lo inet loopback" >> /etc/network/interfaces
echo "# The private network interface" >> /etc/network/interfaces
echo "auto eth0" >> /etc/network/interfaces
echo "iface eth0 inet dhcp" >> /etc/network/interfaces
echo "" >> /etc/network/interfaces
echo "# The public network interface" >> /etc/network/interfaces
echo "auto eth1" >> /etc/network/interfaces
# MAC=`ifconfig eth1 | awk '$1 == "ether" {print $2}'`
# ip equivalent of above
MAC=`ip link show eth1 | awk '$1 == "link/ether" {print $2}'`
case "$MAC" in
"00:11:22:33:44:55" )
echo "iface eth1 inet static" >> /etc/network/interfaces
echo "address 20.0.0.20" >> /etc/network/interfaces
echo "netmask 255.255.255.240" >> /etc/network/interfaces
echo "gateway 20.0.0.1" >> /etc/network/interfaces
echo "" >> /etc/network/interfaces
# add your mount commands or anything else server specific here
;;
"66:77:88:99:AA:BB" )
echo "iface eth1 inet static" >> /etc/network/interfaces
echo "address <some.other.ip>" >> /etc/network/interfaces
echo "netmask 255.255.255.240" >> /etc/network/interfaces
echo "gateway 20.0.0.1" >> /etc/network/interfaces
echo "" >> /etc/network/interfaces
# add your mount commands or anything else server specific here
;;
esac
当然,请用实际值替换 MAC 地址和 IP。并根据需要创建任意数量的模式。
编辑:是的,这非常快、肮脏和丑陋 - 但可靠并且对于新手来说相当容易理解。
EDIT2:添加了等效 ip 命令