Debian

我不擅長編寫腳本…如何最好地更新從 PXE 實時執行的 debian 伺服器上的 IP 地址(DHCP 保留不是一個選項)

  • August 13, 2020

在這一點上,這比任何事情都更像是一個大腦轉儲,但我被困住了,我們將不勝感激!

我的 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 命令

引用自:https://serverfault.com/questions/1030016