1 pontos por GN⁺ 2024-07-03 | Ainda não há comentários. | Compartilhar no WhatsApp
  • Um experimento para inicializar o Arch Linux usando o Google Drive como sistema de arquivos raiz, em vez de disco local ou NFS
  • Na etapa do initramfs, ele monta um sistema de arquivos FUSE e cria com o Dracut uma imagem EFI personalizada com rede e os binários necessários
  • Depois de validar o conceito primeiro com S3 e s3fs, contornou as falhas de switch_root e pivot_root executando chroot como PID 1
  • Ao aplicar a ideia ao Google Drive, usou google-drive-ocamlfuse, mas as limitações de links simbólicos, hard links, permissões e velocidade exigiram correções manuais e ajustes de timeout
  • No fim, conseguiu inicializar até em um notebook sem armazenamento, usando um arquivo EFI unificado em um USB e um driver de rede cabeada, mostrando pouca praticidade mas abrindo espaço para variações como raiz em SSHFS ou baseada em Git

Usando o Google Drive como sistema de arquivos raiz

  • Depois de ver casos de boot de Linux via NFS, tentou algo mais complicado: bootar com o Google Drive como raiz
  • Como queria uma estrutura autossuficiente, sem uma máquina auxiliar separada, escolheu o FUSE, que funciona como um driver de sistema de arquivos em espaço de usuário
  • A condição central era colocar no initramfs o programa FUSE e a configuração de rede, montar o sistema de arquivos raiz remoto e então continuar o boot normalmente

Onde intervir no processo de boot do Linux

  • O fluxo de boot do Linux se divide, em linhas gerais, nas seguintes etapas
    • O firmware BIOS/UEFI inicia o bootloader
    • O bootloader carrega o kernel
    • O kernel descompacta na RAM o initramfs, um sistema de arquivos temporário, e usa ferramentas para montar o sistema de arquivos real
    • O kernel troca para o sistema de arquivos real e executa o sistema de init desse novo sistema de arquivos
  • Se o sistema de arquivos FUSE for montado na terceira etapa, o boot pode continuar usando o armazenamento remoto como raiz

Prova de conceito com S3 criada com Dracut

  • Para gerar um initramfs personalizado, foi usado o Dracut
  • A distribuição base escolhida foi o Arch Linux, por ser relativamente leve e familiar
  • No módulo do Dracut, foram incluídos binários relacionados a FUSE, como fusermount, fuseiso e mkisofs
  • Um arquivo EFI foi criado com dracut.sh e executado no QEMU; depois do aviso de que faltava o argumento root=, o sistema entrou em um shell de depuração
  • Nesse shell de depuração, as tarefas necessárias ao boot foram feitas manualmente
    • modprobe fuse, modprobe e1000 para carregar os drivers
    • dhclient eth0 e configuração de rota para montar a rede
    • montagem de um bucket S3 local em /sysroot com s3fs

Falha do switch_root e desvio com chroot

  • Embora a raiz do Arch Linux aparecesse em /sysroot, switch_root /sysroot /sbin/init falhava com Input/output error
  • pivot_root também não podia ser usado no rootfs do initramfs, gerando Invalid argument
  • Segundo uma resposta do Stack Exchange consultada, no rootfs do initramfs não é possível usar pivot_root nem desmontar, então é preciso fazer overmount da nova raiz, usar chroot e executar o init
  • Se no shell fosse executado apenas chroot /sysroot /sbin/init, o systemd não iniciava corretamente por não ser o PID 1
  • Ao modificar o init.sh do Dracut para incluir configuração de rede, montagem do s3fs, bind mounts de /sys, /dev e /proc, e por fim executar exec chroot /sysroot /sbin/init, o boot com raiz em S3 funcionou

Problema de DNS revelado na raiz em S3

  • Depois do boot, o resultado de mount confirmou que / estava montado como tipo s3fs
  • Ao executar pacman -Sy fastfetch, houve falha porque hosts de mirrors de pacotes, como geo.mirror.pkgbuild.com, não eram resolvidos
  • Como o sistema de arquivos raiz estava no S3, foi possível montar essa raiz em outra máquina e entrar nela com chroot para instalar ferramentas
  • O systemd-resolved não iniciava por um problema de permissão na conexão do socket do journal com stdout, e o DNS foi contornado adicionando nameserver 1.1.1.1 em /etc/resolv.conf

Migrando para o Google Drive

  • Como implementação FUSE para o Google Drive, foi usado google-drive-ocamlfuse
  • Depois de criar segredos OAuth2 na conta do Google e ativar a API, foi instalado o pacote AUR em uma VM Arch Linux
  • Após montar o Google Drive, um longo processo de rsync copiou os arquivos do Arch Linux para o Drive
  • Na raiz baseada em Google Drive, as diferenças de comportamento do sistema de arquivos continuaram causando problemas
    • links simbólicos apontando para links simbólicos não funcionavam, causando problemas em itens relacionados a /usr/lib
    • hard links não funcionavam
    • links simbólicos relativos não funcionavam
    • links simbólicos quebrados não eram permitidos
    • links simbólicos apontando para fora do Google Drive não funcionavam
    • permissões e atributos não funcionavam
    • a velocidade era muito baixa
  • Para manter a condição de não modificar o driver FUSE nem o kernel, a solução foi criar manualmente links simbólicos com base no log de falhas do rsync

Ajustando o initramfs para o Google Drive

  • No initramfs, foram incluídos o arquivo de token gerado no notebook, o binário FUSE do Google Drive e certificados SSL
  • Arquivos relacionados a /.gdfuse/default/config, /.gdfuse/default/state, /etc/ssl e /etc/ca-certificates foram colocados na imagem do Dracut
  • Ao inicializar com a raiz no Google Drive, ocorreu chroot: /sbin/init: File not found
  • Mesmo quando o arquivo existe, o Linux pode retornar File not found se bibliotecas dependentes ou o caminho do linker dinâmico estiverem ausentes
  • Por causa do problema com links simbólicos relativos, o kernel acabou tentando procurar /sysroot/sysroot dentro de /sysroot; isso foi resolvido criando /sysroot/sysroot e depois fazendo bind mount de /sysroot dentro dele
  • Mesmo assim, o boot continuou muito lento
    • a recriação do cache do linker dinâmico levou cerca de 5 minutos
    • cada unidade do systemd levava cerca de 1 minuto
    • o boot parava por causa do timeout de espera por /dev/ttyS0
  • Foi definido JobTimeoutSec=infinity em /etc/systemd/system/dev-ttyS0.device, e LOGIN_TIMEOUT em /etc/login.defs foi alterado para 0 para evitar timeout no login
  • Depois que o cache se acumulou, a leitura de arquivos ficou menos lenta do que no começo

Executando em um notebook sem armazenamento

  • Foi feito um teste de boot em hardware real com um notebook reserva sem dispositivo de armazenamento
  • Em relação à configuração usada no QEMU, alguns itens foram alterados para se adequar ao hardware
    • uso do driver r8169 para a porta Ethernet do notebook, em vez do e1000 padrão
    • sem uso de tela serial
    • ajustes de rede conforme a topologia da rede doméstica
  • Em vez de um cabo Ethernet longo, foi usado Powerline
  • Um arquivo EFI unificado foi gerado, colocado no caminho de boot EFI de um drive USB e usado para iniciar o notebook
  • Como não foi encontrada a diretiva modprobe para o teclado embutido, foi carregado hid_usb e a rede foi configurada com um teclado externo
  • O resultado final foi um “Cloud Native Computer” funcionando com raiz baseada em Google Drive e sem armazenamento local

Variações possíveis e limitações

  • Embora o projeto tenha um tom fortemente brincalhão, o mesmo método permitiria inicializar o Linux sobre SSHFS
  • Com gitfs, também seria possível inicializar o Linux a partir de um repositório Git e rastrear alterações no Git
  • Há muitas possibilidades, mas a praticidade é limitada
  • O próximo experimento cogitado é uma instalação com Nix

Ainda não há comentários.

Ainda não há comentários.