Bare-Metal Provisioning своими руками, или Автоматическая подготовка серверов с нуля

Здравейте, аз съм Денис и едно от основните ми направления е разработването на инфраструктурни решения в X5. Днес бих искал да споделя с вас как с помощта на обществено достъпни инструменти може да се внедри автоматизирана система за подготовка на сървъри. Според мен, това е интересно, прост и гъвкав подход.

Bare-Metal Provisioning своими руками, или Автоматическая подготовка серверов с нуля

Под подготовката се разбира: да се създаде нов сървър от кутията, напълно конфигуриран сървър с операционна система Linux или с хипервизор ESXi (разглеждането на сървъри Windows в тази статия не е обсъдено).

Термини:

  • сървъри – сървъри, които трябва да бъдат конфигурирани.
  • инсталационен сървър – основният сървър, който осигурява целия процес на подготовка по мрежата.

Защо е необходима автоматизация?

Да предположим, че има задача: масово подготвяне на сървъри от нулата, в пикови моменти – 30 на ден. Сървъри от различни производители и модели, на които могат да бъдат инсталирани различни операционни системи, може да има или да няма хипервизор.

Кои операции влизат в процеса на настройка (без автоматизация):

  • да свържете клавиатура, мишка, монитор към сървъра;
  • да настроите BIOS, RAID, IPMI;
  • да обновите фърмуера на компонентите;
  • да разположите образ на файловата система (или да инсталирате хипервизор и да копирате виртуални машини);

Забележка. Като опция, внедряването на ОС е възможно чрез инсталация с файлове за автоматичен отговор. Но това няма да бъде обсъждано в статията. Въпреки това, по-долу ще видите, че добавянето на този функционал не е сложно.

  • да конфигурирате параметрите на ОС (hostname, IP и др.).

При този подход идентичните настройки се изпълняват последователно на всеки сървър. Ефективността на такава работа е много ниска.

Суть на автоматизацията е да се изключи участието на човека от процеса на подготовка на сървъра. Максимално, доколкото е възможно.

Благодарение на автоматизацията се намалява времето на простои между операциите и се появява възможността за подготовка на няколко сървъра едновременно. Също така, вероятността от възникване на грешки поради човешки фактор се намалява значително.

Bare-Metal Provisioning своими руками, или Автоматическая подготовка серверов с нуля

Как протича автоматичната настройка на сървърите?

Нека разгледаме всички етапи подробно.

Имате Linux-сървър, който използвате като PXE инсталационен сървър. На него са инсталирани и настроени услуги: DHCP, TFTP.

И така, стартираме сървъра (който трябва да бъде настроен) по PXE. Нека си спомним как работи това:

  • На сървъра е избрана опцията за зареждане по мрежата.
  • Сървърът зарежда PXE-ROM на мрежовата карта и се свързва с инсталационния сървър чрез DHCP, за да получи мрежов адрес.
  • DHCP инсталационния сървър предоставя адрес, както и инструкция за последващо зареждане чрез PXE.
  • Сървърът зарежда мрежовия зареждач от инсталационния сървър по PXE, а последващото зареждане се извършва съгласно конфигурационния файл PXE.
  • Зареждането се извършва на база на получените параметри (ядро, initramfs, точки на монтиране, образ squashfs и други).

Забележка. В статията се описва зареждането по PXE чрез BIOS режим. В момента производителите активно внедряват UEFI bootmode. За 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/toolkit:

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-образ, с помощта на който ще се извършат основната подготовка и настройка на сървъра.

Както виждате, зареждачът предава много параметри на ядрото. Част от тези параметри се използват от самото ядро. А някои можем да използваме за свои цели. Об этом ще бъде разказано по-късно, а засега може просто да запомните, че всички подадени параметри ще бъдат налични в междинния linux-образ чрез /proc/cmdline.

Къде да ги вземем, ядрото и initramfs?
Можем да изберем всеки linux-дистрибутив. На какво обръщаме внимание при избора:

  • загрузъчен образ трябва да бъде универсален (наличие на драйвери, възможности за инсталиране на допълнителни утилити);
  • вероятно, ще се наложи да кастомизираме initramfs.

Как е реализирано в нашето решение за X5? Избрана е като основа CentOS 7. Нека направим трик: подготвяме бъдещата структура на образа, опаковаме я в архив и създаваме initramfs, в който ще бъде нашият архив на файловата система. При зареждане на образа архивът ще се разопакова в създадения tmpfs. Така ще получим минимален, но напълно функционален live-образ 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, които трябва да бъдат заредени. В резултат на това на този етап, след зареждане на междинния linux образ по PXE, ще получим конзола на ОС.

Отлично, но сега трябва да предадем управлението на нашата "автоматизация".

Може да се направи по следния начин.

Да предположим, след зареждане на образа, планираме да предадем управлението на скрипт mount.sh.
Ще включим скрипт mount.sh в автозапуск. За това ще трябва да модифицираме initramfs:

  • разопаковаме initramfs (ако използваме горепосочения вариант на initramfs, това не е необходимо)
  • включваме в автозапуска код, който ще анализира предаваните параметри през /proc/cmdline и ще предава управлението нататък;
  • опаковаме initramfs.

Забележка. В случая с X5 toolkit управлението на зареждането се предава на скрипт /opt/x5/toolkit/bin/hook.sh с помощью override.conf в getty tty1 (ExecStart=…)

Така, зарежда се образ, в който в автозапуска стартира скрипт mount.sh. След това скрипт mount.sh в процеса на изпълнение анализира предадените параметри (script_cmd=) и стартира необходимата програма/скрипт.

label toolkit-auto
kernel …
append … nfs_toolkit_script=scripts/mount.sh script_cmd=master-install.sh

label toolkit-shell
kernel …
append … nfs_toolkit_script=scripts/mount.sh script_cmd=/bin/bash

Bare-Metal Provisioning своими руками, или Автоматическая подготовка серверов с нуля

Тук отляво е меню PXE, а отдясно – схема на предаване на управлението.

С предаването на управлението се справихме. В зависимост от избора на PXE-меню, се стартира либо скрипт за автоматична настройка, либо конзола за отстраняване на грешки.

В случая на автоматична настройка се монтират необходимите директории от инсталационния сървър, в които присъстват:

  • скриптове;
  • съхранени шаблони за BIOS/UEFI на различни сървъри;
  • фърмуери;
  • утилити за сървъри;
  • логове.

След това скрипт mount.sh предава управлението на скрипт master-install.sh от директорията със скриптове.

Дървото на скриптовете (ред на изпълнение) изглежда по следния начин:

  • master-install
  • sharefunctions (общи функции)
  • info (извеждане на информация)
  • models (настройка на параметри на инсталацията на базата на модела на сървъра)
  • prepare_utils (инсталиране на необходимите утилити)
  • fwupdate (плевел обновяване на фърмуера)
  • diag (основна диагностика)
  • biosconf (конфигуриране на BIOS/UEFI)
  • clockfix (настройка на времето на дънната платка)
  • srmconf (конфигуриране на интерфейса за дистанционно управление)
  • raidconf (конфигуриране на логически обеми)

един от:

  • preinstall (преминаване към инсталатора на ОС или хипервизора, например ESXi)
  • merged-install (незабавен старт на разархивирането на имиджа)

Сега знаем:

  • как да заредим сървъра по PXE;
  • как да предадем управлението на собствен скрипт.


Да продължим. Възникват следните въпроси:

  • Как да идентифицираме сървъра, който подготвяме?
  • С какви инструменти и как да конфигурираме сървъра?
  • Как да получим настройки за конкретния сървър?

Как да идентифицираме сървъра, който подготвяме?

Това е просто – DMI:

dmidecode –s system-product-name
dmidecode –s system-manufacturer
dmidecode –s system-serial-number

Тук има всичко необходимо: производител, модел, сериен номер. Ако не сте сигурни, че тази информация е налична във всички сървъри, можете да ги идентифицирате по MAC адрес. Или и с двата метода едновременно, ако производителите на сървърите са различни и в някои модели информацията за серийния номер просто липсва.

На базата на получената информация се монтират мрежови папки от инсталационния сървър и се подлагат всички необходими (инструменти, фърмуери и други).

С какви инструменти и как да конфигурираме сървъра?

Предоставям инструменти за Linux за някои производители. Всички инструменти са налични на официалните сайтове на производителите.

Bare-Metal Provisioning своими руками, или Автоматическая подготовка серверов с нуля

С фърмуерите, мисля, всичко е ясно. Обикновено те се предоставят под формата на опаковани изпълними файлове. Изпълнимият файл контролира процеса на обновяване на фърмуера и съобщава кода за грешка.

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:esxi_password@127.0.0.1
/vmfs/volumes/datastore1/ovftool/tools/ovftool --acceptAllEulas --noSSLVerify --datastore=datastore1 --name=VM2 /vmfs/volumes/nfsshare1/VM_T/VM2.ova vi://root:esxi_password@127.0.0.1

# Получаване на стринг с настройки на нашия сървър

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://;s/^ *//')
UUID=$(vim-cmd hostsvc/hostsummary | grep uuid | sed 's/ //g;s/,$//;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

На този етап хипервизорът е инсталиран и настроен, виртуалните машини са копирани.

Как сега да настроим виртуалните машини?

Нуждаехме се от малко хитрост: по време на инсталацията зададохме параметър guestinfo.esxihost.id = "$SYSSN" в файла VM1.vmx, указвайки серийния номер на физическия сървър.

Сега след стартиране виртуалната машина (с инсталиран пакет vmware-tools) може да получи достъп до този параметър:

ESXI_SN=$(vmtoolsd --cmd "info-get guestinfo.esxihost.id")

Тоест, ВМ ще може да се идентифицира (тя знае серийния номер на физическия хост), да направи запитване към БД на инсталационния сървър и да получи параметрите, които трябва да бъдат настроени. Всичко това е оформено в скрипт, който трябва да бъде стартиран автоматично при старта на guestos vm (но само веднъж: RunOnce).

Сега знаем как:

  • да зареждаме сървера чрез PXE;
  • да предадем управлението на нашия скрипт;
  • да идентифицираме сървера, който трябва да подготвим, по серийния номер;
  • конфигуриране на сървъра с подходящи инструменти;
  • передаване на настройките в БД на инсталационния сървър чрез клиентската част;
  • настройка на различни видове софтуер, включително внедряване на хипервизор esxi и настройка на виртуални машини (всичко автоматично).

Разбрахме как:

  • инсталираният сървър получава необходимите настройки от БД;
  • всички напредъци на подготовката се записват в БД (логове, събития, флагове на етапите).


Резултат:

Смятам, че уникалността на това решение е в гъвкавостта, простотата, възможностите му и универсалността.

Моля, напишете в коментарите какво мислите.

Източник: habr.com

Купете надежден хостинг за сайтове със защита от DDoS, VPS и VDS сървъри 🔥 Купете надежден хостинг за сайтове със защита от DDoS, VPS и VDS сървъри | ProHoster