Post

Fundamentos do Packer e QEMU/KVM: Criando Imagens Automatizadas

Fundamentos do Packer e QEMU/KVM: Criando Imagens Automatizadas

Nota: Este tutorial é o primeiro de uma série de 6 tutoriais sobre criação de imagens QEMU/KVM com Packer. A série completa abordará desde os fundamentos até técnicas avançadas de personalização e integração com pipelines CI/CD, cobrindo Oracle Linux, Debian e Ubuntu.

Introdução

A criação manual de imagens de máquinas virtuais é um processo demorado, propenso a erros e difícil de reproduzir consistentemente. Imagine ter que instalar manualmente um sistema operacional, configurar pacotes, aplicar atualizações e otimizar configurações toda vez que precisar de uma nova imagem. Agora multiplique isso por dezenas ou centenas de máquinas em um ambiente corporativo.

É aqui que o Packer entra como uma ferramenta revolucionária para DevOps e administradores de sistemas. Desenvolvido pela HashiCorp, o Packer permite automatizar todo o processo de criação de imagens de máquinas virtuais para múltiplas plataformas a partir de uma única configuração.

Neste primeiro tutorial da nossa série, vamos explorar os fundamentos do Packer em conjunto com QEMU/KVM, preparar nosso ambiente de desenvolvimento e criar nosso primeiro arquivo de configuração básico.

O que é Virtualização com QEMU/KVM?

Antes de mergulharmos no Packer, vamos entender brevemente o que é QEMU/KVM:

QEMU (Quick Emulator) é um emulador e virtualizador de código aberto que pode executar sistemas operacionais e programas feitos para uma máquina em uma arquitetura diferente. Quando combinado com o KVM (Kernel-based Virtual Machine), um módulo de virtualização no kernel Linux, o QEMU pode alcançar desempenho próximo ao nativo.

Principais características do QEMU/KVM:

  • Código aberto: Totalmente gratuito e de código aberto
  • Desempenho: Com KVM, oferece virtualização com desempenho próximo ao nativo
  • Flexibilidade: Suporta diversos sistemas operacionais convidados
  • Formatos de disco: Trabalha com vários formatos de disco virtual (raw, qcow2, vmdk, etc.)
  • Integração: Base para muitas soluções de virtualização como libvirt, OpenStack e Proxmox

O que é o Packer?

Packer é uma ferramenta de código aberto para criar imagens de máquinas idênticas para múltiplas plataformas a partir de uma única configuração. Desenvolvido pela HashiCorp (mesma empresa por trás do Terraform, Vault e Consul), o Packer automatiza o processo de criação de imagens para:

  • Máquinas virtuais (QEMU/KVM, VMware, VirtualBox)
  • Contêineres (Docker)
  • Nuvem pública (AWS AMI, Azure VHD, Google Compute Image)
  • E muitas outras plataformas

Por que usar o Packer?

  1. Automação: Elimina processos manuais e repetitivos
  2. Consistência: Garante que todas as imagens sejam criadas da mesma forma
  3. Versionamento: Permite versionar suas configurações de imagem como código
  4. Multi-plataforma: Cria imagens para múltiplas plataformas simultaneamente
  5. Integração com IaC: Complementa ferramentas como Terraform e Ansible
  6. Imutabilidade: Facilita a adoção de infraestrutura imutável

Preparando o Ambiente de Desenvolvimento

Vamos configurar nosso ambiente para trabalhar com Packer e QEMU/KVM. Siga os passos abaixo para instalar as ferramentas necessárias:

Pré-requisitos

  • Sistema operacional Linux (usaremos Ubuntu/Debian neste exemplo)
  • Acesso de administrador (sudo)
  • Processador com suporte a virtualização (Intel VT-x ou AMD-V)
  • Pelo menos 4GB de RAM e 20GB de espaço em disco

Instalando o QEMU/KVM

1
2
3
4
5
6
7
8
# Atualizar repositórios
sudo apt update

# Instalar QEMU e ferramentas relacionadas
sudo apt install -y qemu-kvm libvirt-daemon-system libvirt-clients bridge-utils virtinst

# Verificar se o KVM está disponível
kvm-ok

Se o comando kvm-ok retornar “KVM acceleration can be used”, seu sistema está pronto para usar KVM.

Instalando o Packer

O Packer está disponível em repositórios oficiais, mas para garantir que temos a versão mais recente, vamos usar o repositório da HashiCorp:

1
2
3
4
5
6
7
8
9
10
11
# Adicionar a chave GPG do HashiCorp
curl -fsSL https://apt.releases.hashicorp.com/gpg | sudo apt-key add -

# Adicionar o repositório do HashiCorp
sudo apt-add-repository "deb [arch=amd64] https://apt.releases.hashicorp.com $(lsb_release -cs) main"

# Atualizar e instalar o Packer
sudo apt update && sudo apt install -y packer

# Verificar a instalação
packer version

Certifique-se de que a versão do Packer seja 1.10.0 ou superior, conforme recomendado em nosso projeto.

Estrutura de Diretórios

Para manter nosso projeto organizado, vamos criar uma estrutura de diretórios recomendada:

1
2
3
4
5
6
# Criar diretório do projeto
mkdir -p ~/packer-kvm-tutorial/tutorial1
cd ~/packer-kvm-tutorial/tutorial1

# Criar subdiretórios
mkdir -p http scripts

Esta estrutura básica nos servirá bem para este primeiro tutorial:

  • http/: Armazenará arquivos que serão servidos via HTTP durante a instalação
  • scripts/: Conterá scripts de provisionamento

Entendendo a Estrutura do Arquivo Packer (HCL)

O Packer usa o formato HCL (HashiCorp Configuration Language) para seus arquivos de configuração. Vamos entender as principais seções de um arquivo Packer:

1. Bloco packer

Define a versão mínima do Packer necessária e os plugins requeridos:

1
2
3
4
5
6
7
8
9
packer {
  required_version = ">= 1.10.0"
  required_plugins {
    qemu = {
      version = "= 1.1.0"
      source  = "github.com/hashicorp/qemu"
    }
  }
}

2. Bloco variable

Define variáveis que podem ser reutilizadas em todo o arquivo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
variable "vm_name" {
  default = "ubuntu-kvm-template.raw"
}

variable "disk_size" {
  default = "16384"
}

variable "iso_url" {
  default = "https://releases.ubuntu.com/22.04/ubuntu-22.04.3-live-server-amd64.iso"
}

variable "iso_checksum" {
  default = "a4acfda10b18da50e2ec50ccaf860d7f20823f8f3100053d30f137dc7cc46e9f"
}

3. Bloco source

Define a configuração da máquina virtual e do provedor (QEMU neste caso):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
source "qemu" "iso" {
  vm_name          = var.vm_name
  iso_url          = var.iso_url
  iso_checksum     = var.iso_checksum
  disk_size        = var.disk_size
  memory           = 2048
  disk_image       = false
  output_directory = "build/os-base"
  accelerator      = "kvm"
  disk_interface   = "virtio"
  format           = "raw"
  net_device       = "virtio-net"
  boot_wait        = "3s"
  http_directory   = "http"
  cpu_model        = "host"
  ssh_username     = "packer"
  ssh_password     = "packer"
  ssh_timeout      = "60m"
}

4. Bloco build

Define como a imagem será construída, incluindo provisionadores:

1
2
3
4
5
6
7
8
9
10
build {
  sources = ["source.qemu.iso"]

  # Exemplo de provisionador para executar um script
  provisioner "shell" {
    inline = [
      "echo 'Instalação concluída com sucesso!'"
    ]
  }
}

Criando Nosso Primeiro Arquivo Packer

Vamos criar um arquivo Packer básico para entender como funciona. Este exemplo não criará uma imagem completa ainda, mas nos ajudará a entender a estrutura e validar nossa configuração.

Crie um arquivo chamado basic.pkr.hcl no diretório do projeto:

1
nano ~/packer-kvm-tutorial/tutorial1/basic.pkr.hcl

Adicione o seguinte conteúdo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
packer {
  required_version = ">= 1.10.0"
  required_plugins {
    qemu = {
      version = "= 1.1.0"
      source  = "github.com/hashicorp/qemu"
    }
  }
}

variable "vm_name" {
  default = "basic-vm-template.raw"
}

variable "disk_size" {
  default = "8192"
}

variable "iso_url" {
  default = "https://releases.ubuntu.com/22.04/ubuntu-22.04.3-live-server-amd64.iso"
}

variable "iso_checksum" {
  default = "a4acfda10b18da50e2ec50ccaf860d7f20823f8f3100053d30f137dc7cc46e9f"
}

source "qemu" "iso" {
  vm_name          = var.vm_name
  iso_url          = var.iso_url
  iso_checksum     = var.iso_checksum
  disk_size        = var.disk_size
  memory           = 2048
  disk_image       = false
  output_directory = "build/basic"
  accelerator      = "kvm"
  disk_interface   = "virtio"
  format           = "raw"
  net_device       = "virtio-net"
  boot_wait        = "3s"
  http_directory   = "http"
  cpu_model        = "host"
  ssh_username     = "packer"
  ssh_password     = "packer"
  ssh_timeout      = "60m"
  
  # Este comando não funcionará sem um arquivo de automação adequado
  # Está aqui apenas para ilustrar a estrutura
  boot_command = [
    "<esc><wait>",
    "install <wait>",
    "preseed/url=http://{{ .HTTPIP }}:{{ .HTTPPort }}/preseed.cfg <wait>",
    "<enter><wait>"
  ]
}

build {
  sources = ["source.qemu.iso"]

  # Exemplo simples de provisionador
  provisioner "shell" {
    inline = [
      "echo 'Este é um exemplo básico de provisionamento.'"
    ]
  }
}

Validando o Arquivo Packer

Antes de tentar construir uma imagem, é uma boa prática validar seu arquivo Packer para garantir que não há erros de sintaxe:

1
2
3
cd ~/packer-kvm-tutorial/tutorial1
packer init .
packer validate basic.pkr.hcl

Se tudo estiver correto, você verá a mensagem “The configuration is valid.”

Nota: Este arquivo básico não construirá uma imagem funcional ainda, pois não temos os arquivos de automação necessários (como o preseed.cfg mencionado no boot_command). Nos próximos tutoriais, abordaremos a criação desses arquivos para diferentes distribuições Linux.

Entendendo os Componentes Principais

Vamos revisar os componentes principais que vimos no nosso arquivo básico:

1. Variáveis

As variáveis permitem parametrizar sua configuração, facilitando a reutilização e personalização:

1
2
3
variable "vm_name" {
  default = "basic-vm-template.raw"
}

Você pode substituir o valor padrão ao executar o Packer:

1
packer build -var "vm_name=custom-template.raw" basic.pkr.hcl

2. Provedor QEMU

O provedor QEMU configura como a máquina virtual será criada:

  • vm_name: Nome do arquivo de imagem resultante
  • iso_url e iso_checksum: Localização e verificação da ISO
  • disk_size: Tamanho do disco em MB
  • memory: Quantidade de RAM em MB
  • accelerator: Usa KVM para melhor desempenho
  • format: Formato do disco (raw, qcow2, etc.)
  • boot_command: Comandos enviados durante o boot para automatizar a instalação

3. Provisionadores

Os provisionadores permitem configurar a máquina após a instalação do sistema operacional:

  • shell: Executa comandos shell na máquina
  • file: Copia arquivos para a máquina
  • ansible: Executa playbooks Ansible
  • E muitos outros…

Próximos Passos

Neste tutorial, aprendemos os fundamentos do Packer e QEMU/KVM, preparamos nosso ambiente de desenvolvimento e criamos um arquivo Packer básico. No próximo tutorial, vamos criar nossa primeira imagem completa para Oracle Linux usando Kickstart para automatizar a instalação.

Você já deve estar se perguntando:

  • Como automatizar completamente a instalação sem interação manual?
  • Como personalizar a imagem com pacotes e configurações específicas?
  • Como otimizar a imagem final para uso em produção?

Todas essas perguntas serão respondidas nos próximos tutoriais da série!

Exercícios Práticos

Para fixar o conhecimento adquirido neste tutorial, tente os seguintes exercícios:

  1. Modifique o arquivo basic.pkr.hcl para usar uma ISO diferente (como Debian ou CentOS)
  2. Altere os valores padrão das variáveis (tamanho do disco, memória, etc.)
  3. Adicione comentários explicativos ao arquivo para documentar cada seção
  4. Experimente adicionar mais variáveis para outros parâmetros (como cpu_model ou net_device)

Conclusão

Neste primeiro tutorial, estabelecemos as bases para nossa jornada de criação automatizada de imagens com Packer e QEMU/KVM. Aprendemos sobre os conceitos fundamentais, preparamos nosso ambiente de desenvolvimento e criamos nosso primeiro arquivo de configuração Packer.

Nos próximos tutoriais, vamos mergulhar mais fundo na automação completa da criação de imagens para diferentes distribuições Linux, começando com Oracle Linux e o método Kickstart.

Até lá, experimente com o arquivo básico que criamos e familiarize-se com a sintaxe HCL e os conceitos do Packer!

Referências

This post is licensed under CC BY 4.0 by the author.