您好,我是 Denis,我的活动领域之一是 X5 基础设施解决方案的开发。 今天我想和大家分享一下如何基于公开的工具部署自动服务器准备系统。 在我看来,这是一个有趣、简单且灵活的解决方案。
我们所说的准备是指:将开箱即用的新服务器变成带有操作系统的完全配置的服务器。 Linux 或使用 ESXi 管理程序(本文不讨论 Windows 服务器的部署)。
术语:
- 服务器 – 需要配置的服务器。
- 安装服务器是通过网络提供整个准备过程的主服务器。
为什么需要自动化?
假设有一项任务:从头开始大规模准备服务器,最多时为每天 30 台。 不同制造商和型号的服务器,可能安装不同的操作系统,并且可能有也可能没有虚拟机管理程序。
设置过程中包含哪些操作(无自动化):
- 将键盘、鼠标、显示器连接到服务器;
- 配置BIOS、RAID、IPMI;
- 更新组件固件;
- 部署文件系统映像(或安装虚拟机管理程序并复制虚拟机);
笔记。 或者,可以通过使用自动响应文件进行安装来部署操作系统。 但本文不会讨论这一点。 尽管您将在下面看到添加此功能并不困难。
- 配置操作系统参数(主机名、IP 等)。
通过这种方法,在每台服务器上顺序执行相同的设置。 这样的工作效率是很低的。
自动化的本质是在服务器准备过程中消除人工参与。 越多越好。
自动化减少了操作之间的停机时间,并使同时配置多个服务器成为可能。 由于人为因素造成错误的可能性也大大降低。
服务器如何自动配置?
我们来详细分析一下各个阶段。
您有一台用作 PXE 安装服务器的 Linux 服务器。 在其上安装和配置服务:DHCP、TFTP。
因此,我们通过 PXE 启动服务器(需要配置)。 让我们记住它是如何工作的:
- 服务器上选择网络启动。
- 服务器加载网卡的PXE-ROM,并通过DHCP联系安装服务器获取网络地址。
- DHCP 安装服务器发出地址以及通过 PXE 进一步下载的说明。
- 服务器通过 PXE 从安装服务器加载网络引导加载程序,并根据 PXE 配置文件进行进一步加载。
- 引导根据接收到的参数(内核、initramfs、挂载点、squashfs 映像等)进行。
笔记。 本文介绍了通过 BIOS 模式通过 PXE 启动。 目前,厂商正在积极实施UEFI启动模式。 对于 PXE,区别在于 DHCP 服务器的配置和附加引导加载程序的存在。
让我们看一下 PXE 服务器配置的示例(pxelinux 菜单)。
文件 pxelinux.cfg/default:
default menu.c32
prompt 0
timeout 100
menu title X5 PXE Boot Menu
LABEL InstallServer Menu
MENU LABEL InstallServer
KERNEL menu.c32
APPEND pxelinux.cfg/installserver
LABEL VMware Menu
MENU LABEL VMware ESXi Install
KERNEL menu.c32
APPEND pxelinux.cfg/vmware
LABEL toolkit // меню по умолчанию
MENU LABEL Linux Scripting Toolkits
MENU default
KERNEL menu.c32
APPEND pxelinux.cfg/toolkit // переход на следующее меню
文件 pxelinux.cfg/工具包:
prompt 0
timeout 100
menu title X5 PXE Boot Menu
label mainmenu
menu label ^Return to Main Menu
kernel menu.c32
append pxelinux.cfg/default
label x5toolkit-auto // по умолчанию — автоматический режим
menu label x5 toolkit autoinstall
menu default
kernel toolkit/tkcustom-kernel
append initrd=toolkit/tk-initramfs.gz quiet net.ifnames=0 biosdevname=0 nfs_toolkit_ip=192.168.200.1 nfs_toolkit_path=tftpboot/toolkit nfs_toolkit_script=scripts/mount.sh script_cmd=master-install.sh CMDIS2=”…”
label x5toolkit-shell // для отладки - консоль
menu label x5 toolkit shell
kernel toolkit/tkcustom-kernel
append initrd=toolkit/tkcustom-initramfs.gz quiet net.ifnames=0 biosdevname=0 nfs_toolkit_ip=192.168.200.1 nfs_toolkit_path=tftpboot/toolkit nfs_toolkit_script=scripts/mount.sh script_cmd=/bin/bash CMDIS2=”…”
此阶段的内核和 initramfs 是中间 Linux 映像,服务器的主要准备和配置将在其帮助下进行。
正如您所看到的,引导加载程序将许多参数传递给内核。 其中一些参数由内核本身使用。 我们可以将一些用于我们自己的目的。 这将在稍后讨论,但现在您只需记住所有传递的参数都将通过 /proc/cmdline 在中间 Linux 映像中可用。
我在哪里可以获得内核和 initramfs?
作为基础,您可以选择任何 Linux 发行版。 我们在选择时要注意什么:
- 启动映像必须是通用的(驱动程序的可用性、安装其他实用程序的能力);
- 最有可能的是,您需要自定义 initramfs。
我们的 X5 解决方案是如何做到这一点的? 选择CentOS 7作为基础,让我们尝试以下技巧:准备未来的映像结构,将其打包成存档并创建一个initramfs,其中将包含我们的文件系统存档。 加载映像时,存档将扩展到创建的 tmpfs 分区。 这样,我们将获得一个最小但功能齐全的实时 Linux 映像,其中包含所有必需的实用程序,仅包含两个文件:vmkernel 和 initramfs。
#создаем директории:
mkdir -p /tftpboot/toolkit/CustomTK/rootfs /tftpboot/toolkit/CustomTK/initramfs/bin
#подготавливаем структуру:
yum groups -y install "Minimal Install" --installroot=/tftpboot/toolkit/CustomTK/rootfs/
yum -y install nfs-utils mariadb ntpdate mtools syslinux mdadm tbb libgomp efibootmgr dosfstools net-tools pciutils openssl make ipmitool OpenIPMI-modalias rng-tools --installroot=/tftpboot/toolkit/CustomTK/rootfs/
yum -y remove biosdevname --installroot=/tftpboot/toolkit/CustomTK/rootfs/
# подготавливаем initramfs:
wget https://busybox.net/downloads/binaries/1.31.0-defconfig-multiarch-musl/busybox-x86_64 -O /tftpboot/toolkit/CustomTK/initramfs/bin/busybox
chmod a+x /tftpboot/toolkit/CustomTK/initramfs/bin/busybox
cp /tftpboot/toolkit/CustomTK/rootfs/boot/vmlinuz-3.10.0-957.el7.x86_64 /tftpboot/toolkit/tkcustom-kernel
# создаем /tftpboot/toolkit/CustomTK/initramfs/init (ниже содержание скрипта):
#!/bin/busybox sh
/bin/busybox --install /bin
mkdir -p /dev /proc /sys /var/run /newroot
mount -t proc proc /proc
mount -o mode=0755 -t devtmpfs devtmpfs /dev
mkdir -p /dev/pts /dev/shm /dev/mapper /dev/vc
mount -t devpts -o gid=5,mode=620 devpts /dev/pts
mount -t sysfs sysfs /sys
mount -t tmpfs -o size=4000m tmpfs /newroot
echo -n "Extracting rootfs... "
xz -d -c -f rootfs.tar.xz | tar -x -f - -C /newroot
echo "done"
mkdir -p /newroot/dev /newroot/proc /newroot/sys
mount --move /sys /newroot/sys
mount --move /proc /newroot/proc
mount --move /dev /newroot/dev
exec switch_root /newroot /sbin/init
# упаковываем rootfs и initramfs:
cd /tftpboot/toolkit/CustomTK/rootfs
tar cJf /tftpboot/toolkit/CustomTK/initramfs/rootfs.tar.xz --exclude ./proc --exclude ./sys --exclude ./dev .
cd /tftpboot/toolkit/CustomTK/initramfs
find . -print0 | cpio --null -ov --format=newc | gzip -9 > /tftpboot/toolkit/tkcustom-initramfs-new.gz
所以我们已经指定了应该加载的内核和initramfs。 因此,在这个阶段,通过 PXE 加载中间 Linux 映像,我们将收到操作系统控制台。
太好了,但现在我们需要将控制权转移给我们的“自动化”。
可以这样做。
假设加载图像后,我们计划将控制权转移到 mount.sh 脚本。
让我们将 mount.sh 脚本包含在自动运行中。 为此,您需要修改 initramfs:
- 解压 initramfs(如果我们使用上面的 initramfs 选项,则不需要)
- 在启动中包含代码,该代码将分析通过 /proc/cmdline 传递的参数并进一步转移控制;
- 打包 initramfs。
笔记。 对于 X5 工具包,加载控制转移到脚本 /opt/x5/toolkit/bin/hook.sh с помощью override.conf в getty tty1 (ExecStart=…)
因此,图像已加载,其中 mount.sh 脚本在自动运行时启动。 接下来,mount.sh 脚本在执行过程中分析传递的参数 (script_cmd=) 并启动必要的程序/脚本。
标签工具包-汽车
核心...
附加...nfs_toolkit_script=scripts/mount.sh script_cmd=master-install.sh
标签工具包-壳
核心...
附加...nfs_toolkit_script=scripts/mount.sh script_cmd=/bin/bash
这里左边是PXE菜单,右边是控制传输图。
我们弄清楚了控制权的转移。 根据 PXE 菜单的选择,启动自动配置脚本或调试控制台。
在自动配置的情况下,将从安装服务器安装必要的目录,其中包含:
- 脚本;
- 保存各种服务器的BIOS/UEFI模板;
- 固件;
- 服务器实用程序;
- 日志
接下来,mount.sh 脚本将控制从脚本目录转移到 master-install.sh 脚本。
脚本树(它们启动的顺序)看起来像这样:
- 主安装
- sharefunctions(共享函数)
- info(信息输出)
- models(根据服务器型号设置安装参数)
- prepare_utils(安装必要的实用程序)
- fwupdate(固件更新)
- diag(基本诊断)
- biosconf(BIOS/UEFI 设置)
- ClockFix(设置主板上的时间)
- srmconf(远程接口接口配置)
- raidconf(配置逻辑卷)
之一:
- 预安装(将控制权转移给操作系统或虚拟机管理程序安装程序,例如 ESXi)
- 合并安装(立即开始解压映像)
现在我们知道:
- 如何通过 PXE 启动服务器;
- 如何将控制权转移到您自己的脚本。
我们继续吧。 以下问题变得相关:
- 如何识别我们准备的服务器呢?
- 有哪些实用程序以及如何配置服务器?
- 如何获取特定服务器的设置?
如何识别我们准备的服务器呢?
很简单 - DMI:
dmidecode –s system-product-name
dmidecode –s system-manufacturer
dmidecode –s system-serial-number
您需要的一切都在这里:供应商、型号、序列号。 如果您不确定所有服务器中是否都存在此信息,您可以通过 MAC 地址来识别它们。 或者同时采用两种方式,如果服务器供应商不同并且在某些型号上根本没有有关序列号的信息。
根据收到的信息,从安装服务器安装网络文件夹并加载所需的所有内容(实用程序、固件等)。
有哪些实用程序以及如何配置服务器?
我将为一些制造商提供适用于 Linux 的实用程序。 所有实用程序都可以在供应商的官方网站上找到。
有了固件,我想一切都清楚了。 它们通常以打包的可执行文件的形式出现。 可执行文件控制固件更新过程并报告返回代码。
BIOS和IPMI通常通过模板进行配置。 如有必要,可以在下载之前对模板进行编辑。
某些供应商的 RAID 实用程序也可以使用模板进行配置。 如果不是这种情况,那么您将必须编写配置脚本。
设置 RAID 的过程通常如下:
- 我们请求当前配置。
- 如果已经存在逻辑数组,我们将其删除。
- 让我们看看存在哪些物理磁盘以及有多少个。
- 创建一个新的逻辑数组。 如果出现错误,我们会中断该过程。
如何获取特定服务器的设置?
假设所有服务器的设置都将存储在安装服务器上。 在这种情况下,要回答我们的问题,我们必须首先决定如何将设置传输到安装服务器。
首先,您可以使用文本文件。 (将来,您可能希望使用文本文件作为传输设置的后备方法。)
您可以在安装服务器上“共享”文本文件。 并将其挂载添加到 mount.sh 脚本中。
例如,这些行将如下所示:
<序列号> <主机名> <子网>
这些行将由工程师从他的工作机器传输到文件中。 然后,在设置服务器时,将从文件中读取特定服务器的参数。
但是,从长远来看,最好使用数据库来存储服务器安装的设置、状态和日志。
当然,仅有数据库是不够的,您需要创建一个客户端部分,借助该部分将设置传输到数据库。 与文本文件相比,这更难实现,但事实上,一切并不像看起来那么困难。 很有可能编写一个最小版本的客户端,只需自己将数据传输到数据库。 并且将来可以在免费模式下改进客户端程序(想到的报告、打印标签、发送通知等)。
通过向数据库发出特定请求并指定服务器序列号,我们将收到配置服务器所需的参数。
另外,我们不需要像文本文件那样为同时访问提供锁。
我们可以将各个阶段的配置日志写入数据库,并通过准备阶段的事件和标志来控制安装过程。
现在我们知道如何:
- 通过 PXE 启动服务器;
- 将控制权转移给我们的脚本;
- 通过序列号识别需要准备的服务器;
- 使用适当的实用程序配置服务器;
- 使用客户端部分将设置传输到安装服务器数据库。
我们发现如何:
- 安装的服务器从数据库接收必要的设置;
- 所有准备进度都记录在数据库中(日志、事件、阶段标志)。
您安装的不同类型的软件怎么样? 如何安装虚拟机管理程序、复制虚拟机并进行配置?
在将文件系统映像(linux)部署到硬件的情况下,一切都非常简单:
- 设置完所有服务器组件后,我们部署映像。
- 安装 grub 引导加载程序。
- 我们 chroot 并配置所需的一切。
如何将控制权转移给操作系统安装程序(以 ESXi 为例)。
- 我们使用自动响应文件(kickstart)组织控制从脚本到虚拟机管理程序安装程序的转移:
- 我们删除磁盘上的当前分区。
- 创建一个大小为 500MB 的分区。
- 我们将其标记为可启动。
- 格式化为 FAT32。
- 我们将 ESXi 安装文件复制到根目录。
- 安装 syslinux。
- 将 syslinux.cfg 复制到 /syslinux/
default esxi
prompt 1
timeout 50
label esxi
kernel mboot.c32
append -c boot.cfg
- 将 mboot.c32 复制到 /syslinux。
- Boot.cfg 应该有 kernelopt=ks=ftp:// /ks_esxi.cfg
- 我们重新启动服务器。
服务器重新启动后,ESXi 安装程序将从服务器的硬盘下载。 所有必需的安装程序文件都将加载到内存中,然后根据指定的自动响应文件开始 ESXi 安装。
以下是自动响应文件 ks_esxi.cfg 中的几行:
%firstboot --interpreter=busybox
…
# получаем серийный номер
SYSSN=$(esxcli hardware platform get | grep Serial | awk -F " " '{print $3}')
# получаем IP
IPADDRT=$(esxcli network ip interface ipv4 get | grep vmk0 | awk -F " " '{print $2}')
LAST_OCTET=$(echo $IPADDRT | awk -F'.' '{print $4}')
# подключаем NFS инсталл-сервера
esxcli storage nfs add -H is -s /srv/nfs_share -v nfsshare1
# копируем временные настройки ssh, для использования ssh-клиента
mv /etc/ssh /etc/ssh.tmp
cp -R /vmfs/volumes/nfsshare1/ssh /etc/
chmod go-r /etc/ssh/ssh_host_rsa_key
# копируем ovftool, для развертывания ВМ сейчас, плюс возможно пригодится позже
cp -R /vmfs/volumes/nfsshare1/ovftool /vmfs/volumes/datastore1/
# развертываем ВМ
/vmfs/volumes/datastore1/ovftool/tools/ovftool --acceptAllEulas --noSSLVerify --datastore=datastore1 --name=VM1 /vmfs/volumes/nfsshare1/VM_T/VM1.ova vi://root:[email protected]
/vmfs/volumes/datastore1/ovftool/tools/ovftool --acceptAllEulas --noSSLVerify --datastore=datastore1 --name=VM2 /vmfs/volumes/nfsshare1/VM_T/VM2.ova vi://root:[email protected]
# получаем строку с настройками нашего сервера
ssh root@is "mysql -h'192.168.0.1' -D'servers' -u'user' -p'secretpassword' -e "SELECT ... WHERE servers.serial='$SYSSN'"" | grep -v ^$ | sed 's/NULL//g' > /tmp/servers
...
# генерируем скрипт настройки сети
echo '#!/bin/sh' > /vmfs/volumes/datastore1/netconf.sh
echo "esxcli network ip interface ipv4 set -i=vmk0 -t=static --ipv4=$IPADDR --netmask=$S_SUB || exit 1" >> /vmfs/volumes/datastore1/netconf.sh
echo "esxcli network ip route ipv4 add -g=$S_GW -n=default || exit 1" >> /vmfs/volumes/datastore1/netconf.sh
chmod a+x /vmfs/volumes/datastore1/netconf.sh
# задаем параметр guestinfo.esxihost.id, указываем в нем серийный номер
echo "guestinfo.esxihost.id = "$SYSSN"" >> /vmfs/volumes/datastore1/VM1/VM1.vmx
echo "guestinfo.esxihost.id = "$SYSSN"" >> /vmfs/volumes/datastore1/VM2/VM2.vmx
...
# обновляем информацию в базе
SYSNAME=$(esxcli hardware platform get | grep Product | sed 's/Product Name://' | sed 's/^ *//')
UUID=$(vim-cmd hostsvc/hostsummary | grep uuid | sed 's/ //g;s/,$//' | sed 's/^uuid="//;s/"$//')
ssh root@is "mysql -D'servers' -u'user' -p'secretpassword' -e "UPDATE servers ... SET ... WHERE servers.serial='$SYSSN'""
ssh root@is "mysql -D'servers' -u'user' -p'secretpassword' -e "INSERT INTO events ...""
# возвращаем настройки SSH
rm -rf /etc/ssh
mv /etc/ssh.tmp /etc/ssh
# настраиваем сеть и перезагружаемся
esxcli system hostname set --fqdn=esx-${G_NICK}.x5.ru
/vmfs/volumes/datastore1/netconf.sh
reboot
在此阶段,将安装和配置虚拟机管理程序,并复制虚拟机。
现在如何配置虚拟机?
我们做了一点小作弊:在安装过程中,我们在 VM1.vmx 文件中设置了参数 guestinfo.esxihost.id = "$SYSSN" 并在其中指示了物理服务器的序列号。
现在,启动后,虚拟机(安装了vmware-tools包)就可以访问这个参数了:
ESXI_SN=$(vmtoolsd --cmd "info-get guestinfo.esxihost.id")
也就是说,VM 将能够识别自身(它知道物理主机的序列号),向安装服务器数据库发出请求并接收需要配置的参数。 这一切都被编译成一个脚本,该脚本应该在 guestos vm 启动时自动启动(但一次:RunOnce)。
现在我们知道如何:
- 通过 PXE 启动服务器;
- 将控制权转移给我们的脚本;
- 通过序列号识别需要准备的服务器;
- 使用适当的实用程序配置服务器;
- 使用客户端部分将设置传输到安装服务器数据库;
- 配置各种类型的软件,包括部署 esxi 管理程序和配置虚拟机(全部自动)。
我们发现如何:
- 安装的服务器从数据库接收必要的设置;
- 所有准备进度都记录在数据库中(日志、事件、阶段标志)。
底线:
我相信这个解决方案的独特之处在于它的灵活性、简单性、功能和多功能性。
请在评论中写下你的想法。
来源: habr.com