cloud-init, cloud image e Cloud Hypervisor
Três nomes que aparecem juntos e fazem coisas diferentes. Confundi-los é a causa mais comum de uma VM que arranca e não faz nada — ou que não arranca de todo.
Os três em uma frase
| Peça | O que é | Quando aparece |
|---|---|---|
| cloud image (cloud-img) | Um disco .qcow2 publicado por uma distro, já instalado e
pronto a arrancar. Não tem utilizador, nem password, nem chave SSH. |
O FROM de um VMfile, e o disco base de
vm create. |
| cloud-init | O programa que corre DENTRO dessa imagem no primeiro arranque e a personaliza: hostname, utilizadores, chaves, rede, comandos. | É o que torna a cloud image utilizável. Sem ele, ficas com um disco genérico onde não consegues entrar. |
| Cloud Hypervisor | Um VMM — o programa do HOST que executa a VM. Alternativa ao QEMU/libvirt, feito para microVMs. | --backend cloud-hypervisor, e obrigatório para
type: microvm. |
Analogia com containers, que ajuda mais do que qualquer definição:
a cloud image é a imagem, o cloud-init é o
ENTRYPOINT da primeira execução, e o
Cloud Hypervisor é o runtime — o equivalente ao
runc.
1 · Cloud image — o disco
Cada distro publica um qcow2 pré-instalado, pequeno (algumas centenas de MB) e com o cloud-init já lá dentro. O motor sabe descarregar três famílias e verifica sempre o checksum — nunca aceita um download sem o confrontar.
# Num VMfile
FROM ubuntu:24.04 # cloud-images.ubuntu.com
FROM debian:bookworm # cloud.debian.org
FROM rocky:9 # dl.rockylinux.org
# Ou directamente, sem VMfile nenhum
delonix vm create dev --url-img https://.../imagem.qcow2
Os três publicam checksums de maneiras diferentes,
e isso está tratado: Ubuntu usa SHA256SUMS no formato GNU, Debian
publica só SHA512SUMS (não há SHA256 nenhum), e
Rocky usa um .CHECKSUM por ficheiro no formato BSD
SHA256 (ficheiro) = hash. Com --url-img, o motor
procura um <url>.sha256 ao lado; se não existir,
diz que está a confiar só no TLS em vez de calar.
O disco vem pequeno de propósito — tipicamente 2 GB. Cresce-o
antes de instalares seja o que for, com SIZE 20G no VMfile: crescer
depois de um RUN ter enchido o disco é tarde.
2 · cloud-init — a personalização do primeiro arranque
Uma cloud image acabada de descarregar não tem conta nenhuma. O cloud-init
procura um datasource no arranque, lê de lá o user-data, e
aplica-o. O Delonix usa o datasource NoCloud: gera um ISO por
instância e liga-o à VM.
# O motor gera o seed sozinho quando lhe dás qualquer um destes
delonix vm create dev --hostname dev-01 --ssh-key ~/.ssh/id_ed25519.pub
delonix vm create dev --user-data ./user-data.yaml
delonix vm create dev --seed ./o-meu-seed.iso # ISO já feito por ti
Um user-data mínimo e completo:
#cloud-config
hostname: dev-01
users:
- name: delonix
groups: [sudo]
shell: /bin/bash
sudo: ['ALL=(ALL) NOPASSWD:ALL']
ssh_authorized_keys:
- ssh-ed25519 AAAA... o-teu-email@exemplo
package_update: true
packages: [nginx]
runcmd:
- [systemctl, enable, --now, nginx]
final_message: "pronto em $UPTIME segundos"
Duas camadas, e a distinção importa. O
CLOUDINIT de um VMfile é assado NA IMAGEM (fica em
/etc/cloud/cloud.cfg.d) — é o comportamento por omissão de
todas as VMs feitas a partir dela. O --user-data do
vm create é POR INSTÂNCIA e assenta por cima. Uma é a receita da
imagem, a outra é a configuração daquela VM.
Armadilha real, já paga: um kind: Vm
sem seed nenhum fazia o cloud-init saltar a fase de rede, e a VM ficava sem IP e
sem rota (Network is unreachable lá dentro). Por isso o motor gera
sempre um seed mínimo, mesmo quando não pedes nada — não é
opcional.
E o cloud-init só corre uma vez: guarda um marcador em
/var/lib/cloud. Um vm restart não o volta a executar —
para reaplicar, ou limpas esse estado dentro da VM ou crias outra.
3 · Cloud Hypervisor — o VMM
Quem executa a VM. O Delonix tem dois backends por trás do mesmo trait, e a escolha não é cosmética:
| Cloud Hypervisor | libvirt/QEMU | |
|---|---|---|
| Arranque | Muito rápido (dezenas de ms) — feito para microVMs | Segundos; máquina completa emulada |
| Dispositivos | Só virtio, mínimo | Tudo (TPM, vídeo, USB, …) |
| Rede | tap na SDN do holder — alcança os
containers por IP directo |
virbr0, no netns do HOST — outra L2 |
| Isolamento por namespace | Sim | Não — --namespace é recusado com erro, não
aceite-e-ignorado |
| Snapshots | Não implementado (fail-closed, com erro que aponta para o libvirt) | vm snapshot/restore: memória + disco |
| Arranque de cloud image | Precisa de firmware
(hypervisor-fw/EDK2) ou de kernel+initrd directos |
Arranca a cloud image tal como está |
delonix vm create micro --backend cloud-hypervisor --firmware /usr/share/hypervisor-fw
delonix vm create pesada --backend libvirt # default quando CH não está instalado
Qual usar, e quando
| Se queres… | Usa |
|---|---|
| Uma VM de trabalho, com snapshots e consola | --backend libvirt (é o que a golden do Kubernetes exige — não arranca em CH) |
| Arranque em milissegundos, isolamento por namespace, ou alcançar containers por IP | --backend cloud-hypervisor + firmware |
| Personalizar UMA VM | cloud-init por instância: --hostname/--ssh-key/--user-data |
| Personalizar TODAS as VMs de um modelo | Um VMfile com CLOUDINIT, e vm build |
| Um disco à tua medida, publicável | vm init --vmfile → vm build → vm push |
Onde isto falha, e o que ver
| Sintoma | Quase sempre é |
|---|---|
| A VM arranca e não entras por SSH | Sem seed de cloud-init — não há utilizador nenhum. Passa
--ssh-key. |
IP <none> para sempre |
libvirt caiu em modo user (SLIRP), cujo IP é invisível. Junta-te
ao grupo libvirt — o motor avisa-o no create. |
| A VM não arranca em Cloud Hypervisor | Falta o firmware. CH não faz boot BIOS: precisa de
--firmware ou de --kernel+--initrd. |
O disco enche a meio do vm build |
SIZE em falta, ou depois de um RUN. É
propriedade da stage, e corre antes de tudo. |
Mudaste o user-data e nada muda |
O cloud-init já correu naquela VM. Cria outra, ou limpa
/var/lib/cloud lá dentro. |
Referências
- Documentação do cloud-init — e em especial os exemplos de user-data e o datasource NoCloud, que é o que o Delonix usa.
- Cloud images do Ubuntu · do Debian · do Rocky
- Cloud Hypervisor e o
rust-hypervisor-firmware
(o
--firmwareque uma cloud image precisa para arrancar em CH). - Formato do domínio libvirt —
útil se usares os escape-hatches
libvirtXml/libvirtXmlOverlaydokind: Vm.