Como eu testo kernels remotos sem instalação?

Correr o kernel sem disco rígido: Introdução

Geralmente é muito útil testar as compilações do kernel sem ter que o instalar num disco rígido e reiniciar o computador para iniciar com esse novo kernel que foi compilado. Arrancar o computador através de um kernel localizado num computador remoto (servidor), é algo que acho muito útil.

Neste artigo vou explicar os básicos para configurar um servidor e clientes para que estes possam arrancar com diferentes imagens do kernel através da rede. Assume-se que as máquinas cliente tem, no mínimo, uma placa Ethernet ligada à mesma rede do servidor que vamos utilizar.

Existem duas formas para um arranque sem disco numa máquina cliente. Uma delas é utilizar a ramdisk como a partição root e a outra é utilzar a partição root através de NFS (Network File System). No artigo que se segue, ambas as opções são examinadas.

Configuração do NFS Server

Utilizando o gestor de pacotes da sua distribuição (yum, yast, apt, conary) instale o pacote nfs-utils (o nome pode variar entre distribuições). Uma vez instalado, altere o /etc/exports com informações sobre directórios e opções. Quando concluir, inicie o serviço de NFS:

[root@localhost ~]# /etc/init.d/nfs start
[root@localhost ~]# /etc/init.d/portmap start

Para fazer estas alterações permanentes:

[root@localhost ~]# chkconfig --level 345 nfs on
[root@localhost ~]# chkconfig --level 345 portmap on

Exemplo do ficheiro /etc/exports

/tftpboot/installroot     192.168.10.0/255.255.255.0(rw,async,no_root_squash)

A derivativa no_root_squash é muito importante quando utilizando NFS

Configuração do servidor de PXE

É necessário instalar o neoPXE. Se o gestor de pacotes não o fez, ou se efectuou uma instalação através da fonte, deverá introduzir uma nova entrada em /etc/rc.sysinit para garantir de que o serviço será automaticamente iniciado após reiniciar o computador. Edite o ficheiro de configuração (normalmente em /usr/local/etc/neopxe.conf) e adicione as entradas necessárias.

Exemplo do ficheiro neopxe.conf

  1. ip_addr=192.168.10.1
  2. prompt=Press [F8] for menu...
  3. prompt_timeout=10
  4. service=1,192.168.10.1,pxelinux.0,Linux

Configuração do servidor de TFTP

Novamente, utilizando o gestor de pacotes, ou através da fonte, instale os pacotes xinetd e tftp-server (nome pode alterar). Configure o ficheiro /etc/xinetd.d/tftp.

Exemplo do ficheiro /etc/xinetd.d/tftp

  1. service tftp
  2. {
  3. socket_type = dgram
  4. protocol = udp
  5. wait = yes
  6. user = root
  7. server = /usr/local/sbin/in.tftpd
  8. server_args = -s /tftpboot -r blksize
  9. disable = no
  10. per_source = 11
  11. cps = 100 2
  12. flags = IPv4
  13. }

Configuração do servidor de DHCP (opcional)

A configuração deste serviço é extremamente importante, pois pode causar problemas na rede se for mal configurado. Instale o software dhcp-server (nome pode mudar) e faça a sua configuração. Normalmente a configuração do servidor de DHCP é feita no ficheiro /etc/dhcpd.conf. Consulte a documentação da sua distribuição caso este não seja o caso.

Exemplo do ficheiro dhcpd.conf

  1. ddns-update-style ad-hoc;
  2. class "PXE" {
  3. match if substring(option vendor-class-identifier, 0, 9) = "PXEClient";
  4. option vendor-class-identifier "PXEClient";
  5. }
  6.  
  7. subnet 192.168.10.0 netmask 255.255.255.0 {
  8. range 192.168.10.10 192.168.10.254;
  9. default-lease-time 1200;
  10. max-lease-time 1800;
  11. option subnet-mask 255.255.255.0;
  12. }

O método do ramdisk

O ramdisk é uma porção da memória RAM utilizada como disco rígido, para armazenar um ficheiro ou pasta. Para arrancar o Linux, uma grande variedade de sistemas de ficheiros estão disponíveis (ext2, ext3, ext4, ReiserFS, Minix, etc...), no entanto, devido à forma como o ramdisk funciona (não é persistente - alterações não são mantidas após desligar a máquina), um sistema de ficheiros Journaled, como o ext3 ou o JFS, não faz muito sentido, e daí não serem utilizados em ramdisk.

Assume-se, durante este método, que a distribuição de GNU/Linux utilizada é a mesma quer na máquina que desenvolvemos o kernel, quer na máquina onde o kernel vai ser testado.

Limitações do ramdisk

Uma das limitações é o facto que o ramdisk não pede ser aumentado ou duminuido de uma forma dinâmica. Ainda para mais, a memória que decidimos utilizar o ramdisk vai ser marcada como ocupada na RAM e não será libertada, daí, não podemos mais contar com ela para o uso 'normal' do computador.

Neste exemplo criamos uma ramdisk mínima, num sistema Fedora. Caso tenha alguma dúvida a criar na sua distribuição, por favor utilize o Fórum do BR.KernelNewbies.

A preparar o directório de destino

Precisamos de um directório onde os pacotes serão instalados. Criar o directório 'installroot' em /tftpboot.

[root@localhost ~]# mkdir -p /tftpboot/installroot

De forma a obrigar o yum a instalar os pacotes neste directório em vez de instalar em /, temos que utilizar a seguinte sintaxe:

  1. [root@localhost ~]# yum clean all
  2. [root@localhost ~]# yum -y --installroot=/tftpboot/installroot install basesystem filesystem bash

Uma vez que este comando termine sem erros, veja o tamanho do directório utilizando o du:

  1. [root@localhost ~]# du -sh /tftpboot/installroot
  2. 279M /tftpboot/installroot

Criar o ramdisk e copiar ficheiros

Agora vamos criar um ficheiro preenchido com zeros (de tamanho ~200M) e formatar esse ficheiro com o sistema de ficheiros ext2:

  1. [root@localhost /tftpboot]# dd if=/dev/zero of=/tftpboot/ramdisk.ext2 bs=1k count=524288
  2. 524288+0 records in
  3. 524288+0 records out
  4. 536870912 bytes (537 MB) copied, 14.0037 seconds, 38.3 MB/s
  5. [root@localhost /tftpboot]# mkfs.ext2 -v -m 0 -b 4096 ./ramdisk.ext2
  6. mke2fs 1.39 (29-May-2006)
  7. ./ramdisk.ext2 is not a block special device.
  8. Proceed anyway? (y,n) y
  9. Filesystem label=
  10. OS type: Linux
  11. Block size=4096 (log=2)
  12. Fragment size=4096 (log=2)
  13. 131072 inodes, 131072 blocks
  14. 0 blocks (0.00%) reserved for the super user
  15. First data block=0
  16. Maximum filesystem blocks=134217728
  17. 4 block groups
  18. 32768 blocks per group, 32768 fragments per group
  19. 32768 inodes per group
  20. Superblock backups stored on blocks:
  21. 32768, 98304
  22.  
  23. Writing inode tables: done
  24. Writing superblocks and filesystem accounting information: done
  25.  
  26. This filesystem will be automatically checked every 30 mounts or
  27. 180 days, whichever comes first. Use tune2fs -c or -i to override.

Agora é necessário mountar este ficheiro e copiar os contêudos da 'installroot', depois desmontar e comprimir o ficheiro com gzip.

  1. [root@localhost ~]# cd /tftpboot
  2. [root@localhost /tftpboot]# mount -o loop -t ext2 ./ramdisk.ext2 ./ramdisk
  3. [root@localhost /tftpboot]# mount -o loop -t ext2 ./ramdisk.ext2 ./ramdisk.dir
  4. [root@localhost /tftpboot]# rsync -av ./installroot/ ./ramdisk.dir
  5. [root@localhost /tftpboot]# umount ./ramdisk.dir/
  6. [root@localhost /tftpboot]# cat ramdisk.ext2 | gzip -9 > ramdisk.ext2.gz

Este ramdisk foi criada com um sistema de ficheiros mínimo. Pode acontecer não ter os módulos necessários para o arranque do kernel que está a compilar. Se for este o caso, utilize este guia para fazer uma CrossCompilation dos módulos. Esse guia estará disponível neste site brevemente em Português.

Se quisermos adicionar mais conteúdo à nossa ramdisk, podemos instalar, por exemplo:

[root@localhost ~]# yum install -y autofs nfs nfs-utils-lib nfs-utils dhclient

Para termos rede, é necessário os ficheiros de configuração:

  1. [root@localhost ~]# cat ./etc/sysconfig/network-scripts/ifcfg-eth1
  2. # Broadcom Corporation NetXtreme BCM5703X Gigabit Ethernet
  3. DEVICE=eth1
  4. BOOTPROTO=dhcp
  5. ONBOOT=yes

Activar a rede:

  1. [root@localhost ~]# cat ./etc/sysconfig/network
  2. NETWORKING=yes

Se o kernel for compilado com módulos, é importante não esquecer de instalar os módulos no local correcto.

Utilizar o método de CPIO baseado em initramfs

Devido ao facto do ramdisk não libertar a memória da RAM, uma outra opção é de utilizar CPIO baseado em initramfs. Apenas algumas alterações são necessárias:

Criar um link para o init na root

[root@localhost /tftpboot/installroot]# ln -s ./sbin/init ./init

Criar o arquivo do CPIO (imagem de root do initramfs

[root@localhost /tftpboot/installroot]# find | cpio -ocv | gzip -9 > ../initrd.cpio.gz

É necessário, também, mudar o nosso ficheiro de configuração do neoPXE para incluir estas alterações (exemplo de ficheiro de configuração):

  1. label linux-initrd
  2. MENU LABEL Ramdisk kernel
  3. kernel os_images/fc6/vmlinuz
  4. append initrd=os_images/fc6/initrd-2.6.23-omyx.img ramdisk_size=524288 load_ramdisk=1 root=/dev/ram0 rw console=ttyS0 console=tty0 debug

Root através de NFS

Apesar de ser razoavelmente fácil de configurar um ambiente para testes através do ramdisk, existem várias limitações que o podem tornar uma opção não muito prática para várias pessoas. Desta forma, montar a root numa partilha NFS permite-nos testar uma distribuição com X, e ter um ambiente de testes mais prático.

Configurar o kernel

Entre no directório com a arvore do kernel e corra make menuconfig:

  1. [root@localhost /tftpboot]# cd /space/src/linux-2.6/
  2. [root@localhost /space/src/linux-2.6]# make menuconfig

Verifique que "TCP/IP networking" é seleccionado. Escolha IP:Kernel level autoconfiguration e IP:DHCP support e IP:RARP. Escolha também Root File System on NFS presente em File Systems -> Network File Systems.

Root através de NFS: Arranque

Parâmetros na linha de comandos:

root=/dev/nfs

/dev/nfs é um pseudo dispositivo (pode não existir) para informar o kernel que o root está sobre NFS, e não num dispositivo real, presente no directório /dev.

nfsroot=[<server-ip>:]<root-dir>[,<nfs-options>]

Se este parâmetro não foi dado na linha de comandos de kernel, o de defeito /tftpboot/%s é utilizado. Onde %s é uma representação do endereço de IP. Mais informações em Documentation/nfsroot.txt.

ip=<client-ip>:<server-ip>:<gw-ip>:<netmask>:<hostname>:<device>:<autoconf>

Exemplo de ficheiro de configuração do PXELinux

  1. label NFS Autoconf linux-2.6.23-Net
  2. MENU LABEL NFS linux-2.6.23-net
  3. kernel os_images/fc6/bzImage.net
  4. append netdev=eth1 root=/dev/nfs rw ip=192.168.10.10:192.168.10.1:192.168.10.1:255.255.255.0:testsrv:eth1:none nfsroot=192.168.10.1:/tftpboot/installroot console=ttyS0 console=tty0 debug