我不擅長編寫腳本…如何最好地更新從 PXE 實時執行的 debian 伺服器上的 IP 地址(DHCP 保留不是一個選項)
在這一點上,這比任何事情都更像是一個大腦轉儲,但我被困住了,我們將不勝感激!
我的 3 台伺服器有一組非常複雜的限制,需要從 ram 驅動器執行作業系統。長話短說,我有一組刀片伺服器,每個刀片伺服器總共有 4 個硬碟。我需要以分佈式模式執行一個名為 MinIO 的伺服器應用程序。對於分佈式模式,MinIO 需要 3 個節點,每個節點有 4 個原始 HDD。這意味著刀片中沒有足夠的 HDD。對於這種情況,有一些解決方法,但由於我們不會在這裡討論的原因,我們不能這樣做。我的任務是從 ram 驅動器啟動這些伺服器……我最終使用 FOG 讓它工作(基本上只是 PXE 啟動並通過網路使用根文件系統載入 squashfs 文件)。
目前,最困難的部分已經完成。伺服器啟動,我正在瀏覽他們用來配置 MinIO 的 squashfs 文件。不過,我遇到了一些持久設置的障礙。所以基本上,我需要一種方法讓三台伺服器根據它們的網路控制器的 MAC 地址設置自己的靜態 IP。
現在我知道我可以設置 DHCP 保留,並且我有 3 個有問題的 nic!但是 3 個 nic 存在於沒有DHCP 伺服器的公共網路上……這些 nic必須動態設置靜態 IP……是的……我似乎無法找到一個好的方法來做到這一點。
我將繼續研究並嘗試自己挑選這個,但我會隨時在這裡發布我的進展。如果有人有想法,我非常願意接受建議!
接下來是我到目前為止所做的事情時的大腦轉儲。請注意,除了 DHCP 部分之外,所有這些都是在 PXE 伺服器本身上完成的。理論上,如果我做對了,除了引導之外,不需要在目標伺服器上做任何事情。
第 1 部分:通過 FOG
安裝的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
設置網路配置並重新啟動。
安裝霧:
$ 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 指示我登錄管理網站以完成配置……這很簡單;只需打開瀏覽器,轉到霧提供的網址,點擊“安裝”,就完成了。
**免責聲明:**我沒有為網頁使用 ssl,也沒有配置防火牆。PXE 伺服器不在公共網路上。此外,我們所在的網路僅為此安裝提供了 Internet 訪問權限。一旦一切啟動並執行,PXE 伺服器就從網際網路上完全斷開(完全拔掉了電纜)。任何使用此作為實時 PXE 引導指南的人都應該考慮設置 ssl,尤其是在連接到 Internet 的情況下!至少你應該設置你的防火牆並創建一個自簽名證書!
第 2 部分:執行命令 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 菜單。如果我們首先在測試 VM 設置中設置舊適配器,我們甚至可以讓 HyperV 中的 VM 啟動到它。
在看到“等待網路”之前,在 dmesg 中看到實際下載進度的“正在下載 filesystem.squashfs”有點超現實。看 lsblk 時更是如此!在此之後,我將建構一個恢復映像(想到 knoppix)以供一般使用***。***不再需要拇指驅動器或刻錄 DVD,只需啟動到網路並選擇恢復選項!
第 3 部分:在熱鍵盤上工作
這部分非常簡單。我使用了george1421的本指南來實現這一切……如果沒有他的幫助,我不會走到這一步!
下載 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
轉到霧網路管理(在我的情況下為http://10.10.10.100/fog/management) FOG Configuration->iPXE New Menu Entry 菜單項:
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 文件並 chroot 以進行更改。
$ 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不要在 chroot 中啟用防火牆,除非您可以物理訪問伺服器(或具有 IPMI),否則防火牆實際上會阻止主機作業系統中的流量!不知道如何解決這個問題……我們需要在啟動時在客戶端上啟用防火牆。我最好的想法是在 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,將 temp 文件夾壓縮回 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
… 如果它有效,我會將您的回复標記為解決方案。
考慮這樣的事情:
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 命令