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.
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
É 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
ip_addr=192.168.10.1 prompt=Press [F8] for menu... prompt_timeout=10 service=1,192.168.10.1,pxelinux.0,Linux
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
service tftp { socket_type = dgram protocol = udp wait = yes user = root server = /usr/local/sbin/in.tftpd server_args = -s /tftpboot -r blksize disable = no per_source = 11 cps = 100 2 flags = IPv4 }
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
ddns-update-style ad-hoc; class "PXE" { match if substring(option vendor-class-identifier, 0, 9) = "PXEClient"; option vendor-class-identifier "PXEClient"; } subnet 192.168.10.0 netmask 255.255.255.0 { range 192.168.10.10 192.168.10.254; default-lease-time 1200; max-lease-time 1800; option subnet-mask 255.255.255.0; }
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:
[root@localhost ~]# yum clean all [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:
[root@localhost ~]# du -sh /tftpboot/installroot 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:
[root@localhost /tftpboot]# dd if=/dev/zero of=/tftpboot/ramdisk.ext2 bs=1k count=524288 524288+0 records in 524288+0 records out 536870912 bytes (537 MB) copied, 14.0037 seconds, 38.3 MB/s [root@localhost /tftpboot]# mkfs.ext2 -v -m 0 -b 4096 ./ramdisk.ext2 mke2fs 1.39 (29-May-2006) ./ramdisk.ext2 is not a block special device. Proceed anyway? (y,n) y Filesystem label= OS type: Linux Block size=4096 (log=2) Fragment size=4096 (log=2) 131072 inodes, 131072 blocks 0 blocks (0.00%) reserved for the super user First data block=0 Maximum filesystem blocks=134217728 4 block groups 32768 blocks per group, 32768 fragments per group 32768 inodes per group Superblock backups stored on blocks: 32768, 98304 Writing inode tables: done Writing superblocks and filesystem accounting information: done This filesystem will be automatically checked every 30 mounts or 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.
[root@localhost ~]# cd /tftpboot [root@localhost /tftpboot]# mount -o loop -t ext2 ./ramdisk.ext2 ./ramdisk [root@localhost /tftpboot]# mount -o loop -t ext2 ./ramdisk.ext2 ./ramdisk.dir [root@localhost /tftpboot]# rsync -av ./installroot/ ./ramdisk.dir [root@localhost /tftpboot]# umount ./ramdisk.dir/ [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:
[root@localhost ~]# cat ./etc/sysconfig/network-scripts/ifcfg-eth1 # Broadcom Corporation NetXtreme BCM5703X Gigabit Ethernet DEVICE=eth1 BOOTPROTO=dhcp ONBOOT=yes
Activar a rede:
[root@localhost ~]# cat ./etc/sysconfig/network 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):
label linux-initrd MENU LABEL Ramdisk kernel kernel os_images/fc6/vmlinuz 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
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.
Entre no directório com a arvore do kernel e corra make menuconfig:
[root@localhost /tftpboot]# cd /space/src/linux-2.6/ [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
label NFS Autoconf linux-2.6.23-Net MENU LABEL NFS linux-2.6.23-net kernel os_images/fc6/bzImage.net 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