Pular para o conteúdo principal
IT BIBLEEntrar

Blog

Esta publicação foi traduzida do inglês por IA. Ler o original

Construindo um template cloud-init no Proxmox que você pode recriar a partir do Git

Um template cloud-init transforma uma nova VM no Proxmox em um único comando de clone mais algumas configurações. Veja como estou montando o meu a partir de uma imagem cloud oficial e onde ainda tenho dúvidas.

PriyaInTheCloset
· 6 min read
Construindo um template cloud-init no Proxmox que você pode recriar a partir do Git

Por muito tempo minhas VMs no Proxmox foram feitas à mão. Eu passava clicando pelo instalador, adicionava meu usuário, colava uma chave SSH, instalava o guest agent e, na VM seguinte, já tinha esquecido metade do que fiz. Elas funcionavam. Só não eram reproduzíveis, e eu não saberia dizer o que diferia entre duas máquinas que montei com um mês de intervalo.

Um template cloud-init resolve a maior parte disso. Este post mostra como estou montando um a partir de uma imagem cloud oficial, usando a CLI qm para que cada passo possa ficar em um script no Git. Não uso esse setup há muito tempo, então trate como um método que funciona por enquanto. Vou sinalizar as partes em que tenho dúvidas.

Se você ainda não tem um host Proxmox para testar, o lab Install Proxmox VE cobre a instalação base.

Você vai praticar a instalação do Proxmox VE em dois SSDs em espelho com ZFS e a configuração de um endereço fixo para o host.

Por que uma imagem cloud e não uma VM clonada

A alternativa comum é instalar uma VM manualmente, arrumar tudo e converter em template. Funciona, mas o template carrega qualquer estado que você deixou para trás: host keys, machine ID, histórico do shell, algum pacote perdido. Limpar isso é uma checklist à parte, e prefiro não ter que manter essa checklist.

Uma imagem cloud oficial já começa limpa. Ela espera que o cloud-init a configure no primeiro boot: usuário, chaves SSH, rede, hostname. O Proxmox pode fornecer esses valores por meio de um drive cloud-init virtual. O template continua genérico, e cada clone recebe sua identidade na hora da criação.

A contrapartida é que você abre mão do instalador gráfico e precisa saber de antemão o que quer. Para mim isso é uma vantagem. A lista do que eu quero é exatamente a documentação que sempre digo que vou escrever.

Montando o template

Aqui estou usando a imagem cloud do Ubuntu. Qualquer distro que distribua uma imagem cloud funciona da mesma forma. Rode isto no node do Proxmox. O VM ID, o nome do storage e a bridge são os meus, então troque pelos seus.

cd /var/lib/vz/template/iso
wget https://cloud-images.ubuntu.com/noble/current/noble-server-cloudimg-amd64.img

qm create 9000 --name ubuntu-2404-ci \
  --memory 2048 --cores 2 \
  --net0 virtio,bridge=vmbr0 \
  --ostype l26 --agent enabled=1

qm importdisk 9000 noble-server-cloudimg-amd64.img local-zfs
qm set 9000 --scsihw virtio-scsi-pci --scsi0 local-zfs:vm-9000-disk-0
qm set 9000 --ide2 local-zfs:cloudinit
qm set 9000 --boot order=scsi0
qm set 9000 --serial0 socket --vga serial0

Algumas notas sobre o porquê de cada peça:

  • importdisk transforma a imagem baixada em um disco de VM no seu storage. Versões mais novas do Proxmox também têm qm disk import. Veja o que a sua versão suporta.
  • O drive cloudinit em ide2 é onde o Proxmox grava as configurações de usuário, chave e rede que o cloud-init lê no boot.
  • O console serial está ali porque muitas imagens cloud esperam um. Sem ele, já vi o console web não mostrar nada útil. Não tenho certeza de que ele seja necessário em todas as imagens.

Ainda não converta em template. Primeiro, vamos tratar do guest agent.

O problema do guest agent

A imagem cloud não vem com o qemu-guest-agent. Sem ele, o Proxmox não consegue ver o endereço IP da VM, e os desligamentos limpos e o quiesce dos backups ficam menos confiáveis. Eu poderia instalá-lo manualmente e converter o resultado, mas isso traz de volta o problema do template feito à mão.

Em vez disso, estou usando um snippet de vendor-data que o cloud-init aplica no primeiro boot:

#cloud-config
package_update: true
packages:
  - qemu-guest-agent
runcmd:
  - systemctl enable --now qemu-guest-agent

Salve como /var/lib/vz/snippets/vendor.yaml. Snippets precisam de um storage do tipo diretório com o tipo de conteúdo Snippets habilitado. O storage local padrão pode fazer isso, mas um storage baseado em ZFS como o local-zfs não consegue guardar snippets. Depois, anexe:

qm set 9000 --cicustom "vendor=local:snippets/vendor.yaml"
qm template 9000

Uma ressalva para clusters: esse arquivo de snippet fica no storage local de um único node. Se um clone cair em um node que não o tem, o clone vai falhar ao iniciar. Ainda não decidi como lidar com isso. As opções que vejo são copiar o arquivo para todos os nodes a partir do mesmo script ou colocar os snippets em um storage compartilhado. Copiar é mais simples, então estou inclinado para esse lado.

Clonando com configurações

O template guarda o que é comum. Cada clone adiciona o que é específico:

qm clone 9000 120 --name devvm --full
qm set 120 --ciuser priya --sshkeys ~/.ssh/lab_keys.pub
qm set 120 --ipconfig0 ip=dhcp
qm resize 120 scsi0 32G
qm start 120

A flag --sshkeys recebe um arquivo com chaves públicas. Somente chaves públicas vão para a VM. Eu não defino senha nenhuma, então não há nada para vazar nem para rotacionar. Se você quiser um endereço estático, --ipconfig0 ip=10.0.20.50/24,gw=10.0.20.1 resolve. Eu prefiro uma reserva de DHCP, já que isso mantém o endereçamento em um só lugar.

Depois de um ou dois minutos, qm guest cmd 120 network-get-interfaces deve retornar dados assim que o agent estiver no ar. Se der timeout, provavelmente o agent ainda não está rodando ou o snippet de vendor não foi aplicado.

O que eu verificaria antes de confiar nele

Um template que dá boot não é a mesma coisa que um template correto. Esta é a minha checagem rápida depois de cada rebuild:

  1. Faça login por SSH com a chave e confirme que o login por senha está desativado.
  2. Confirme que o hostname corresponde ao nome da VM, e não ao do template.
  3. Verifique erros com cloud-init status --long.
  4. Confirme que o guest agent está rodando e que o Proxmox mostra o IP.
  5. Garanta que dois clones não compartilham o mesmo machine ID: cat /etc/machine-id nos dois.

O último item é o motivo de eu ter escolhido uma imagem cloud. É também o que eu menos gostaria de descobrir do jeito difícil.

Colocando tudo no Git

O objetivo de tudo isso é que nada fique só na minha cabeça. Os comandos de build vão em um único script shell, o snippet de vendor fica ao lado dele, e ambos são commitados. Recriar o template passa a ser: apagar a VM 9000 e rodar o script. Ainda não integrei isso ao Ansible. Esse é o próximo passo, e espero que seja mais chato do que a versão em shell, já que os módulos do Proxmox exigem credenciais de API para gerenciar. Gostaria de saber se vale a pena para um fluxo de trabalho com um node de cada vez.

Do que eu não tenho certeza

  • Atualizações da imagem. A imagem current é substituída no upstream. Quero fixar a versão ou, no mínimo, registrar um checksum para que um rebuild seja de fato o mesmo build. Ainda não decidi como.
  • Drift do template. Os clones não são atualizados quando o template muda. Estou tratando as VMs como descartáveis, com os dados em um storage separado, então recriar sai mais barato do que manter uma linhagem de templates com patches. Não tenho certeza de que isso vale para todas as VMs que rodo.
  • Comportamento em cluster. Só testei isso em um node por vez.

Como vocês estão lidando com isso? Vocês montam templates com a CLI qm, Terraform, Packer ou outra coisa? E vocês fixaram as imagens base ou deixam flutuar e lidam com as surpresas?

homelabproxmoxcloud-init
Compartilhar

Have a question about this guide?

Create a free account to ask the community and join the discussion. Members who run the real thing answer every day.