Multitool PXE baseado em Raspberry Pi



Os engenheiros do data center geralmente enfrentam a tarefa de configuração inicial do servidor. Além disso, na maioria das vezes é necessário configurar não um ou dois equipamentos, mas várias dezenas ou mesmo centenas. Cada vez que um novo equipamento chega até nós, devemos não apenas verificá-lo minuciosamente antes de colocá-lo em operação, mas também configurá-lo adequadamente para funcionar com nossos sistemas internos.



Antes de prosseguir com o procedimento bastante trivial de configuração do BIOS e IPMI, devemos nos certificar de que cada componente do servidor possui a versão de firmware necessária. Na maioria dos casos, com raras exceções, é necessária uma versão atualizada, disponível no site do fabricante dos componentes específicos. Hoje vamos contar como surgiu a ideia de usar a agora popular "framboesa" para acelerar o processo.



Qual é a dificuldade



Parece que a tarefa é muito simples. Bem, vamos pegar uma distribuição Linux ativa, instalá-la em uma unidade flash USB, inicializar a partir dela e executar os procedimentos necessários. Mas não estava lá.



O problema é que cada fornecedor possui seus próprios métodos e utilitários para atualizar o firmware. Além disso, nem todos são capazes de funcionar corretamente no Linux. Alguns componentes, por exemplo, BIOS para servidores SuperMicro, é desejável costurar no MS-DOS. Para alguns componentes, por exemplo, placas de rede Mellanox, em alguns casos você precisa usar o Windows e alguns suportam firmware diretamente do Linux.



Portanto, precisaremos coletar uma imagem de inicialização múltipla e gravá-la em várias dezenas de unidades flash e, em seguida, inicializar a partir delas por um longo tempo e persistentemente, ou criar algo mais interessante e rápido. E é aqui que o uso de placas de rede de servidor com suporte para PXE (Preboot eXecution Environment, pronuncia-se pixie) vem à mente.



Pegamos o "raspberry", implantamos um servidor DHCP e TFTP ali, preparamos as imagens necessárias para o carregamento. Para carregar em massa várias dezenas de servidores, usamos apenas temporariamente um switch gigabit de 48 portas não gerenciado e pronto. Por padrão, a maioria dos servidores permite a inicialização PXE sem configuração adicional, portanto, isso é ideal.



Tomei um excelente artigo como base. a partir de Romanenko_Eugene, mas com correções para os recursos do Raspberry Pi e as tarefas a serem resolvidas. Vamos começar!



Geleia de framboesa



A primeira vez que fiz isso, a versão mais avançada do Raspberry Pi foi a terceira com uma placa de rede de 100 Mbps. Francamente, isso não é suficiente para a distribuição em massa de imagens pesadas, portanto, recomendo fortemente o uso do Raspberry Pi 4 atualmente disponível com uma porta de 1 Gb / s. Outra recomendação é usar um cartão de memória rápido e amplo sempre que possível.



Agora sobre a configuração inicial. Uma interface gráfica para tal coisa não é absolutamente necessária, então você pode baixar a versão Lite mais simples do sistema operacional Raspberry Pi OS. Descompactamos a imagem e carregamos a imagem para o cartão MicroSD de qualquer maneira conveniente, por exemplo, usando dd:



sudo dd if=<_> of=/dev/mmcblk0 bs=1M
      
      





Durante o processo de configuração, você pode configurar da maneira tradicional conectando um teclado e monitor ou via SSH. Para fazer o serviço SSH funcionar na inicialização, crie um arquivo vazio chamado ssh na seção / boot .



Como a porta de rede será usada para operação DHCP, você pode usar uma conexão Wi-Fi para acessar a Internet ou conectar outra placa de rede ao Malinka via USB. Aqui está um, por exemplo:





Agora vamos lançar o Raspberry Pi, conectá-lo à Internet e atualizar os repositórios e pacotes de software:



sudo apt update
      
      





sudo apt upgrade
      
      





Como estou usando outra placa de rede, a placa interna deve ser configurada para um endereço IP estático. Abra a configuração:



sudo nano /etc/dhcpcd.conf
      
      





Adicione as seguintes linhas:



interface eth0
static ip_address=192.168.50.1/24
      
      





Aqui, a eth0 é a placa de rede integrada do Raspberry Pi. É com a ajuda dele que será feita a distribuição dos endereços IP e o carregamento da rede. Agora instale o servidor tftp:



sudo apt install tftpd-hpa
      
      





Após a instalação, abra o arquivo de configuração:



sudo nano /etc/default/tftpd-hpa
      
      





Trazemos a linha para o seguinte formato:



TFTP_OPTIONS="--secure -l -v -r blksize"
      
      





Em geral, pode-se deixar tudo como está, mas testar cada vez em uma máquina separada às vezes não é muito conveniente. As opções -l -v -r blksize permitem que você teste tudo isso em uma VM VirtualBox sem problemas, corrigindo alguns problemas de compatibilidade. Agora instalamos um servidor DHCP para distribuição de endereços IP:



sudo apt install isc-dhcp-server
      
      





Abra o primeiro arquivo de configuração isc-dhcp-server:



sudo nano /etc/default/isc-dhcp-server
      
      





Indicamos explicitamente a interface na qual o servidor DHCP deve funcionar:



INTERFACESv4="eth0"
      
      





Agora abra o segundo config dhcpd.conf :



sudo nano /etc/dhcp/dhcpd.conf
      
      





Definimos os parâmetros de servidor necessários, a sub-rede a ser distribuída e também passamos o nome do arquivo carregador:



default-lease-time 600;
max-lease-time 7200;
ddns-update-style none;
authoritative;

subnet 192.168.50.0 netmask 255.255.255.0 {
        range 192.168.50.2 192.168.50.250;
        option broadcast-address 192.168.50.255;
        option routers 192.168.50.1;
        filename "pxelinux.0";
}

      
      





Salvamos o arquivo e agora temos que baixar o bootloader, os módulos necessários e formar o menu PXE. Vamos começar baixando um conjunto de carregadores Syslinux, no meu caso a versão 5.01 é a mais conveniente:



wget https://mirrors.edge.kernel.org/pub/linux/utils/boot/syslinux/syslinux-5.01.zip
      
      





Desempacotando:



unzip syslinux-5.01.zip
      
      





Agora precisamos encontrar e extrair o módulo memdisk , que pode carregar imagens ISO inteiras na RAM, o carregador pxelinux.0 e o resto dos módulos comboot . Executamos sequencialmente os comandos que encontrarão e copiarão tudo o que for encontrado no diretório / srv / tftp:



find ./ -name "memdisk" -type f|xargs -I {} sudo cp '{}' /srv/tftp/
      
      





find ./ -name "pxelinux.0"|xargs -I {} sudo cp '{}' /srv/tftp/
      
      





find ./ -name "*.c32"|xargs -I {} sudo cp '{}' /srv/tftp/
      
      





Após esta operação, precisamos criar um arquivo de configuração diretamente para o menu exibido na tela PXE. Vá para o nosso diretório:



cd /srv/tftp
      
      





Crie um diretório chamado pxelinux.cfg e navegue até ele:



sudo mkdir pxelinux.cfg
      
      





cd pxelinux.cfg
      
      





Criamos um arquivo de configuração:



sudo nano default
      
      





Como exemplo, vamos pegar a excelente distribuição GRML ao vivo e baixá-la via PXE. Abaixo está um exemplo de configuração concluída:



UI vesamenu.c32                  
PROMPT 0
MENU TITLE Raspberry Pi PXE Server
MENU BACKGROUND bg.png
LABEL bootlocal
   menu label Boot from HDD
   kernel chain.c32
   append hd0 0
   timeout 0
TEXT HELP
Boot from first HDD in your system
ENDTEXT
LABEL grml
   menu label GRML Linux
KERNEL grml/boot/grml32full/vmlinuz
APPEND root=/dev/nfs rw nfsroot=192.168.50.1:/srv/tftp/grml/ live-media-path=/live/grml32-full boot=live lang=us nomce apm=power-off noprompt noeject initrd=grml/boot/grml32full/initrd.img vga=791
LABEL reboot
    menu label Reboot
    kernel reboot.c32
TEXT HELP
Reboot server
ENDTEXT

      
      





Provavelmente, vale a pena parar um pouco aqui e descobrir o que cada linha faz:



  • UI vesamenu.c32 - use o módulo vesamenu.c32 para exibir o menu;
  • PROMPT 0 - destaca o item zero do menu;
  • TÍTULO DO MENU Servidor Raspberry Pi PXE - defina o nome geral do menu;
  • FUNDO DO MENU bg.png - elemento de design, use bg.png como imagem de fundo.


A imagem de fundo pode ser feita com antecedência. Por padrão, uma imagem de 640x480 com uma profundidade de cor de no máximo 24 bits, no formato PNG ou JPG, é adequada. Deve ser copiado para / srv / tftp com antecedência . Agora vamos dar uma olhada em cada seção. A primeira seção foi introduzida por conveniência. Se você precisar inicializar a partir do primeiro disco rígido, registramos:



  • LABEL bootlocal - nome da seção interna;
  • rótulo do menu Boot from HDD - como o menu do usuário será exibido;
  • kernel chain.c32 - usamos o módulo chain.c32, que pode inicializar de várias mídias;
  • anexar hd0 0 - indica explicitamente que o carregamento deve ser feito a partir da primeira partição do primeiro disco rígido;
  • tempo limite 0 - aqui você pode definir um tempo limite em segundos, após o qual o download começará automaticamente, ou especificando 0 para remover o cronômetro.
  • TEXT HELP - indica o início do texto de ajuda para o usuário;
  • Inicialize a partir do primeiro HDD em seu sistema - texto de dica;
  • ENDTEXT - indica o final do texto da dica.


Aproximadamente da mesma forma, formamos a seção para recarregar. A única diferença será a chamada para o módulo reboot.c32, que na verdade envia o carro para reiniciar. Bem, antes de examinar o que a terceira seção, que carrega a distribuição GRML, faz, vamos falar sobre o que realmente será carregado e como.



Tudo é um arquivo



A própria imagem ISO está disponível no site desta distribuição ao vivo. Baixe-o e renomeie-o por conveniência, no exemplo usaremos a versão de 32 bits:



wget https://download.grml.org/grml32-full_2020.06.iso
      
      





mv grml32-full_2020.06.iso grml.iso
      
      





Agora precisamos forçar de alguma forma essa imagem a inicializar. Por um lado, você pode usar o módulo memdisk e forçá-lo a carregar primeiro todo o conteúdo "bruto" da imagem diretamente na RAM e então transferir o controle sobre a inicialização. Mas esse método só é bom para imagens muito pequenas, por exemplo, é conveniente inicializar o MS-DOS dessa maneira. Imagens grandes demoram muito para carregar na memória e nem sempre funcionam adequadamente.



Portanto, você ainda deve "destruir" a imagem e transferir apenas o kernel e livefs para inicializar. Mas outros arquivos do disco podem ser fornecidos ao sistema mediante solicitação usando o servidor NFS. Essa abordagem funciona de forma muito mais rápida e adequada, mas requer gestos adicionais, como a instalação de um servidor NFS.



Isso é feito de uma forma elementar:



sudo apt install nfs-kernel-server
      
      





Para não bagunçar os arquivos, crie um diretório separado para grml:



sudo mkdir /srv/tftp/grml
      
      





Precisamos montar o ISO, então cuidaremos do ponto de montagem temporário:



sudo mkdir /tmp/iso
      
      





Montamos a imagem. O sistema irá avisá-lo de que a imagem está montada no modo somente leitura:



sudo mount -o loop grml.iso /tmp/iso
      
      





Copie recursivamente o conteúdo da imagem para nosso diretório separado:



sudo cp -R /tmp/iso/* /srv/tftp/grml
      
      





Para evitar problemas com os direitos de acesso, mudamos o proprietário e atribuímos recursivamente a este diretório os direitos da série "Free home, live who you want":



sudo chown -R nobody:nogroup /srv/tftp/grml/
      
      





sudo chmod -R 755 /srv/tftp/grml/
      
      





Agora é fácil dizer ao servidor NFS que ele deve fornecer o diretório / srv / tftp / grml para qualquer endereço IP de nossa sub-rede:



sudo nano /etc/exports
      
      





Registramos a linha:



/srv/tftp/grml 192.168.50.0/24(rw,sync,no_subtree_check)
      
      





Atualize a lista e reinicie o servidor NFS:



sudo exportfs -a
      
      





sudo systemctl restart nfs-kernel-server
      
      





Agora, finalmente, temos a oportunidade de dividir corretamente o processo de download em dois estágios condicionais. O primeiro passo é carregar o kernel e o sistema de arquivos ao vivo. O segundo estágio está puxando todos os outros arquivos pelo NFS. É hora de dar uma olhada na seção restante:



  • LABEL grml - nome da seção;
  • rótulo de menu GRML Linux - exibir no menu;
  • KERNEL grml / boot / grml32full / vmlinuz - especifica o caminho para o kernel, relativo ao root / srv / tftp ;
  • APPEND root = / dev / nfs rw nfsroot = 192.168.50.1: / srv / tftp / grml / live-media-path = / live / grml32-full boot = live lang = us nomce apm = power-off noprompt noeject initrd = grml /boot/grml32full/initrd.img vga = 791 - aqui dizemos que estamos usando NFS, escrevemos os caminhos para a raiz condicional, definimos alguns parâmetros adicionais recomendados na documentação e indicamos o caminho relativo para initrd.


Agora tudo o que resta é iniciar o servidor TFTP e DHCP sequencialmente e você pode tentar inicializar no PXE. Se tudo for feito corretamente, você verá o menu criado:





Selecionando o item GRML Linux, pressione Enter e veja se o processo de carregamento da imagem foi bem-sucedido:





Assim, obtivemos a capacidade de inicializar pela rede a distribuição GRML, que é popular entre os administradores de sistema. Mas e quanto ao mesmo MS-DOS e como você pode preparar independentemente uma imagem para atualizar o BIOS. Vamos conversar mais sobre isso.



Em DOS, nós confiamos



O sistema operacional dos anos 80 do último milênio ainda está em uso no século 21? Não importa o quão estranho possa parecer, mas para algumas tarefas específicas o MS-DOS ainda é relevante e bastante útil por si só. Uma dessas tarefas é atualizar o firmware do BIOS nos servidores.



Vamos pegar algumas placas-mãe como exemplo, por exemplo, Supemicro X11SSL-F e baixar a atualização do BIOS do site oficial. Dentro, vemos um conjunto semelhante de arquivos:



user@linux:~//X11SSLF0_B26> ls -l
 16592
-rw-r--r-- 1 user users   169120   1  2015 AFUDOSU.SMC
-rw-r--r-- 1 user users     5219  20  2003 CHOICE.SMC
-rw-r--r-- 1 user users    22092  27  2014 FDT.smc
-rw-r--r-- 1 user users     3799  15  2016 FLASH.BAT
-rw-r--r-- 1 user users     3739  22  2019 Readme for UP X11 AMI  BIOS.txt
-rw-r--r-- 1 user users 16777216  25 23:48 X11SSLF0.B26

      
      





Vemos que já temos um arquivo BAT pronto que nos permite fazer o flash do BIOS. Mas para fazer isso, você deve ter um servidor já carregado no MS-DOS. Agora vamos mostrar exatamente como fazer isso.



Em primeiro lugar, precisamos preparar uma pequena imagem bruta do disco rígido com o sistema operacional. Crie uma nova máquina virtual por meio do Oracle VM VirtualBox com um pequeno disco de 32 megabytes. Selecionamos o formato QCOW, após todas as manipulações pode ser facilmente convertido para raw.



Certamente todos vocês sabem onde obter imagens de disquetes com o MS-DOS, então monte-os dentro da máquina virtual e execute a instalação:





Mudamos as imagens do disquete no drive virtual duas vezes e depois de literalmente 20 segundos temos uma imagem qcow com um novo sistema operacional MS-DOS 6.22:





A maneira mais fácil agora de copiar arquivos para este disco é montá-lo em qualquer outra máquina virtual executando Windows ou Linux. Após esta operação, remontamos o disco na máquina virtual do MS-DOS e verificamos se os arquivos estão visíveis:





Se desejar, você pode até configurar o autoload para executar um arquivo BAT para que o BIOS seja atualizado automaticamente. Mas lembre-se de que esta é uma operação potencialmente perigosa e você a faz por sua própria conta e risco. Agora desligue a máquina virtual e converta-a em uma imagem bruta usando qemu-img.



qemu-img convert -f qcow -O raw DOS.qcow dos.img
      
      





Copie a imagem IMG resultante para um diretório separado de nosso servidor TFTP:



sudo mkdir /srv/tftp/dos
      
      





sudo cp dos.img /srv/tftp/dos
      
      





Agora abra a configuração /srv/tftp/pxelinux.cfg/default para edição e adicione mais um item ao menu:



LABEL DOS
        kernel memdisk
        initrd dos/dos.img
        append raw

      
      





Salvamos a configuração e agora temos um novo item de menu no menu PXE, selecionando qual carregamos a imagem criada:





Da mesma forma, você pode criar imagens contendo utilitários e para se divertir com jogos DOS antigos.



No Windows Veritas



Vamos agora tentar inicializar a imagem Live a partir do WinPE (ambiente de pré-instalação do Windows). Freqüentemente, o download de uma versão completa simplesmente não é necessário, apenas um número limitado de funções é suficiente. Essa coisa encontra uso real ao atualizar alguns dispositivos.



O mesmo Mellanox, absorvido pela Nvidia há um ano, lança o utilitário Mellanox Firmware Tools para atualizar suas placas de rede em diferentes versões para WinPE. Claro, agora já existem várias opções de MFT disponíveis, mas algumas vezes nos deparamos com a necessidade de costurar a versão WinPE.



Criar sua própria imagem WinPE e integrar o software necessário não é uma tarefa muito difícil, mas sua explicação está além do escopo deste artigo. Para dominar esse processo em detalhes, você pode visitar o excelente recurso winpe.ru . Como exemplo, usaremos qualquer montagem pronta para demonstrar o processo de lançamento.



Freqüentemente, esses conjuntos são imagens iso ou arquivos rar com imagens iso. Antes de escolher essa imagem, precisamos obter o bootloader apropriado.



wimboot é um bootloader bastante simples, capaz de carregar imagens no formato wim (Windows Imaging Format). Ele pode ser usado em conjunto com o syslinux ou com seu irmão mais avançado, o iPXE... Crie um diretório separado em / srv / tftp :



sudo mkdir wimboot
      
      





cd wimboot
      
      





Baixe o próprio bootloader:



wget https://github.com/ipxe/wimboot/releases/latest/download/wimboot
      
      





Agora é hora de montar a imagem. Crie um diretório temporário em / tmp :



sudo mkdir winpe
      
      





Vá para o diretório com a imagem de montagem ISO baixada e execute:



sudo mount -o loop <_> /tmp/winpe
      
      





Crie um diretório em / srv / tftp , onde colocaremos os arquivos de que precisamos:



sudo mkdir /srv/tftp/winpe
      
      





Agora pesquisamos na montagem e copiamos 4 arquivos:



sudo cp BOOTMGR /srv/tftp/winpe
      
      





sudo cp bcd /srv/tftp/winpe
      
      





sudo cp boot.sdi /srv/tftp/winpe
      
      





sudo cp boot.wim /srv/tftp/winpe
      
      





O assunto é pequeno - adicione a seguinte seção ao arquivo de configuração /srv/tftp/pxelinux.cfg/default :



LABEL WinPE
        menu label WinPE
        com32 linux.c32 wimboot/wimboot
        append initrdfile=winpe/BOOTMGR,winpe/bcd,winpe/boot.sdi,winpe/boot.wim

      
      





Na verdade, usamos o módulo linux.c32 para carregar o bootloader, uma excelente tautologia , e passamos os parâmetros para ele no formato familiar ao wimboot. Assim, o wimboot é carregado primeiro e, em seguida, os arquivos necessários são descompactados e executados sequencialmente.





É importante levar em consideração que o upload dos arquivos é feito via TFTP, o que não é muito rápido e conveniente. Em geral, você pode modificar ligeiramente a configuração e ampliá-la de uma maneira diferente. Mas para tarefas utilitárias simples, isso é o bastante.





Em vez de uma conclusão



Não há know-how neste artigo, mas quando surgiu a necessidade, o Raspberry Pi fez um ótimo trabalho. Ela não precisou procurar uma tomada adicional, a porta USB do servidor gratuito mais próximo era perfeita. Não há problemas adicionais em encontrar um lugar em uma prateleira lotada até os olhos. Funciona exatamente como deveria e suas pequenas dimensões permitem que você o tenha sempre à mão.



Na verdade, existem muitos tutoriais na rede para configurar o netboot. O único problema é que meios e abordagens diferentes são usados ​​para imagens diferentes. Escolher a abordagem certa às vezes pode levar muito tempo, e eu realmente espero que este material ajude muitas pessoas a economizar tempo ao resolver várias tarefas relacionadas à necessidade de implantar rapidamente o PXE em um computador de placa única Raspberry Pi.






All Articles