Hola, soy Denis y una de mis áreas de trabajo es el desarrollo de soluciones de infraestructura en X5. Hoy quisiera compartir con ustedes cómo se puede implementar un sistema automático de preparación de servidores utilizando herramientas de acceso público. En mi opinión, es una solución interesante, simple y flexible.

Con la preparación se entiende: convertir un nuevo servidor de fábrica en un servidor completamente configurado con un sistema operativo Linux o con el hipervisor ESXi (instalación de Windows no se discute en este artículo). servidores Windows в данной статье не обсуждается).
Términos:
- servidores – servidores que necesitan ser configurados.
- servidor de instalación – el servidor principal que garantiza todo el proceso de preparación a través de la red.
¿Por qué es necesaria la automatización?
Supongamos que hay una tarea: preparar servidores masivamente desde cero, hasta 30 por día en el pico. Servidores de diferentes fabricantes y modelos, sobre los que se pueden instalar diferentes sistemas operativos, puede haber o no un hipervisor.
¿Qué operaciones entran en el proceso de configuración (sin automatización):
- conectar teclado, ratón, monitor al servidor;
- configurar BIOS, RAID, IPMI;
- actualizar el firmware de los componentes;
- desplegar una imagen del sistema de archivos (o instalar el hipervisor y copiar máquinas virtuales);
Nota. Como opción, el despliegue del sistema operativo puede ser a través de la instalación con un archivo de respuestas automáticas. Pero esto no se discutirá en el artículo. Aunque más adelante verán que agregar esta funcionalidad no es difícil.
- configurar los parámetros del sistema operativo (hostname, IP, otros).
Con este enfoque, se realizan configuraciones idénticas de forma secuencial en cada servidor. La eficiencia de este trabajo es muy baja.
La esencia de la automatización es excluir la participación humana en el proceso de preparación del servidor. Tanto como sea posible.
Gracias a la automatización, se reduce el tiempo de inactividad entre operaciones y se permite preparar varios servidores simultáneamente. También se disminuye significativamente la probabilidad de errores debido al factor humano.

¿Cómo se lleva a cabo la configuración automática de servidores?
Analicemos todos los pasos en detalle.
Usted tiene un servidor Linux que utiliza como servidor de instalación PXE. Tiene instalados y configurados los servicios: DHCP, TFTP.
Así que, arrancamos el servidor (que necesita ser configurado) a través de PXE. Recordemos cómo funciona esto:
- En el servidor se ha seleccionado el arranque a través de la red.
- El servidor carga el PXE-ROM de la tarjeta de red y contacta al servidor de instalación a través de DHCP para obtener la dirección de red.
- El servidor de instalación DHCP asigna la dirección y también proporciona instrucciones para la carga a través de PXE.
- El servidor descarga el cargador de red desde el servidor de instalación por PXE, y la carga continua según el archivo de configuración de PXE.
- Se produce la carga según los parámetros obtenidos (núcleo, initramfs, puntos de montaje, imagen squashfs, etc.).
Nota. En este artículo se describe la carga por PXE a través del modo BIOS. Actualmente, los fabricantes están implementando activamente el modo de arranque UEFI. Para PXE, la diferencia será en la configuración del servidor DHCP y la presencia de un cargador adicional.
Veamos un ejemplo de configuración de un servidor PXE (menú pxelinux).
Archivo pxelinux.cfg/default:
default menu.c32
prompt 0
timeout 100
menu title Menú de Arranque PXE X5
LABEL Menú del Servidor de Instalación
MENU LABEL Servidor de Instalación
KERNEL menu.c32
APPEND pxelinux.cfg/installserver
LABEL Menú VMware
MENU LABEL Instalación de VMware ESXi
KERNEL menu.c32
APPEND pxelinux.cfg/vmware
LABEL toolkit \\ menú por defecto
MENU LABEL Herramientas de Scripting de Linux
MENU default
KERNEL menu.c32
APPEND pxelinux.cfg/toolkit \\ ir al siguiente menúArchivo pxelinux.cfg/toolkit:
prompt 0
timeout 100
menu title Menú de Arranque PXE X5
label mainmenu
menu label ^Volver al Menú Principal
kernel menu.c32
append pxelinux.cfg/default
label x5toolkit-auto \\ por defecto — modo automático
menu label autoinstalación del toolkit x5
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 \\ para depuración - consola
menu label shell del toolkit x5
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=”…”El núcleo y el initramfs en esta etapa son una imagen linux intermedia, con la cual se llevará a cabo la preparación y configuración principal del servidor.
Como puedes ver, el cargador pasa muchos parámetros al núcleo. Algunos de estos parámetros son utilizados por el propio núcleo. Y algunos podemos usarlos para nuestros propios fines. Esto se explicará más adelante, pero por ahora solo recuerda que todos los parámetros pasados estarán disponibles en la imagen linux intermedia a través de /proc/cmdline.
¿Dónde conseguir el núcleo y el initramfs?
Se puede elegir cualquier distribución de linux como base. ¿Qué debemos tener en cuenta al elegir?
- La imagen de arranque debe ser universal (presencia de controladores, posibilidad de instalar utilidades adicionales);
- es probable que se necesite personalizar el initramfs.
¿Cómo se hace esto en nuestra solución para X5? Como base se eligió CentOS 7. Realizaremos el siguiente truco: prepararemos la futura estructura de la imagen, la empacaremos en un archivo y crearemos el initramfs, dentro del cual estará nuestro archivo de sistema de archivos. Al cargar la imagen, el archivo se desplegará en la partición tmpfs creada. Así, obtendremos una imagen live de Linux minimalista, pero completa, con todas las utilidades necesarias, compuesta por solo dos archivos: 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.gzEntonces, hemos especificado el núcleo e initramfs que deben cargarse. Como resultado, en esta etapa, al cargar la imagen intermedia de Linux por PXE, obtendremos la consola del SO.
Genial, pero ahora necesitamos transferir el control a nuestra "automatización".
Esto se puede hacer de la siguiente manera.
Supongamos que, después de cargar la imagen, planeamos transferir el control al script mount.sh.
Incluiré el script mount.sh en el inicio automático. Para esto será necesario modificar el initramfs:
- desplegar initramfs (si usamos la variante de initramfs mencionada anteriormente, esto no es necesario)
- incluir en el autoarranque el código que analizará los parámetros pasados a través de /proc/cmdline y transferirá el control posteriormente;
- empaquetar el initramfs.
Nota. En el caso del toolkit X5, el control de arranque se transfiere al script /opt/x5/toolkit/bin/hook.sh с помощью override.conf в getty tty1 (ExecStart=…)
Así que se carga la imagen, en la que se inicia el script mount.sh en el arranque automático. Luego, el script mount.sh, en su ejecución, analiza los parámetros pasados (script_cmd=) y ejecuta el programa/script necesario.
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

Aquí, en la parte izquierda, está el menú PXE, y a la derecha – el esquema de transferencia de control.
Hemos comprendido la transferencia de control. Dependiendo de la elección en el menú PXE, se inicia el script de auto-configuración o la consola de depuración.
En el caso de la configuración automática, se montan los directorios necesarios desde el servidor de instalación, que contienen:
- scripts;
- plantillas guardadas de BIOS/UEFI de varios servidores;
- firmwares;
- utilidades para servidores;
- logs.
Luego, el script mount.sh transfiere el control al script master-install.sh en el directorio con los scripts.
El árbol de scripts (el orden de su ejecución) se ve aproximadamente así:
- master-install
- sharefunctions (funciones compartidas)
- info (salida de información)
- models (instalación de parámetros de instalación basados en el modelo del servidor)
- prepare_utils (instalación de utilidades necesarias)
- fwupdate (actualización de firmware)
- diag (diagnóstico elemental)
- biosconf (configuración de BIOS/UEFI)
- clockfix (ajuste de tiempo en la placa madre)
- srmconf (configuración de la interfaz remota)
- raidconf (configuración de volúmenes lógicos)
uno de:
- preinstall (transferencia de control al instalador del sistema operativo o hipervisor, por ejemplo ESXi)
- merged-install (inicio directo de la descompresión de la imagen)
Ahora sabemos:
- cómo arrancar el servidor por PXE;
- cómo transferir el control a un script propio.
Continuemos. Ahora surgen las siguientes preguntas:
- ¿Cómo identificar el servidor que estamos preparando?
- ¿Qué utilidades y cómo configurar el servidor?
- ¿Cómo obtener configuraciones para un servidor específico?
¿Cómo identificar el servidor que estamos preparando?
Es sencillo – DMI:
dmidecode –s system-product-name
dmidecode –s system-manufacturer
dmidecode –s system-serial-numberAquí está toda la información necesaria: proveedor, modelo, número de serie. Si no está seguro de que esta información esté presente en todos los servidores, puede identificarlos por la dirección MAC. O por ambos métodos a la vez, si los proveedores de los servidores son diferentes y en algunos modelos la información sobre el número de serie simplemente no está disponible.
Con la información obtenida, se montan las carpetas de red desde el servidor de instalación y se carga todo lo necesario (utilidades, firmware y más).
¿Qué utilidades y cómo configurar el servidor?
Aquí están las utilidades para Linux de algunos fabricantes. Todas las utilidades están disponibles en los sitios web oficiales de los proveedores.

Con los firmware, creo que todo está claro. Por lo general, se entregan en forma de archivos ejecutables empaquetados. El archivo ejecutable controla el proceso de actualización del firmware y reporta el código de retorno.
BIOS e IPMI generalmente se configuran mediante plantillas. Si es necesario, la plantilla se puede editar antes del arranque.
Las utilidades RAID de algunos proveedores también pueden configurarse mediante plantillas. Si no es así, será necesario escribir un script de configuración.
El orden de configuración del RAID suele ser el siguiente:
- Solicitamos la configuración actual.
- Si ya hay matrices lógicas, las borramos.
- Vemos qué discos físicos están presentes y cuántos hay.
- Creamos una nueva matriz lógica. Interrumpimos el proceso en caso de error.
¿Cómo obtener configuraciones para un servidor específico?
Supongamos que la configuración de todos los servidores se almacenará en el servidor de instalación. En tal caso, para responder a nuestra pregunta, primero debemos decidir: de qué manera transferir la configuración al servidor de instalación.
Al principio se puede gestionar perfectamente con archivos de texto. (En el futuro, se puede usar el archivo de texto como un método de respaldo para la transmisión de configuraciones).
Se puede "compartir" un archivo de texto en el servidor de instalación. Y agregar su montaje en el script mount.sh.
Las líneas serán, por ejemplo, de este tipo:
Estas líneas serán transferidas a un archivo por el ingeniero desde su máquina de trabajo. Y luego, al configurar el servidor, los parámetros para el servidor específico se leerán del archivo.
Pero, en perspectiva, es mejor utilizar una base de datos para almacenar configuraciones, estados y registros de instalaciones de servidores.
Por supuesto, no se puede depender solo de una base de datos, y será necesario crear una parte cliente, mediante la cual se transmitirán las configuraciones a la base. Implementar esto es más complicado que con un archivo de texto, pero, en realidad, no es tan difícil como parece. La versión mínima del cliente, que simplemente transmitirá datos a la base de datos, se puede escribir fácilmente por uno mismo. Y posteriormente se puede mejorar el programa cliente de manera libre (informes, impresión de etiquetas, envío de notificaciones y todo lo que se te ocurra).
Haciendo una consulta en la base y especificando el número de serie del servidor, obtendremos los parámetros necesarios para la configuración del servidor.
Además, no necesitaremos inventar bloqueos para el acceso simultáneo, como en el caso de un archivo de texto.
El registro de configuración lo podemos escribir en la base de datos en todas las etapas y controlar el proceso de instalación a través de eventos y banderas de etapas de preparación.
Ahora sabemos cómo:
- cargar el servidor por PXE;
- transferir el control a nuestro script;
- identificar el servidor que debe ser preparado por su número de serie;
- configurar el servidor con las utilidades correspondientes;
- transferir configuraciones a la base de datos del servidor de instalación mediante la parte cliente.
Hemos averiguado cómo:
- el servidor a instalar obtiene las configuraciones necesarias de la base de datos;
- todo el progreso de la preparación se registra en la base de datos (registros, eventos, banderas de etapas).
¿Qué pasa con los diferentes tipos de software a instalar? ¿Cómo instalar un hipervisor, copiar una VM y configurar todo esto?
En el caso de desplegar una imagen del sistema de archivos (linux) en hardware, todo es bastante simple:
- Después de configurar todos los componentes del servidor, desplegamos la imagen.
- Instalamos el cargador grub.
- Realizamos chroot y configuramos todo lo necesario.
Cómo transferir el control al instalador del sistema operativo (con un ejemplo de ESXi).
- Organizamos la transferencia de control desde nuestro script al instalador del hipervisor mediante un archivo de respuesta automática (kickstart):
- Eliminamos las particiones actuales en el disco.
- Creemos una partición de 500MB.
- La marcamos como de arranque.
- La formateamos en FAT32.
- Copiamos los archivos de instalación de ESXi en la raíz de esta partición.
- Instalamos syslinux.
- Copiamos syslinux.cfg en /syslinux/
default esxi
prompt 1
timeout 50
label esxi
kernel mboot.c32
append -c boot.cfg- Copiamos mboot.c32 en /syslinux.
- En boot.cfg debe haber kernelopt=ks=ftp:///ks_esxi.cfg
- Reiniciamos el servidor.
Después de reiniciar el servidor, se iniciará el instalador de ESXi desde su disco duro. Todos los archivos necesarios del instalador se cargarán en la memoria y luego comenzará la instalación de ESXi, de acuerdo con el archivo de respuesta automática especificado.
Aquí incluiré algunas líneas del archivo de respuesta automática ks_esxi.cfg:
%firstboot --interpreter=busybox
…
# obtenemos el número de serie
SYSSN=$(esxcli hardware platform get | grep Serial | awk -F " " '{print $3}')
# obtenemos la IP
IPADDRT=$(esxcli network ip interface ipv4 get | grep vmk0 | awk -F " " '{print $2}')
LAST_OCTET=$(echo $IPADDRT | awk -F'.' '{print $4}')
# conectamos el servidor de instalación NFS
esxcli storage nfs add -H is -s /srv/nfs_share -v nfsshare1
# copiamos la configuración temporal de ssh para usar el cliente ssh
mv /etc/ssh /etc/ssh.tmp
cp -R /vmfs/volumes/nfsshare1/ssh /etc/
chmod go-r /etc/ssh/ssh_host_rsa_key
# copiamos ovftool para desplegar la VM ahora, y posiblemente sea útil después
cp -R /vmfs/volumes/nfsshare1/ovftool /vmfs/volumes/datastore1/
# desplegamos la VM
/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
# obtenemos la línea con la configuración de nuestro servidor
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
...
# generamos el script de configuración de red
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
# establecemos el parámetro guestinfo.esxihost.id, indicamos el número de serie
echo "guestinfo.esxihost.id = "$SYSSN"" >> /vmfs/volumes/datastore1/VM1/VM1.vmx
echo "guestinfo.esxihost.id = "$SYSSN"" >> /vmfs/volumes/datastore1/VM2/VM2.vmx
...
# actualizamos la información en la base de datos
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 ...""
# devolvemos la configuración SSH
rm -rf /etc/ssh
mv /etc/ssh.tmp /etc/ssh
# configuramos la red y reiniciamos
esxcli system hostname set --fqdn=esx-${G_NICK}.x5.ru
/vmfs/volumes/datastore1/netconf.sh
reboot
En esta etapa, el hipervisor está instalado y configurado, y se han copiado las máquinas virtuales.
¿Cómo configurar ahora las máquinas virtuales?
Hemos hecho un pequeño truco: durante la instalación, establecimos el parámetro guestinfo.esxihost.id = "$SYSSN" en el archivo VM1.vmx, indicando el número de serie del servidor físico.
Ahora, después de arrancar, la máquina virtual (con el paquete vmware-tools instalado) puede acceder a este parámetro:
ESXI_SN=$(vmtoolsd --cmd "info-get guestinfo.esxihost.id")Es decir, la VM podrá identificarse (sabe el número de serie del host físico), hacer una consulta a la base de datos del servidor de instalación y obtener los parámetros que deben configurarse. Todo esto se presenta en un script que debe ejecutarse automáticamente al iniciar la VM guestos (pero solo una vez: RunOnce).
Ahora sabemos cómo:
- cargar el servidor por PXE;
- transferir el control a nuestro script;
- identificar el servidor que debe ser preparado por su número de serie;
- configurar el servidor con las utilidades pertinentes;
- transmitir configuraciones a la base de datos del servidor de instalación a través del cliente;
- configurar diferentes tipos de software, incluyendo implementar el hipervisor ESXi y configurar máquinas virtuales (todo automáticamente).
Hemos averiguado cómo:
- el servidor a instalar obtiene las configuraciones necesarias de la base de datos;
- todo el progreso de la preparación se registra en la base de datos (registros, eventos, banderas de etapas).
Conclusión:
Creo que la singularidad de esta solución radica en su flexibilidad, simplicidad, capacidades y versatilidad.
Por favor, escribe en los comentarios qué piensas.
Fuente: habr.com
