Blogue ·
De uma resposta DHCP a uma instalação pronta
Netboot, segunda parte. Depois da oferta: o script de arranque, o ficheiro de respostas, a chamada que ninguém escreve e quem publica somas de verificação.
Por Provibr
Levar uma máquina a aceitar uma oferta de netboot é a parte sobre a qual toda a gente escreve. Nós também escrevemos, depois de perder uma semana com o endereço de destino de uma resposta de proxy-DHCP.
A parte a seguir a essa quase não tem cobertura, e é onde vivem as falhas verdadeiras. Uma máquina que arranca e depois fica para sempre parada numa pergunta é pior do que uma que nunca arrancou, porque parece progresso. Esta é a segunda metade: o que tem de ser verdade entre a chegada da oferta e o aparecimento de um pedido de início de sessão, e quais dessas coisas falham em silêncio.
As cinco coisas que são servidas
Assim que o cliente tem uma oferta e um ficheiro de arranque, uma instalação sem assistência são cinco artefactos. Nenhum deles é opcional, e o último é aquele que as pessoas deixam de fora.
| # | O quê | Servido por | Falha como |
|---|---|---|---|
| 1 | Script de arranque | HTTP | A máquina cai numa shell |
| 2 | Kernel | HTTP | O arranque aborta |
| 3 | Initrd | HTTP | O arranque aborta |
| 4 | Ficheiro de respostas | HTTP | O instalador faz uma pergunta e espera |
| 5 | Chamada de retorno de conclusão | O sistema instalado | Fica tudo suspenso até um prazo terminar |
A coluna interessante é a última. Os itens 1 a 3 falham alto, no ecrã, de uma forma que alguém repara. Os itens 4 e 5 falham como uma instalação que parece estar a correr e nunca acaba.
Scripts de arranque e o problema do marcador
O script de arranque tem de nomear URL absolutos, e não os consegue conhecer no momento em que o perfil é escrito: o endereço de quem serve os ficheiros depende do segmento em que a máquina apareceu.
Por isso o perfil contém um marcador que é substituído no momento de servir. O nosso é @@PROVIBR_BASE@@, e a sua forma é uma escolha deliberada e não uma preferência de estilo.
A forma óbvia seria ${BASE}. É exatamente o que não se deve fazer, porque o iPXE expande ${...} ele próprio. Uma substituição que não chega a acontecer torna-se uma cadeia vazia em vez de um erro, e acaba-se a olhar para
chain http:///vmlinuzsem perceber o que se passa com o servidor web. Um delimitador que o carregador de arranque não reconhece transforma uma falha silenciosa de substituição numa falha visível.
As três linhas de comando de kernel que interessam, depois de se retirar a marca:
# Ubuntu (subiquity)
kernel <kernel> initrd=<initrd> ip=dhcp autoinstall ds=nocloud;s=<dir>/ --- || goto failed
# Debian (preseed)
kernel <kernel> initrd=<initrd> auto=true priority=critical ip=dhcp url=<file> DEBIAN_FRONTEND=text --- quiet || goto failed
# RHEL family (Anaconda)
kernel <kernel> initrd=<initrd> ip=dhcp inst.repo=<tree> inst.ks=<file> inst.text || goto failedTrês instaladores, três vocabulários completamente diferentes para a mesma ideia, e o argumento que transporta o ficheiro de respostas escreve-se de maneira diferente em cada um. ds= recebe um diretório; url= e inst.ks= recebem um ficheiro. Trocar isso dá um instalador que arranca e depois faz a primeira pergunta.
As quatro chaves de autoinstall que decidem se aquilo acaba
O autoinstall do Ubuntu merece um parágrafo próprio, porque num segmento isolado quatro chaves separam uma instalação que termina de uma que não termina, e nenhuma delas é sobre discos ou utilizadores:
interactive-sections: []: sem ela, o subiquity ainda se detém para perguntar alguma coisa.refresh-installer.update: false: sem ela, vai primeiro à procura de um instalador mais recente.apt.fallback: offline-install: sem ela, fica à espera do arquivo antes de desistir.drivers.install: false: mesma classe de problema, mesmo resultado.
A falha é a mesma em todos os casos: um ecrã que parece ocupado. Não há erro, porque do ponto de vista do instalador nada correu mal.
Há uma opção equivalente para o suporte de instalação. O initrd de netboot do Ubuntu descompacta um suporte de instalação para um tmpfs e instala a partir dele; se não lhe disser onde está esse suporte, vai à internet procurar um. Num segmento sem ligação para o exterior, é essa a diferença entre funcionar e quatro minutos de nada seguidos de uma linha de comandos do busybox.
A chamada de retorno que ninguém escreve
O item 5 da lista é uma única linha num script de pós-instalação que vai buscar um URL, e é a peça que mais vezes falta numa montagem caseira.
Sem ela não há acontecimento nenhum que signifique terminou. O instalador reinicia, a máquina arranca, e o sistema que iniciou a instalação não faz ideia, pelo que espera pelo prazo que tiver e depois comunica um tempo esgotado numa máquina que se instalou na perfeição.
Dois pormenores tornam isto menos incómodo do que parece. Primeiro, entregue o gancho no modelo em vez de o documentar, para que quem escreve o seu próprio script de pós-instalação não tenha de saber que ele existe. Segundo, tenha um gancho de falha além do gancho de sucesso: uma instalação que falha às 04:00 e o diz é uma experiência de apoio diferente de uma que fica calada.
E mantenha dois relógios, não um. O comando que inicia uma instalação deve terminar assim que os ouvintes estiverem a funcionar e a sessão for aceite, e não quando a instalação acabar; o nosso tem um prazo de 90 segundos para isso, contra um orçamento de instalação de uma hora que é imposto dos dois lados. Um prazo único para ambos significa ou um trabalho parado na interface durante uma hora sem fazer nada, ou uma instalação morta por demorar o tempo que as instalações demoram.
Que fornecedores publicam uma soma de verificação, medido
Se a máquina vai buscar um kernel e um initrd por HTTP a um espelho, alguma coisa deve verificar o que voltou. A forma de o fazer é fixar um sha256 no perfil e verificá-lo depois da transferência, no sítio que faz a transferência.
Isso só funciona se o fornecedor publicar uma. Partimos do princípio de que a resposta era «na maior parte não», escrevemos isso, e afinal estava errado em três de quatro casos. O que é realmente publicado, medido a 2026-09-02:
| Fornecedor | Kernel + initrd de netboot | Onde |
|---|---|---|
| Debian | Sim | SHA256SUMS ao lado de installer-amd64/current/images/ |
| Família RHEL | Sim | [checksums] no .treeinfo junto à árvore |
| Ubuntu (ISO live server) | Sim | SHA256SUMS ao lado da versão |
| Ubuntu (kernel + initrd de netboot) | Não | Nenhum ficheiro de somas no diretório de netboot, e o tarball também não consta das somas da versão |
O custo desse pressuposto errado não foi uma indisponibilidade; foi pior, de uma forma discreta. Ativos que podiam ter sido fixados ficaram marcados como não verificáveis, e os perfis diziam de si próprios que não eram instaláveis enquanto o fornecedor publicava a resposta à vista de todos. Quatro de cinco artefactos nos dois primeiros perfis.
O comportamento para quando uma soma de verificação de facto não existe merece ser desenhado de propósito. O nosso deixa a fixação vazia, marca o ativo como pendente, e o perfil declara-se não instalável até um administrador colar um resumo. Isso é deliberadamente mais barulhento do que transferir na mesma. Um kernel não verificado obtido por HTTP a partir de um espelho é o sítio de maior valor para atacar um sistema de aprovisionamento, e «não conseguimos verificar isto, por isso fizemo-lo à mesma» não é uma política.
O que «mantido» pode querer dizer
Entregamos dez perfis base: Ubuntu Server 24.04 e 26.04, Debian 12 e 13, Rocky Linux 9 e 10, AlmaLinux 9 e 10, CentOS Stream 10, Fedora Server 44.
O estado de suporte associado a cada um é calculado, não escrito à mão. Um perfil só se pode dizer mantido quando tiver uma execução verificada nos dois caminhos de firmware, BIOS e UEFI. Só um dos dois dá «pré-visualização». Nenhum dos dois dá «não mantido».
Fazer disso uma regra em vez de um campo compensa a pequena quantidade de código. Uma etiqueta escrita à mão vale exatamente o cuidado de quem a escreveu, e esta é uma etiqueta pela qual um cliente põe uma máquina em jogo.
O que obriga a ser claro sobre onde isso nos deixa hoje. O Ubuntu Server 26.04 e o Debian 13 instalaram-se por completo e sem assistência num segmento isolado, numa máquina BIOS. O caminho UEFI foi reparado na mesma ronda, e repará-lo não é o mesmo que executá-lo. Nenhum perfil de origem está portanto maintained no momento em que isto é escrito, e os perfis da família RHEL não foram sequer executados numa máquina real: foram escritos a partir da documentação dos fornecedores e medidos contra ficheiros de origem reais, o que é uma afirmação mais fraca do que parece visto de fora.
Em separado, oferecer o netboot como forma de criar uma máquina nova está desligado por predefinição na nossa plataforma, à espera de exatamente uma coisa: uma máquina real a instalar-se assim, em firmware real. O caminho que existe e é usado é a reinstalação por cima de uma máquina existente. Um sinalizador de funcionalidade que está ligado porque o código está escrito, e não porque se observou a coisa a funcionar, produz um botão de encomenda que encalha a meio com o primeiro cliente real.
Pequenas coisas que custam uma tarde cada
- Valide os caminhos dos ficheiros servidos. Sem barra inicial, sem
.., sem barras invertidas, uma única classe de caracteres. Quem serve os ficheiros está dentro da rede de alguém, com um sistema de ficheiros por trás. - Oculte a linha de auditoria. Registe que ficheiro foi servido e se transportava um segredo, nunca o conteúdo. Quem precisar do conteúdo pode voltar a gerar o perfil.
- Não deixe o ficheiro de respostas ser uma segunda fonte de verdade sobre o suporte de instalação. O argumento do kernel e o ficheiro de respostas nomeiam ambos de onde vêm os pacotes; derivar os dois de uma única definição é a única maneira de se manterem iguais.
- Parta do princípio de que ninguém está a olhar para a consola. Todas as escolhas acima são escolhas sobre o que acontece quando a instalação vai no minuto seis de oito e não há ninguém na sala.
Esta é a segunda parte do texto sobre porque é que o netboot UEFI falha onde o BIOS funciona, e saiu da construção da instalação em rede no Provibr. Os pormenores estão na documentação de netboot.