Buna ziua, sunt Denis si una dintre domeniile mele de activitate este dezvoltarea solutiilor de infrastructura la X5. Astăzi aș dori să vă împărtășesc cum puteți implementa un sistem automat de pregătire a serverului bazat pe instrumente disponibile public. În opinia mea, aceasta este o soluție interesantă, simplă și flexibilă.

Pregătirea înseamnă: transformarea unui server nou, imediat după deschidere, într-un server complet configurat, cu un sistem de operare. Linux sau cu hipervizorul ESXi (transmiterea servere Windows (nediscutată în acest articol).
Termeni:
- servere – servere care trebuie configurate.
- serverul de instalare este serverul principal care asigură întregul proces de pregătire prin rețea.
De ce este nevoie de automatizare?
Să presupunem că există o sarcină: pregătirea masivă a serverelor de la zero, la un vârf – 30 pe zi. Servere de producători și modele diferiți, sisteme de operare diferite pot fi instalate pe ele și pot avea sau nu un hypervisor.
Ce operațiuni sunt incluse în procesul de configurare (fără automatizare):
- conectați o tastatură, un mouse, un monitor la server;
- configurați BIOS, RAID, IPMI;
- actualizați firmware-ul componentei;
- implementați o imagine a sistemului de fișiere (sau instalați un hypervisor și copiați mașini virtuale);
Notă. Alternativ, implementarea sistemului de operare este posibilă prin instalare cu un fișier de răspuns automat. Dar acest lucru nu va fi discutat în articol. Deși veți vedea mai jos că adăugarea acestei funcționalități nu este dificilă.
- configurați parametrii OS (nume de gazdă, IP etc.).
Cu această abordare, aceleași setări sunt efectuate secvenţial pe fiecare server. Eficiența unei astfel de lucrări este foarte scăzută.
Esența automatizării este eliminarea participării umane din procesul de pregătire a serverului. Cat mai mult posibil.
Automatizarea reduce timpul de nefuncționare dintre operațiuni și face posibilă furnizarea de mai multe servere simultan. Probabilitatea erorilor datorate factorilor umani este, de asemenea, mult redusă.

Cum se configurează automat serverele?
Să analizăm în detaliu toate etapele.
Aveți un server Linux pe care îl utilizați ca server de instalare PXE. Pe acesta sunt instalate și configurate servicii: DHCP, TFTP.
Deci, pornim serverul (care trebuie configurat) prin PXE. Să ne amintim cum funcționează:
- Pornirea în rețea este selectată pe server.
- Serverul încarcă PXE-ROM-ul plăcii de rețea și contactează serverul de instalare prin DHCP pentru a obține o adresă de rețea.
- Serverul de instalare DHCP emite o adresă, precum și instrucțiuni pentru descărcarea ulterioară prin PXE.
- Serverul încarcă bootloader-ul de rețea de pe serverul de instalare prin PXE, încărcarea ulterioară are loc în funcție de fișierul de configurare PXE.
- Bootarea are loc pe baza parametrilor primiți (kernel, initramfs, puncte de montare, imagine squashfs etc.).
Notă. Articolul descrie pornirea prin PXE prin modul BIOS. În prezent, producătorii implementează în mod activ modul de pornire UEFI. Pentru PXE, diferența va fi în configurația serverului DHCP și prezența unui bootloader suplimentar.
Să ne uităm la un exemplu de configurare a unui server PXE (meniul pxelinux).
Fișier 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 // переход на следующее меню
Fișier 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=”…”
Nucleul și initramf-urile în această etapă sunt o imagine Linux intermediară, cu ajutorul căreia va avea loc pregătirea și configurarea principală a serverului.
După cum puteți vedea, bootloader-ul transmite mulți parametri nucleului. Unii dintre acești parametri sunt utilizați de nucleul însuși. Și putem folosi unele în scopurile noastre. Acest lucru va fi discutat mai târziu, dar deocamdată vă puteți aminti că toți parametrii trecuți vor fi disponibili în imaginea intermediară Linux prin /proc/cmdline.
De unde le pot obține, kernel și initramfs?
Ca bază, puteți alege orice distribuție Linux. La ce acordăm atenție atunci când alegem:
- imaginea de boot trebuie să fie universală (disponibilitatea driverelor, capacitatea de a instala utilități suplimentare);
- Cel mai probabil, va trebui să personalizați initramfs.
Cum se face acest lucru în soluția noastră pentru X5? Am ales ca bază CentOS 7. Să încercăm următorul truc: pregătim viitoarea structură a imaginii, o împachetăm într-o arhivă și creăm un fișier initramfs care conține arhiva sistemului nostru de fișiere. Când imaginea este pornită, arhiva va fi dezarhivată în partiția tmpfs nou creată. În acest fel, vom obține o imagine Linux live minimală, dar complet funcțională, cu toate utilitățile necesare, constând din doar două fișiere: vmkernel și 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
Deci am specificat nucleul și initramfs care ar trebui să fie încărcate. Ca urmare, în această etapă, prin încărcarea imaginii linux intermediare prin PXE, vom primi consola OS.
Grozav, dar acum trebuie să transferăm controlul către „automatizarea” noastră.
Se poate face așa.
Să presupunem că după încărcarea imaginii intenționăm să transferăm controlul către scriptul mount.sh.
Să includem scriptul mount.sh în autorun. Pentru a face acest lucru, va trebui să modificați initramfs:
- despachetați initramfs (dacă folosim opțiunea initramfs de mai sus, aceasta nu este necesară)
- include cod în pornire care va analiza parametrii trecuți prin /proc/cmdline și va transfera controlul în continuare;
- pachet initramfs.
Notă. În cazul setului de instrumente X5, controlul încărcării este transferat în script /opt/x5/toolkit/bin/hook.sh с помощью override.conf в getty tty1 (ExecStart=…)
Deci, imaginea este încărcată, în care scriptul mount.sh începe la autorun. Apoi, scriptul mount.sh analizează parametrii trecuți (script_cmd=) în timpul execuției și lansează programul/scriptul necesar.
trusa de instrumente pentru etichete -Auto
nucleu...
anexează... nfs_toolkit_script=scripts/mount.sh script_cmd=master-install.sh
trusa de instrumente pentru etichete -coajă
nucleu...
anexează... nfs_toolkit_script=scripts/mount.sh script_cmd=/bin/bash

Aici în stânga este meniul PXE, în dreapta este diagrama de transfer de control.
Ne-am dat seama de transferul controlului. În funcție de alegerea meniului PXE, se lansează fie scriptul de auto-configurare, fie consola de depanare.
În cazul configurării automate, de pe serverul de instalare se montează directoarele necesare, care conțin:
- scenarii;
- şabloane BIOS/UEFI salvate pentru diverse servere;
- firmware;
- utilități de server;
- busteni
Apoi, scriptul mount.sh transferă controlul către scriptul master-install.sh din directorul de scripturi.
Arborele de script (ordinea în care sunt lansate) arată cam așa:
- master-install
- sharefunctions (funcții partajate)
- info (ieșire de informații)
- modele (setarea parametrilor de instalare pe baza modelului de server)
- prepare_utils (instalarea utilităților necesare)
- fwupdate (actualizare firmware)
- diag (diagnostic elementar)
- biosconf (setări BIOS/UEFI)
- clockfix (setarea orei pe placa de bază)
- srmconf (configurarea interfeței la distanță)
- raidconf (configurarea volumelor logice)
unul dintre:
- preinstalare (transferând controlul către sistemul de instalare sau hypervisor, cum ar fi ESXi)
- merged-install (începerea imediată a despachetării imaginii)
Acum știm:
- cum să pornești un server prin PXE;
- cum să transferați controlul către propriul script.
Hai sa continuăm. Următoarele întrebări au devenit relevante:
- Cum să identificăm serverul pe care îl pregătim?
- Ce utilitare și cum se configurează serverul?
- Cum să obțineți setări pentru un anumit server?
Cum să identificăm serverul pe care îl pregătim?
Este simplu - DMI:
dmidecode –s system-product-name
dmidecode –s system-manufacturer
dmidecode –s system-serial-number
Tot ce aveți nevoie este aici: furnizor, model, număr de serie. Dacă nu sunteți sigur că aceste informații sunt prezente pe toate serverele, le puteți identifica după adresa lor MAC. Sau în ambele moduri în același timp, dacă furnizorii de servere sunt diferiți și pe unele modele pur și simplu nu există informații despre numărul de serie.
Pe baza informațiilor primite, de pe serverul de instalare se montează foldere de rețea și se încarcă tot ce este necesar (utilități, firmware etc.).
Ce utilitare și cum se configurează serverul?
Voi oferi utilități pentru Linux pentru unii producători. Toate utilitățile sunt disponibile pe site-urile web oficiale ale vânzătorilor.

Cu firmware-ul, cred că totul este clar. Ele vin de obicei sub formă de fișiere executabile ambalate. Fișierul executabil controlează procesul de actualizare a firmware-ului și raportează codul de returnare.
BIOS și IPMI sunt de obicei configurate prin șabloane. Dacă este necesar, șablonul poate fi editat înainte de descărcare.
Utilitarele RAID de la unii furnizori pot fi, de asemenea, configurate folosind un șablon. Dacă nu este cazul, atunci va trebui să scrieți un script de configurare.
Procedura de configurare a RAID este cel mai adesea următoarea:
- Solicităm configurația curentă.
- Dacă există deja tablouri logice, le ștergem.
- Să ne uităm la ce discuri fizice sunt prezente și câte sunt.
- Creați o nouă matrice logică. Întrerupem procesul în cazul unei erori.
Cum să obțineți setări pentru un anumit server?
Să presupunem că setările tuturor serverelor vor fi stocate pe serverul de instalare. În acest caz, pentru a răspunde la întrebarea noastră, trebuie mai întâi să decidem cum să transferăm setările pe serverul de instalare.
La început, vă puteți descurca cu fișierele text. (În viitor, este posibil să doriți să utilizați un fișier text ca metodă alternativă pentru transferul setărilor.)
Puteți „parta” un fișier text pe serverul de instalare. Și adăugați montura sa în scriptul mount.sh.
Liniile vor arăta, de exemplu, astfel:
<număr de serie> <nume gazdă> <subrețea>
Aceste linii vor fi transferate în dosar de către inginer de la mașina sa de lucru. Și apoi, la configurarea unui server, parametrii pentru un anumit server vor fi citiți din fișier.
Dar, pe termen lung, este mai bine să folosiți o bază de date pentru a stoca setările, stările și jurnalele instalărilor de server.
Desigur, o bază de date nu este suficientă și va trebui să creați o parte client cu ajutorul căreia setările vor fi transferate în baza de date. Acest lucru este mai dificil de implementat în comparație cu un fișier text, dar, de fapt, totul nu este atât de dificil pe cât pare. Este foarte posibil să scrieți o versiune minimă a unui client care va transfera pur și simplu datele în baza de date. Iar pe viitor se va putea îmbunătăți programul client în modul gratuit (rapoarte, imprimare etichete, trimitere notificări etc. care îmi vine în minte).
Făcând o cerere specifică la baza de date și specificând numărul de serie al serverului, vom primi parametrii necesari pentru configurarea serverului.
În plus, nu va trebui să venim cu blocări pentru acces simultan, cum este cazul unui fișier text.
Putem scrie jurnalul de configurare în baza de date în toate etapele și controlăm procesul de instalare prin evenimente și steaguri ale etapelor de pregătire.
Acum știm cum:
- porniți serverul prin PXE;
- transferați controlul către scriptul nostru;
- identificați serverul care trebuie pregătit prin numărul său de serie;
- configurați serverul utilizând utilitățile corespunzătoare;
- transferați setările în baza de date a serverului de instalare folosind partea client.
Am aflat cum:
- serverul instalat primește setările necesare din baza de date;
- toate progresele pregătirii sunt înregistrate în baza de date (jurnal, evenimente, steaguri de etapă).
Dar diferitele tipuri de software pe care le instalați? Cum să instalezi un hypervisor, să copiezi o VM și să configurezi totul?
În cazul implementării unei imagini de sistem de fișiere (linux) pe hardware, totul este destul de simplu:
- După configurarea tuturor componentelor serverului, implementăm imaginea.
- Instalați bootloader-ul grub.
- Chrootăm și configurăm tot ce este necesar.
Cum să transferați controlul către programul de instalare a sistemului de operare (folosind ESXi ca exemplu).
- Organizam transferul de control de la scriptul nostru la instalatorul de hypervisor folosind fișierul de răspuns automat (kickstart):
- Ștergem partițiile curente de pe disc.
- Creați o partiție cu o dimensiune de 500 MB.
- Îl marchem ca bootabil.
- Formatați în FAT32.
- Copiem fișierele de instalare ESXi la rădăcină.
- Instalarea syslinux.
- Copiați syslinux.cfg în /syslinux/
default esxi
prompt 1
timeout 50
label esxi
kernel mboot.c32
append -c boot.cfg
- Copiați mboot.c32 în /syslinux.
- Boot.cfg ar trebui să aibă kernelopt=ks=ftp:// /ks_esxi.cfg
- Repornim serverul.
După repornirea serverului, programul de instalare ESXi se va descărca de pe hard diskul serverului. Toate fișierele de instalare necesare vor fi încărcate în memorie și apoi va începe instalarea ESXi, conform fișierului de răspuns automat specificat.
Iată câteva rânduri din fișierul de răspuns automat 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://' | 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
În această etapă, hypervisorul este instalat și configurat, iar mașinile virtuale sunt copiate.
Cum se configurează acum mașinile virtuale?
Am înșelat puțin: în timpul instalării am setat parametrul guestinfo.esxihost.id = "$SYSSN" în fișierul VM1.vmx și am indicat numărul de serie al serverului fizic din acesta.
Acum, după pornire, mașina virtuală (cu pachetul vmware-tools instalat) poate accesa acest parametru:
ESXI_SN=$(vmtoolsd --cmd "info-get guestinfo.esxihost.id")
Adică, VM-ul va putea să se identifice (știe numărul de serie al gazdei fizice), să facă o cerere către baza de date a serverului de instalare și să primească parametrii care trebuie configurați. Toate acestea sunt compilate într-un script, care ar trebui să fie lansat automat când guestos vm pornește (dar o dată: RunOnce).
Acum știm cum:
- porniți serverul prin PXE;
- transferați controlul către scriptul nostru;
- identificați serverul care trebuie pregătit prin numărul său de serie;
- configurați serverul utilizând utilitățile corespunzătoare;
- transferați setările în baza de date a serverului de instalare folosind partea client;
- configurați diferite tipuri de software, inclusiv implementarea hypervisorului esxi și configurarea mașinilor virtuale (toate automat).
Am aflat cum:
- serverul instalat primește setările necesare din baza de date;
- toate progresele pregătirii sunt înregistrate în baza de date (jurnal, evenimente, steaguri de etapă).
Linia de jos:
Cred că unicitatea acestei soluții constă în flexibilitatea, simplitatea, capacitățile și versatilitatea ei.
Vă rugăm să scrieți în comentarii ce părere aveți.
Sursa: www.habr.com
