Avançar para o conteúdo principal
BlogLinuxDia de Lançamento: Automatização do Distro Linux (com Ubuntu 20.04)

Dia de Lançamento: Automatização do Linux Distro (com Ubuntu 20.04)

distribuições-distribuições automáticas

Olá! Sou Brad, um engenheiro de sistemas na Linode. Hoje marca um dia agitado no mundo Linux com o lançamento do Ubuntu 20.04, a próxima versão LTS (suporte de longo prazo) de uma das distribuições mais populares. Tal como no Ubuntu 18.04 há dois anos, esperamos que esta se torne a nossa imagem mais amplamente utilizada, que já está disponível para todos os clientes da Linode.

A disponibilidade de distro no mesmo dia tornou a norma aqui na Linode, graças à automação que desenvolvemos em torno da construção, testes e implantação de novas imagens. Mas o que é uma imagem (ou um template como às vezes são chamados), e o que é que vai fazer para as criar? Para responder a essa pergunta, vamos começar olhando para como as instalações de SO normalmente funcionam. ​

Instalando um sistema operacional

Você pode estar familiarizado com o processo de instalação manual de um sistema operacional em um computador doméstico ou em um servidor. Geralmente envolve baixar uma ISO de instalação, gravá-la em um CD ou drive USB, e inicializar o sistema a partir daí. A partir daí você normalmente corre por uma série de menus (ou às vezes comandos manuais) que lhe permitem controlar vários aspectos da instalação, como qual disco rígido instalar, que software/pacotes você gostaria de incluir, e talvez alguma customização, como definir um nome de usuário e senha. Quando tudo estiver feito, você tem um SO (esperançosamente) totalmente funcional que você pode inicializar e começar a usar.

Este processo funciona suficientemente bem para usuários individuais que realizam instalações únicas, mas se você precisar instalar mais do que uma pequena quantidade de sistemas, então o processo de instalação manual é simplesmente inviável. É aqui que entram as imagens. ​

O que é uma Imagem?

Uma imagem é essencialmente um SO pré-instalado que você pode implantar em quantos sistemas você precisar. Ela funciona executando uma instalação normal uma vez e depois fazendo uma cópia dessa instalação que você pode mais tarde "colar" em outro sistema. Há uma variedade de formas e formatos em que você pode armazenar imagens para uso posterior, mas na maioria das vezes são cópias byte por byte exatas da instalação original.

Agora só precisamos realizar uma instalação manual uma vez, e podemos reutilizá-la em qualquer outro lugar. Mas ainda podemos fazer melhor. Linode suporta uma grande variedade de distribuições, desde as suspeitas habituais (Debian, Ubuntu, CentOS, OpenSUSE) até algumas que você pode não encontrar em outros provedores (Alpine, Arch, e até mesmo Gentoo). Cada uma tem seu próprio calendário de lançamento e suporte vitalício. Realizar instalações manuais para todas as nossas distros suportadas (mesmo apenas uma vez) e levar tempo para garantir que as imagens resultantes funcionem e não contenham nenhum erro levaria uma enorme quantidade de tempo e seria muito propenso a acidentes. Então, ao invés disso, optamos por automatizar o próprio processo de construção de imagens, com a ajuda de uma maravilhosa ferramenta chamada Packer feita pela HashiCorp. ​

Automatizando a Construção

Apesar de cada distribuição Linux compartilhar uma base comum (nomeadamente, o kernel Linux), todas elas são muito diferentes umas das outras, incluindo a forma como são instaladas. Algumas distribuições usam instruções de linha de comando, outras usam interfaces de menu, e algumas incluem maneiras de navegar automaticamente e fornecer respostas a esses menus. Felizmente, Packer é uma ferramenta muito versátil e pode lidar com todos esses casos de uso.

A primeira coisa que fazemos é instruir a Packer a criar uma máquina virtual (ou VM) que se assemelhe o mais próximo possível de um Linode. Isto significa emular o mesmo "hardware" e recursos que usamos para Linodes reais. Desta forma, a instalação será realizada em um ambiente que se assemelha muito ao ambiente de tempo de execução final. Imagine instalar um SO em um drive USB e depois usar esse drive para inicializar um computador completamente diferente. Se você tiver sorte, as coisas podem funcionar, mas na maioria das vezes algum dispositivo de hardware não será detectado ou talvez ele não inicialize de todo. Ao ter um ambiente de instalação que corresponda ao ambiente de execução real, eliminamos estes problemas.

Assim que a VM for criada, o Packer irá inicializá-la a partir da ISO de instalação da distro, que ela vai buscar a partir de uma URL especificada. O processo a partir daqui varia muito entre distros. Para distribuições controladas por comandos como Arch, nós alimentamos um script bash que executa uma instalação básica. Para distribuições guiadas por menus como Ubuntu, nós usamos o método preferido da distribuição para fornecer respostas ao instalador (tipicamente ou Preseed em distribuições do tipo Debian ou Kickstart em distribuições do tipo RHEL). Além da nossa VM, Packer também cria um pequeno servidor HTTP que permite que qualquer arquivo necessário seja transferido para a VM. ​

Tudo isto é controlado através de uma pasta JSON com as definições e opções de construção que o Packer irá utilizar. Para iniciar uma compilação, nós simplesmente precisamos executar (por exemplo): packer build ubuntu-20.04.json.

Personalização

Na sua maioria, realizamos instalações que são tão baunilha quanto possível. Isto significa instalar quaisquer pacotes que a dada distro considere como "padrão" (por vezes referidos como "base" ou "standard"). Além desses pacotes padrão, nós também instalamos uma pequena quantidade do que chamamos de pacotes "de suporte": utilitários básicos como iotop, mtr e sysstat que podem ajudar a depurar quaisquer problemas que possam surgir. Como resultado, a equipe de suporte da Linode também pode razoavelmente assumir que estas ferramentas estão instaladas enquanto assiste os clientes.

Após a instalação concluída, mas antes que a VM seja desligada, fazemos algumas personalizações finais para garantir a funcionalidade adequada com todas as funcionalidades da plataforma Linode. Por exemplo, asseguramos que o bootloader esteja configurado com as configurações corretas para LISH (nossa ferramenta para acesso de console fora da banda). No entanto, em geral, tentamos manter as coisas o mais próximo possível dos seus padrões. Desta forma, um utilizador que prefira uma distro específica terá aquilo com que está familiarizado e não terá vontade de conduzir o carro de outra pessoa.

Embalagem

Após a instalação e configuração estar concluída, o Packer desliga a VM e exporta a sua imagem de disco para uma pasta. Pode parecer que terminamos, mas ainda faltam alguns passos. O disco rígido de um computador típico começará com uma tabela de partições (ou MBR, ou GPT em sistemas mais recentes). Os Linodes são um pouco únicos na medida em que o próprio bootloader do GRUB realmente vive em nossos hosts, ao invés de em cada Linode (a configuração ainda é lida a partir do Linode, no entanto). Isto significa que podemos realmente tirar a tabela de partições completamente, deixando apenas com uma única partição.

Para conseguirmos isso, nós corremos fdisk -l disk.img na imagem do disco para determinar onde a partição começa e termina, e qual é o tamanho do bloco. Usamos então o dd if=disk.img of=part.img bs=### skip=### count=### para "empilhar" a partição usando o offset inicial do nosso comando anterior. Mais especificamente, cada "###" nesse comando é substituído pela saída do nosso comando anterior fdisk ...o comando.

Tal como num computador novo, a maior parte do espaço na unidade estará vazia, o que se refletirá na nossa imagem de disco. Seria uma tolice copiar todos esses bytes "vazios", então a próxima coisa que faremos é esvaziar a imagem (mais tarde, quando você implanta uma imagem no seu Linode, nós re-inflamos para preencher o espaço disponível na sua instância). Como todas as nossas imagens usam partições ext4, podemos executar resize2fs -M part.imgque irá automaticamente reduzir a nossa imagem para o seu menor tamanho possível, removendo o espaço vazio. Finalmente, para garantir a integridade da imagem resultante, realizamos uma fsck sobre ele antes de o comprimir com gzip.

Testes

Depois que a imagem é construída e preparada, o próximo passo no processo é garantir que ela realmente funcione. Nossa imagem recém-moldada é implantada em um ambiente de teste, onde um monte de instâncias Linode são provisionadas a partir da imagem em várias configurações diferentes. Desenvolvemos um conjunto de testes automatizados que verifica todos os tipos de coisas diferentes, como conectividade de rede e um gerenciador de pacotes funcional, bem como vários recursos da plataforma Linode, como Backups e redimensionamento de disco; atiramos o livro para essas instâncias. Se alguma verificação falhar, o processo é imediatamente abortado e a compilação falha, juntamente com alguns detalhes sobre qual verificação falhou e porquê.

Construir e testar de uma forma automatizada como esta permite ciclos rápidos de desenvolvimento que, por sua vez, nos permitem lançar imagens melhores, mais rápidas. Nós estruturamos nosso processo de testes de tal forma que adicionar novas verificações é trivial. Se um cliente relatar um problema com uma de nossas imagens, podemos rapidamente liberar uma correção e adicionar outro item à nossa crescente lista de verificações - quase como um sistema imunológico! ​

O mesmo, mas diferente

Implantar sistemas a partir de uma imagem comum é ótimo, mas e as coisas que são exclusivas de uma instância específica, como a senha raiz ou a configuração de rede? Nossas imagens são configuradas para usar DHCP, o que fará com que seu sistema receba automaticamente seu endereço IP atribuído e um hostname único de nossos servidores DHCP. No entanto, nós também fornecemos uma variedade de "helpers" como o Network Helper (que irá configurar automaticamente a rede estática no seu Linode), e a nossa ferramenta de redefinição de senha root (que define sua senha root inicial e que você também pode usar em emergências se você precisar redefini-la). Estas ferramentas permitem, por exemplo, que informações específicas sejam aplicadas ao seu Linode na parte superior da imagem base.

É claro que nem todas as distro lidam com estas tarefas da mesma forma, por isso as nossas ferramentas precisam de estar conscientes de como fazer estas coisas em todas as nossas distros suportadas. Novas versões principais de uma distro tipicamente requerem algumas atualizações nesses sistemas para que as coisas funcionem completamente. Por exemplo, o Debian tradicionalmente configura a rede em /etc/network/interfacesenquanto o CentOS coloca configurações de rede em /etc/sysconfig/network-scripts. Felizmente, a maioria das distros fornece lançamentos beta antes do tempo, o que nos dá muito tempo para fazer essas mudanças e garantir que tudo esteja pronto para o dia do lançamento. ​

Conclusão

Como você pode ver, há muitas coisas que existem para apoiar uma nova distro, então qual é o verdadeiro benefício de automatizar este processo? Bem, anos atrás antes de termos o processo que temos hoje, uma típica liberação de distro (desde a construção até os testes e disponibilidade) levaria na melhor das hipóteses um dia inteiro, mas normalmente vários dias, e muitas pessoas estariam envolvidas. Em comparação, o lançamento de hoje do Ubuntu 20.04 exigiu apenas 5 linhas de mudanças de código e levou menos de uma hora do início ao fim. Esta abordagem de construção de imagens nos poupa muito tempo, complicações e resulta em construções consistentes que são completamente testadas e em constante melhoria. Se você tiver alguma sugestão ou coisa que gostaria de ver, nos avise! Eu ando no IRC como blaboon na OFTC e lblaboon na Freenode. Se você estiver interessado em experimentar o Packer por conta própria, eles têm uma ótima documentação que pode ser encontrada aqui. Também temos nosso próprio construtor Linode para Packer, que você pode usar para criar suas próprias imagens personalizadas em nossa plataforma. Mais documentação para usar o construtor Linode para Packer pode ser encontrada em nossa biblioteca de Guias


Não é um cliente Linode? Inscreva-se aqui com um crédito de 20 dólares.

Comentários (4)

  1. Author Photo

    This is brilliant and very timely (for me) as I happened to spend some of last weekend to “reverse engineer” the build process (and discovered the GRUB config quirks) while tried to test migrating a Linode VM over to a on-premises (lab) VM Host and vice versa. Maybe this would be a good write-up, if you are searching for tutorial/blog topics. Many thanks for publishing this!

  2. Nathan Melehan

    Hey A. –

    That sounds like a cool topic! If you’re interested, we actually have a paid freelance contributor program for our documentation library called Write For Linode. You can learn more about the program and apply to it here: https://www.linode.com/lp/write-for-linode/

    • Author Photo

      Hi Nathan
      Thanks for this, it looks very tempting. I started to work on the process for the first migration but I was stopped by Grub2. As described in the Packaging section above, the stripped out boot partition stops me to boot up the the image in my VM Host and I haven’t been able boot up the image dd’d out of Linode. If I create a vanilla VM image with the same Ubuntu version as in my Linode VM, the (virtual) disk is partitioned with two partitions, sda1 hosting grub (I assume this is what you strip out in the build process) and sda2, which is “/”. The image “exported” out of Linode, on the other hand has only a single partition as described above. Is there any documentation describing how to undu the stripping out of sda1, or how insert a new boot (sda1) partition back into the image? Many thanks, A

      • Author Photo

        Ok, I managed to get through booting my local clone in the end and it turns out that the startup process didn’t crash (as I thought), it was just slow*. It is because (unsurprisingly) it has a hard-coded static IP address which now lives on the wrong network, so I had to wait until the network config time-out* during the boot-up process.

        That’s easy enough I’ll just change the config in /etc/network/interfaces (the default/standard place in Ubuntu, and as also mentioned in this article). Looking at the “interfaces” file it, is blank with a note that things have moved on (since I last had to deal with linux networking) and it is now handled by something called “netplan”. [grrrrr….]

        No matter, it can’t be that hard, let’s see what /etc/netplan says. Well, the yaml file says my ethernet interface should be called `enp0s3` and should be getting the address from dhcp. But my actual interface name is `eth0` and has a static address. Where is this coming from?! [&$#^%#]

        Time to “brute force” search the entire config.
        `find /etc/ -exec grep ‘12.34.56.78’ {} \; 2>/dev/null` results in 3 hits, one is by an application so there are only two potential places to change, it might be easy enough to check**:

        `grep -Rn ‘12.34.56.78’ * 2>/dev/null`

        systemd/network/05-eth0.network
        systemd/network/.05-eth0.network

        It was auto-generated by Linode’s Network Helper (as described in the article) which is not available in my lab, unsurprisingly, so let’s just copy back the original config:

        `cp 05-eth0.network 05-eth0.network.bak`
        `cp .05-eth0.network 05-eth0.network`
        `shutdown -r now`

        Bingo!!! The VM came up with a new dynamic IP address and I can ping and nslookup to my heart content!!! I haven’t checked if the actual web application survived the extraction, and what else may have broken in the process.

        *and probably a lot more linode specific configs that are inaccessible to my local clone.
        **The actual IP address is not this

        Lessons learned: It is a lot more complicated to migrate out of Linode to a local VM or different cloud and require a lot of effort to fix/adapt the extracted application and the OS, it would be a lot faster just to build the lab up from the ground up. It might be a simpler process to move the other way around (i.e. develop in my own lab and pull the result into Linode) but wouldn’t hold my breath trying.

        Not sure if my experience warrants an article beyond this (chain of) comment(s). But it was a great weekend project and an inspirational learning exercise, many thanks, Linode!

Deixe uma resposta

O seu endereço de correio electrónico não será publicado. Os campos obrigatórios estão marcados com *