Provisioning bare metal fai-da-te o preparazione automatica dei server da zero

Ciao, sono Denis e una delle mie aree di attività è lo sviluppo di soluzioni infrastrutturali presso X5. Oggi vorrei condividere con voi come implementare un sistema di preparazione automatica del server basato su strumenti disponibili pubblicamente. Secondo me questa è una soluzione interessante, semplice e flessibile.

Provisioning bare metal fai-da-te o preparazione automatica dei server da zero

Per preparazione intendiamo: trasformare un nuovo server pronto all'uso in un server completamente configurato con sistema operativo. Linux o con l'hypervisor ESXi (l'implementazione di server Windows non è discussa in questo articolo).

condizioni:

  • server – server che devono essere configurati.
  • il server di installazione è il server principale che fornisce l'intero processo di preparazione sulla rete.

Perché è necessaria l’automazione?

Diciamo che c'è un compito: preparare massicciamente i server da zero, al massimo – 30 al giorno. Su di essi possono essere installati server di produttori e modelli diversi, sistemi operativi diversi e possono avere o meno un hypervisor.

Quali operazioni sono incluse nel processo di configurazione (senza automazione):

  • collegare una tastiera, un mouse, un monitor al server;
  • configurare BIOS, RAID, IPMI;
  • aggiornare il firmware dei componenti;
  • distribuire un'immagine del file system (o installare un hypervisor e copiare macchine virtuali);

Nota. In alternativa, la distribuzione del sistema operativo è possibile tramite l'installazione con un file di risposta automatica. Ma di questo non parleremo nell’articolo. Anche se vedrai di seguito che aggiungere questa funzionalità non è difficile.

  • configurare i parametri del sistema operativo (nome host, IP, ecc.).

Con questo approccio, le stesse impostazioni vengono eseguite in sequenza su ciascun server. L'efficienza di tale lavoro è molto bassa.

L'essenza dell'automazione è eliminare la partecipazione umana dal processo di preparazione del server. Per quanto possibile.

L'automazione riduce i tempi di inattività tra le operazioni e consente di fornire più server contemporaneamente. Anche la probabilità di errori dovuti a fattori umani è notevolmente ridotta.

Provisioning bare metal fai-da-te o preparazione automatica dei server da zero

Come vengono configurati automaticamente i server?

Analizziamo nel dettaglio tutte le fasi.

Hai un server Linux che usi come server di installazione PXE. Su di esso sono installati e configurati i servizi: DHCP, TFTP.

Quindi, avviamo il server (che deve essere configurato) tramite PXE. Ricordiamo come funziona:

  • Sul server è selezionato l'avvio di rete.
  • Il server carica la PXE-ROM della scheda di rete e contatta il server di installazione tramite DHCP per ottenere un indirizzo di rete.
  • Il server di installazione DHCP rilascia un indirizzo e istruzioni per ulteriori download tramite PXE.
  • Il server carica il bootloader di rete dal server di installazione tramite PXE, l'ulteriore caricamento avviene in base al file di configurazione PXE.
  • L'avvio avviene in base ai parametri ricevuti (kernel, initramfs, mount points, immagine squashfs, ecc.).

Nota. L'articolo descrive l'avvio tramite PXE tramite la modalità BIOS. Attualmente, i produttori stanno implementando attivamente la modalità di avvio UEFI. Per PXE la differenza sarà nella configurazione del server DHCP e nella presenza di un bootloader aggiuntivo.

Diamo un'occhiata ad un esempio di configurazione di un server PXE (menu pixelinux).

File 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 // переход на следующее меню

File 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=”…”

Il kernel e initramfs in questa fase sono un'immagine Linux intermedia, con l'aiuto della quale avverrà la preparazione e la configurazione principale del server.

Come puoi vedere, il bootloader passa molti parametri al kernel. Alcuni di questi parametri vengono utilizzati dal kernel stesso. E possiamo usarne alcuni per i nostri scopi. Questo verrà discusso più avanti, ma per ora puoi solo ricordare che tutti i parametri passati saranno disponibili nell'immagine Linux intermedia tramite /proc/cmdline.

Dove posso trovarli, kernel e initramfs?
Come base, puoi scegliere qualsiasi distribuzione Linux. A cosa prestiamo attenzione nella scelta:

  • l'immagine di avvio deve essere universale (disponibilità di driver, possibilità di installare utilità aggiuntive);
  • Molto probabilmente dovrai personalizzare initramfs.

Come viene fatto questo nella nostra soluzione per X5? Come base è stato scelto CentOS 7. Proviamo il seguente trucco: preparare la futura struttura dell'immagine, comprimerla in un archivio e creare un initramfs, all'interno del quale si troverà l'archivio del nostro file system. Durante il caricamento dell'immagine, l'archivio verrà espanso nella partizione tmpfs creata. In questo modo otterremo un'immagine Linux live minima ma completa con tutte le utilità necessarie, composta da soli due file: vmkernel e 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

Quindi abbiamo specificato il kernel e l'initramfs che dovrebbero essere caricati. Di conseguenza, in questa fase, caricando l'immagine Linux intermedia tramite PXE, riceveremo la console del sistema operativo.

Ottimo, ma ora dobbiamo trasferire il controllo alla nostra “automazione”.

Si può fare così.

Supponiamo che dopo aver caricato l'immagine intendiamo trasferire il controllo allo script mount.sh.
Includiamo lo script mount.sh nell'esecuzione automatica. Per fare ciò dovrai modificare l'initramfs:

  • decomprimere initramfs (se utilizziamo l'opzione initramfs sopra, questo non è richiesto)
  • includere codice all'avvio che analizzerà i parametri passati attraverso /proc/cmdline e trasferirà ulteriormente il controllo;
  • comprimere initramfs.

Nota. Nel caso del toolkit X5, il controllo del caricamento viene trasferito allo script /opt/x5/toolkit/bin/hook.sh с помощью override.conf в getty tty1 (ExecStart=…)

Quindi, viene caricata l'immagine, in cui lo script mount.sh inizia con l'esecuzione automatica. Successivamente, lo script mount.sh analizza i parametri passati (script_cmd=) durante l'esecuzione e avvia il programma/script necessario.

toolkit per etichette-auto
nocciolo...
aggiungi...nfs_toolkit_script=scripts/mount.sh script_cmd=master-install.sh

toolkit per etichette-conchiglia
nocciolo...
aggiungi...nfs_toolkit_script=scripts/mount.sh script_cmd=/bin/bash

Provisioning bare metal fai-da-te o preparazione automatica dei server da zero

Qui a sinistra c'è il menu PXE, a destra c'è il diagramma di trasferimento del controllo.

Abbiamo capito il trasferimento del controllo. A seconda della scelta del menu PXE, viene avviato lo script di autoconfigurazione o la console di debug.

Nel caso della configurazione automatica, dal server di installazione vengono montate le directory necessarie, che contengono:

  • script;
  • modelli BIOS/UEFI salvati per vari server;
  • firmware;
  • utilità del server;
  • registri

Successivamente, lo script mount.sh trasferisce il controllo allo script master-install.sh dalla directory degli script.

L'albero degli script (l'ordine in cui vengono lanciati) assomiglia a questo:

  • installazione principale
  • sharefunctions (funzioni condivise)
  • info (output di informazioni)
  • modelli (impostazione dei parametri di installazione in base al modello del server)
  • prepare_utils (installazione delle utilità necessarie)
  • fwupdate (aggiornamento del firmware)
  • diag (diagnostica elementare)
  • biosconf (impostazioni BIOS/UEFI)
  • clockfix (impostazione dell'ora sulla scheda madre)
  • srmconf (configurazione dell'interfaccia dell'interfaccia remota)
  • raidconf (configurazione dei volumi logici)

uno di:

  • preinstallazione (trasferimento del controllo al sistema operativo o al programma di installazione dell'hypervisor, come ESXi)
  • installazione unita (avvio immediato della decompressione dell'immagine)

Ora sappiamo:

  • come avviare un server tramite PXE;
  • come trasferire il controllo al tuo script.


Continuiamo. Le seguenti domande sono diventate rilevanti:

  • Come identificare il server che stiamo preparando?
  • Quali utilità e come configurare il server?
  • Come ottenere le impostazioni per un server specifico?

Come identificare il server che stiamo preparando?

È semplice - DMI:

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

Tutto ciò di cui hai bisogno è qui: fornitore, modello, numero di serie. Se non sei sicuro che queste informazioni siano presenti in tutti i server, puoi identificarli tramite il loro indirizzo MAC. Oppure in entrambi i modi contemporaneamente, se i fornitori di server sono diversi e su alcuni modelli semplicemente non ci sono informazioni sul numero di serie.

In base alle informazioni ricevute, dal server di installazione vengono montate le cartelle di rete e viene caricato tutto il necessario (utility, firmware, ecc.).

Quali utilità e come configurare il server?

Fornirò utilità per Linux per alcuni produttori. Tutte le utilità sono disponibili sui siti Web ufficiali dei fornitori.

Provisioning bare metal fai-da-te o preparazione automatica dei server da zero

Con il firmware, penso che tutto sia chiaro. Di solito si presentano sotto forma di file eseguibili confezionati. Il file eseguibile controlla il processo di aggiornamento del firmware e riporta il codice di ritorno.

BIOS e IPMI vengono solitamente configurati tramite modelli. Se necessario, il modello può essere modificato prima del download.

Anche le utilità RAID di alcuni fornitori possono essere configurate utilizzando un modello. In caso contrario, dovrai scrivere uno script di configurazione.

La procedura per configurare il RAID è molto spesso la seguente:

  • Richiediamo la configurazione attuale.
  • Se sono già presenti array logici, li cancelliamo.
  • Diamo un'occhiata a quali dischi fisici sono presenti e quanti ce ne sono.
  • Crea un nuovo array logico. Interrompiamo il processo in caso di errore.

Come ottenere le impostazioni per un server specifico?

Supponiamo che le impostazioni di tutti i server verranno archiviate sul server di installazione. In questo caso, per rispondere alla nostra domanda, dobbiamo prima decidere come trasferire le impostazioni sul server di installazione.

All'inizio puoi cavartela con i file di testo. (In futuro, potresti voler utilizzare un file di testo come metodo di fallback per trasferire le impostazioni.)

È possibile “condividere” un file di testo sul server di installazione. E aggiungi il suo mount allo script mount.sh.

Le linee, ad esempio, saranno simili a queste:

<numero di serie> <nome host> <sottorete>

Queste righe verranno trasferite nel file dall'ingegnere dalla sua macchina da lavoro. Quindi, quando si configura un server, i parametri per un server specifico verranno letti dal file.

Ma, a lungo termine, è meglio utilizzare un database per archiviare impostazioni, stati e registri delle installazioni del server.

Naturalmente, il database da solo non è sufficiente e sarà necessario creare una parte client con l'aiuto della quale le impostazioni verranno trasferite al database. Questo è più difficile da implementare rispetto a un file di testo, ma in realtà tutto non è così difficile come sembra. È del tutto possibile scrivere una versione minima del client che trasferirà semplicemente i dati nel database da solo. E in futuro sarà possibile migliorare il programma client in modalità gratuita (report, stampa di etichette, invio di notifiche, ecc., mi viene in mente).

Facendo una specifica richiesta al database e specificando il numero di serie del server, riceveremo i parametri necessari per la configurazione del server.

Inoltre, non avremo bisogno di inventare blocchi per l'accesso simultaneo, come nel caso di un file di testo.

Possiamo scrivere il log di configurazione nel database in tutte le fasi e controllare il processo di installazione attraverso eventi e flag delle fasi di preparazione.

Ora sappiamo come:

  • avviare il server tramite PXE;
  • trasferire il controllo al nostro script;
  • identificare il server da preparare tramite il suo numero di serie;
  • configurare il server utilizzando le apposite utilità;
  • trasferire le impostazioni al database del server di installazione utilizzando la parte client.

Abbiamo scoperto come:

  • il server installato riceve le impostazioni necessarie dal database;
  • tutti i progressi della preparazione sono registrati nel database (registri, eventi, bandiere di scena).

E i diversi tipi di software che installi? Come installare un hypervisor, copiare una VM e configurare il tutto?

Nel caso di distribuzione di un'immagine del file system (linux) sull'hardware, tutto è abbastanza semplice:

  • Dopo aver configurato tutti i componenti del server, distribuiamo l'immagine.
  • Installa il bootloader grub.
  • Effettuiamo il chroot e configuriamo tutto ciò che è necessario.

Come trasferire il controllo al programma di installazione del sistema operativo (utilizzando ESXi come esempio).

  • Organizziamo il trasferimento del controllo dal nostro script al programma di installazione dell'hypervisor utilizzando il file di risposta automatica (kickstart):
  • Eliminiamo le partizioni correnti sul disco.
  • Crea una partizione con una dimensione di 500 MB.
  • Lo contrassegniamo come avviabile.
  • Formattare in FAT32.
  • Copiamo i file di installazione di ESXi nella root.
  • Installazione di syslinux.
  • Copia syslinux.cfg in /syslinux/

default esxi
prompt 1
timeout 50
label esxi
kernel mboot.c32
append -c boot.cfg

  • Copia mboot.c32 in /syslinux.
  • Boot.cfg dovrebbe avere kernelopt=ks=ftp:// /ks_esxi.cfg
  • Riavviamo il server.

Dopo il riavvio del server, il programma di installazione di ESXi verrà scaricato dal disco rigido del server. Tutti i file di installazione necessari verranno caricati in memoria e quindi inizierà l'installazione di ESXi, in base al file di risposta automatica specificato.

Ecco alcune righe dal file di risposta automatica 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

In questa fase, l'hypervisor viene installato e configurato e le macchine virtuali vengono copiate.

Come configurare le macchine virtuali adesso?

Abbiamo imbrogliato un po': durante l'installazione abbiamo impostato il parametro guestinfo.esxihost.id = "$SYSSN" nel file VM1.vmx e in esso indicato il numero di serie del server fisico.

Ora, dopo l'avvio, la macchina virtuale (con il pacchetto vmware-tools installato) può accedere a questo parametro:

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

La VM sarà cioè in grado di identificarsi (conosce il numero di serie dell'host fisico), effettuare una richiesta al database del server di installazione e ricevere i parametri da configurare. Tutto questo è compilato in uno script, che dovrebbe essere lanciato automaticamente all'avvio di guestos vm (ma una volta: RunOnce).

Ora sappiamo come:

  • avviare il server tramite PXE;
  • trasferire il controllo al nostro script;
  • identificare il server da preparare tramite il suo numero di serie;
  • configurare il server utilizzando le apposite utilità;
  • trasferire le impostazioni al database del server di installazione utilizzando la parte client;
  • configurare vari tipi di software, inclusa la distribuzione dell'hypervisor esxi e la configurazione di macchine virtuali (tutto automaticamente).

Abbiamo scoperto come:

  • il server installato riceve le impostazioni necessarie dal database;
  • tutti i progressi della preparazione sono registrati nel database (registri, eventi, bandiere di scena).


La linea di fondo:

Credo che l'unicità di questa soluzione risieda nella sua flessibilità, semplicità, capacità e versatilità.

Per favore scrivi nei commenti cosa ne pensi.

Fonte: habr.com

Aggiungi un commento