===== Preparare immagini cloud resizable con Oz ===== * Alvise Dorigo (INFN Padova) ==== Informazioni preliminari ==== [[https://github.com/clalancette/oz/wiki|Oz]] è uno strumento largamente utilizzato per la creazione "unattended" di immagini di sistemi operativi che funzionano correttamente in ambienti cloud. Di default Oz ha dei suoi template file per le installazioni automatiche ([[https://access.redhat.com/site/documentation/en-US/Red_Hat_Enterprise_Linux/5/html/Installation_Guide/ch-kickstart2.html|Kickstart]] per RedHat e compatibili, [[http://www.debian.org/releases/stable/amd64/apb.html.it|Preseed]] per Debian/Ubuntu, etc.). E' possibile passare a Oz un file di installazione automatica per produrre immagini costruite in maniera personalizzata; nel nostro caso ci interessa produrre immagini AMI (Amazon Machine Image) che hanno la peculiarità di non contenere partizioni interne, di non avere spazio riservato per lo swap, di avere il cloud-init installato, e alcune modifiche a file per la configurazione di rete. Per funzionare Oz ha anche bisogno di un template file contenente informazioni su dove reperire l'immagine ISO o i file di installazione del S.O. da creare, la size del disco virtuale, eventuali repositories aggiuntivi per l'installazione di pacchetti non standard, e altre personalizzazioni. Per quasi tutti i S.O. supportati da Oz, l'utente può scegliere che l'installazione di pacchetti e certe configurazioni siano dichiarate nel kickstart file (o preseed file) oppure li può far eseguire da Oz mettendoli nel template file. Per Debian, purtroppo, Oz al momento non supporta la customizzazione, per cui la maggior parte delle personalizzazioni vanno fatte nel preseed file o mediante lo strumento [[http://libguestfs.org/guestfish.1.html|guestfish]]. Una volta che Oz ha terminato il build dell'immagine, sarà necessario manipolare l'immagine di qemu (Oz sfrutta qemu/kvm per la creazione dell'immagine) per estrarne l'immagine AMI, che una volta istanziata dentro un ambiente cloud, grazie ad alcuni script del pacchetto cloud-init avrà un filesystem che al boot prenderà la dimensione del disco virtuale specificato dal flavor scelto dall'utente (il flavor è come noto un insieme di caratteristiche di una macchina virtuale: la sua RAM, la dimensione dello swap, il numero di CPU virtuali e la dimensione del disco virtuale). Il motivo per cui vogliamo estrarre la partizione (contenente il root filesystem ''"/"'') interna all'immagine appena creata, è che allo stato attuale OpenStack non è in grado di passare degli argomenti al kernel al momento del boot, nella fattiscpecie il device e/o partizione da cui bootstrappare il S.O.. Esiste [[https://wiki.openstack.org/wiki/LibvirtCustomKernelArgs|questa]] pagina di documentazione in cui si dichiara la possibilità di poterlo fare; tuttavia ho sperimentato che l'immagine AKI continua a ricevere da openstack l'argomento "root=/dev/vda"; non è quindi possibile passargli l'argomento "root=/dev/vda1" a meno di non manipolare pesantemente l'initrd (o initramfs). Questo è documentato [[http://lists.openstack.org/pipermail/openstack-dev/2013-February/005537.html|qui]] e [[https://blueprints.launchpad.net/nova/+spec/expose-ramdisk-kernel-and-command-line-via-rest-and-cli|qui]]. Una volta estratta l'AMI dal file immagine (l'AMI viene estratta come immagine del block device corrispondente alla partizione montata nella root "/" ) questa sarà automaticamente individuata dal kernel AKI come unico device da poter montare in "/" (/dev/vda appunto) e da cui poter lanciare il processo init. ==== Pre-requisiti ==== Oz è un wrapper attorno ad un ambiente virtualizzato. Quindi è necessario che nell'host siano correttamente installati i binari e le librerie di qemu-kvm. Se si installa Oz su una SL o CentOS 6.x con EPEL-6, yum installerà automaticamente tutte le dipendenze. Tuttavia è necessario verificare alcune cose prima di procedere: * Verificare che il processore della macchina host supporti la virtualizzazione; è necessario ottenere un output del genere dal comando lscpu: dorigoa@lxadorigo 18:13:55 ~>lscpu |grep -i virtu Virtualization: VT-x o [root@gilda-11 ~]# lscpu |grep -i virtu Virtualization: AMD-V a seconda ci si trovi su una piattaforma Intel o AMD rispettivamente. * Se il punto precedente è soddisfatto verificare che il modulo kernel sia caricato: dorigoa@lxadorigo 18:15:33 ~>lsmod |grep -i kvm kvm_intel 54394 6 kvm 317504 1 kvm_intel se il modulo non è caricato è necessario farlo manualmente con modprobe: modprobe kvm_intel su piattaforma Intel e modprobe kvm_amd su piattaforma AMD. * Se modprobe fallisce, bisogna verificare nel BIOS della macchina che il supporto hardware alla virtualizzazione sia abilitato. * Verificare che il demone di libvirtd stia girando e sia abilitato al boot: [root@gilda-11 ~]# chkconfig --list|grep libvirtd libvirtd 0:off 1:off 2:off 3:on 4:on 5:on 6:off [root@gilda-11 ~]# service libvirtd status libvirtd (pid 5595) is running... ==== Files di configurazione ==== In [[https://github.com/alvise72/cloud/tree/master/imagebuild|questo]] repository sono presenti, per diverse piattaforme, i kickstart o preseed files e i template files per Oz per la costruzione di immagini cloud-ready e i relativi comandi usati per il build. Le immagini prodotte da Oz (di norma depositate nella directory ''/var/lib/libvirt/images/'' e con estensione .dsk) non sono pero' ancora in formato AMI/AKI/ARI. Per ottenere queste tre componenti si può procedere in due diversi modi. ==== Preparazione immagine ==== === Metodo 1 losetup/kpartx === == Collegare l'immagine ad un device loopback == # > losetup -f -v /var/lib/libvirt/image/myimage.dsk Loop device is /dev/loop1 == Mappare la partizione interna == # > kpartx -a /dev/loop1 add map loop1p1 (253:0): 0 4192902 linear /dev/loop1 63 == Estrarre la partizione root == # > dd if=/dev/mapper/loop1p1 of=myimage_extracted.img == Scollegare il device loopback == # > kpartx -d /dev/loop1 # > losetup -d /dev/loop1 == Estrarre kernel e initrd dall'immagine AMI == # > mount -o loop myimage_extracted.img /mnt # > cp /mnt/boot/vmlinuz . # > cp /mnt/boot/initramfs . # > umount /mnt Ovviamente i filename reali vmlinuz e initramfs saranno comprensivi del numero di versione del kernel. A questo punto i 3 oggetti vmlinux-, initramfs-, myimage_extracted.img sono le 3 componenti AKI, ARI, AMI da caricare dentro glance con la procedura già descritta nella parte finale di questo documento: [[http://wiki.infn.it/cn/ccr/cloud/preparazione_immagini_per_centos_6.4_e_sl6.4_con_cloud-init|Preparare immagine cloud di CentOS 6.4 (x86_64) e ScientificLinux 6.4 (x86_64)]] === Metodo 2 guestfish === == Ottenere il device contenente il root filesystem ("/") con il S.O. == # > guestfish --ro add ubuntu_quantal_x86_64_2G.dsk : run : inspect-os /dev/vda1 == Listare il contenuto della directory /boot == # > guestfish --ro add ubuntu_quantal_x86_64_2G.dsk : run : mount /dev/vda1 / : ls  /boot System.map-3.5.0-17-generic abi-3.5.0-17-generic config-3.5.0-17-generic grub initrd.img-3.5.0-17-generic memtest86+.bin memtest86+_multiboot.bin vmlinuz-3.5.0-17-generic == Estrarre AKI, ARI, AMI == # > guestfish --ro add ubuntu_quantal_x86_64_2G.dsk : run : mount /dev/vda1 / : download /boot/vmlinuz-3.5.0-17-generic vmlinuz-3.5.0-17-generic # > guestfish --ro add ubuntu_quantal_x86_64_2G.dsk : run : mount /dev/vda1 / : download /boot/initrd.img-3.5.0-17-generic initrd.img-3.5.0-17-generic # > guestfish --ro add ubuntu_quantal_x86_64_2G.dsk : run : mount /dev/vda1 / : download /dev/vda1 ubuntu12-10-oz-resize.img === Nota su Debian === ---- **ATTENZIONE:** poiché Oz ancora non implementa la customizzazione per Debian (non si può usare l'opzione "-u") e quindi qualunque customizzazione post creazione dovrà essere fatta tramite il preseed file nei limiti che tale meccanismo impone. Per lo svuotamento del file 75-persistent-net-generator.rules personalmente preferisco utilizzare [[http://libguestfs.org/guestfish.1.html|guestfish]]. Nei miei test quindi, per Debian 7.1 ho usato sempre e solo guestfish per tutta la procedura di preparazione dei componenti AMI/AKI/ARI. Per modificare un file con guestfish: # > guestfish --ro add debian_wheezy_x86_64_2G.dsk : run : mount /dev/vda1 / : write /lib/udev/rules.d/75-persistent-net-generator.rules "# Empty file"