How to Build a Live* Disk Image Eric Lalonde, Olaf Manczak How to Build a Live* Disk Image Copyright © 2008 Sun Microsystems, Inc. All Rights Reserved. Use is subject to license terms. 2 How to Build a Live* Disk Image 1 Introduction This document describes the Live* software disk image creation process for an operating system image. It includes details regarding how an immutable software disk image is created from a standard disk image. In this document we walk through the build process of a Fedora 8 Core Operating System software disk image. This process is canonical, and the model can be adapted to generate Live* software disk images for other operating systems as well. The disk image creation process has 5 major steps. The result of each step is either an additional set of files to be copied to the software image, or a set of files to be excluded from the software image. An example where files are excluded is configuration files that are tailored for a specific deployment. The below diagram illustrates the 5 steps of generating a software disk image from a disk image: @44/$4*&'1 6@A >,.?(>*/* <1''(=8*#' C1,3,+*$(>,.?(B)*3' ② !"#$%&'(!$' )*+,-'./ ③ @%,$&(943,# 0'+'1*/41.5( 6*+,-'./(*+& 7148'1/,'. ④ ① 0'+'1*/'& ,+,/1&2,)3 9,:';( 6'/*&*/* 7*1/,/,4+(E 7*1/,/,4+(D 9,:';(>,.?(B)*3' 0'+'1*/41. 9,:';( 6'/*&*/* @44/$4*&'1 6@A >,.?(>*/* ⑤ 1 The build process generates a new initrd boot archive which executes the Live* runtime during the boot discovery process. This new initrd is copied to the Live* image /boot directory. 2 The build process generates a list of files to exclude from the original disk data. These include log files, caches, and configuration files that will be generated during the Live* runtime. 3 The build process copies the data from the original disk image, except for those files that are specified in the exclude manifest. 4 The build process copies the generators, a generator manifest, and default properties from the build source tree to the Live* image. 5 The build process appends image metadata information to the tail of the image. The metadata is either determined from the filename of the original disk image or specified in the Makefile. 3 How to Build a Live* Disk Image 2 Disk Image Format The format of Live* disk images varies slightly from the format of disk images used in traditional, “monolithic” virtual appliances. Besides a regular partition with software, the Live* images contain an additional partition with so-called generators – programs and scripts used by the Live* runtime for dynamic generation of per-instance configuration data, and a metadata section which describes content of the image. Also, since the Live* disk images are immutable the amount of free space both in the software and in the generators partition is minimal.The diagram below illustrates the format of a Live* disk: Generators metalen metacrc 8 bytes 4 bytes 4 bytes metalen magic Signature Partition 4 Partition 3 Partition 2 Partition 1 name=fedora8\0group=os\0... Live* Metadata Bootloader MBR Code Area Disk Data The partition table in the Master Boot Record (MBR) contains two valid partitions (partition 1 for the software and partition 2 for the generators). Both partitions end at the cylinder boundaries and the first partition leaves first track for the MBR and bootloader. Both of them contain ext3 file systems. The metadata section is appended at the end of the second partition (i.e. at the end of the image). It contains a dictionary of <key>=<value> strings separated by nul characters. A 16-byte long structure at the end of the metadata section end (i.e. the very end of the image) contains a magic string TCIDATEM, and two little-endian 32-bit unsigned integer values representing, respectively, the length and CRC checksum of the dictionary. 3 Disk Image Build Process In this section we describe details of the Live* disk image build process. Typically, the Live* images containing a bootable operating system are derived from traditional virtual appliance disk images created by installation of the operating system within the virtual machine. This process resembles conventional V2V or P2V conversion and it involves instrumentation of the initrd boot archive. The images with other software components can be derived from the union file system copy-up disk images (after a software component was installed in a Live* virtual environment). The process of building images with non-operating-system (non-bootable) components is much simpler, as it does not require any instrumentation to the initrd boot archive. The Live* reference implementation contains a set of Makefiles, scripts and supplemental files that automate the build process for several different releases of Fedora Linux. We believe that the automation process can be easily customized and extended to other Linux flavors. This description follows the path of the make process and can it might serve as a companion to reading the build process Makefiles. 4 How to Build a Live* Disk Image 3.1 Setting Build Variables To build a bootable operating system software image, one needs to first set the appropriate environment variables. This can be achieved by creating a file called ~/.makeit in the user’s home directory. An example ~/.makeit will have the following: SOURCE_BASE=/path/to/source BUILD_BASE=/path/to/build/space IMAGE=/path/to/original/disk/image ALTIMAGE=/path/to/image/or/directory/with/compilers/and/kernel/headers Once the ~/.makeit file is created, the script ${SOURCE_BASE}/build/makeit may be executed, which starts the build process. To make the build process more reproducible the makeit script unsets all unneeded shell environment variables and it executes the make command passing the parameters given in the ~/.makeit file. If the original image contains a minimal operating system distribution that lacks either gcc or the kernel headers, then the user has to specify location of and image or a directory tree containing a full distro. 3.2 Mounting the original image The first step of the build process is to make the ${SOURCE_BASE}/runtime/imagini target. This target mounts ${IMAGE} to ${BUILD_BASE}/runtime/mnt. The image is loopback-mounted so that its contents can be copied to the new software disk image, and so that all compilation links against the libraries on the source image. 3.3 Compilation of the union file system kernel module Most Linux distributions lack union file system. However, the union file system can be added as an additional kernel module. There are two independent implementations of union file system for Linux: unionfs developed and maintained by Erez Zadok’s FiST project, and aufs created and maintained by Junjiro Okajima. In the Live* reference implementation we use aufs. Once the ${IMAGE} file is mounted, the build process compiles an aufs kernel module and, under some circumstances, a customized kernel RPM. For kernel versions 2.6.24 and higher, a patched kernel RPM is generated. This rpm contains a patched vmlinuz kernel that supports aufs. This patch is only necessary for kernel version 2.6.24 and higher. Once the aufs kernel module and the custom kernel are generated, they are placed in a path relative to ${BUILD_BASE}/runtime/imagemod/root. Later in the build process, the contents of this directory are copied into the Live* software disk image. 3.4 Compilation of the Live* runtime Next the build process compiles the Live* runtime. The runtime is a set of programs used as instrumentation to the initrd boot archive. The sources for these targets are located in ${SOURCE_BASE}/runtime/libs and ${SOURCE_BASE}/runtime/progs. Later in the build process, each of the programs is injected into the instrumented initrd (boot archive) of the software disk image. For now the build process places the compiled binaries into ${BUILD_BASE}/runtime/bin. 3.5 Generating new grub.conf The next step in the build is to generate a customized bootloader configuration file grub.conf (or menu.lst). The bootloader configuration contains a single boot entry (choice). The initrd archive referenced by this entry will be generated later in the build process. The vmlinuz kernel 5 How to Build a Live* Disk Image file referenced by this entry will either be copied out of ${IMAGE} or the result of the kernel build process, depending on the kernel version. (see 3.3). 3.6 Locating and copying of the kernel file Next, the build process determines whether to copy the vmlinuz kernel from the source image or to extract it from the patched kernel rpm that was generated during step 3.3. The kernel is copied into the ${BUILD_BASE}/runtime/imagemod/root/boot directory. 3.7 Generating new boot archive (initrd) The next stage in the image build process modifies the original initrd archive from the source disk image to support the Live* runtime. This modified initrd archive is then copied into the ${BUILD_BASE}/runtime/imagemod/root/boot directory. The initrd patching step is broken into the following sub-steps. 3.7.1 Unpacking the original boot archive to temporary directory. During this sub-step, the contents of the initrd archive on ${IMAGE} is extracted to a temporary directory ${BUILD_BASE}/runtime/imagemod/initrd. 3.7.2 Installing Live* runtime files The second sub-step in the initrd patching process is to copy the compiled runtime binaries to ${BUILD_BASE}/runtime/bin to ${BUILD_BASE}/runtime/imagemod/initrd/bin. 3.7.3 Installing selected kernel modules from the original mounted disk image The third sub-step is to locate the necessary kernel modules (storage and file system drivers) on the mounted disk image and copy them to ${BUILD_BASE}/runtime/imagemod/initrd/lib. These modules are specified by $(FILES_KOBJS) in the imagemod Makefile. 3.7.4 Installing union file system kernel module Next the previously compiled aufs.ko kernel object is copied out of the aufs build directory to ${BUILD_BASE}/runtime/imagemod/initrd/lib. 3.7.5 Installing additional files required by the Live* runtime The programs referenced by $(FILES_IMAGE) are next located on the mounted disk image and copied to ${BUILD_BASE}/runtime/imagemod/initrd/bin. These files are utilized during the Live* runtime to decompress various archive types. 3.7.6 Instrumenting the init script The next sub-step is to instrument the init script. This script conducts the boot device discovery process after the initrd is loaded into memory. The init script is instrumented such that it calls programs that build the virtual file system out of Live* software disk images and generated content instead of simply identifying the root volume partition. This instrumented script is stored in to ${BUILD_BASE}/runtime/imagemod/initrd/init. 3.7.7 Repacking the boot archive (initrd) After all previous steps copy and instrument the contents of the extracted initrd archive, the directory is repacked into a gzip’ed cpio archive. This repacked archive is stored in ${BUILD_BASE}/runtime/imagemod/root/boot, until it is copied to the software disk image, which occurs later in the build process. 6 How to Build a Live* Disk Image 3.8 Excluding unneeded files from the original image Before we start copying the contents of the original image into the software partition of the newly created Live* image we have to create a list of files and directories to exclude. It is often desirable for files such as system logs, caches, or files containing system-specific personalization to be excluded from the immutable disk image. The list of excluded files is generated dynamically based on a set of “exclude rules” which are specified beforehand by the user. These are used to either include, exclude, or recursively exclude files and directories. An example of an exclude manifest file can be found in ${SOURCE_BASE}/runtime/imagemod/Fedora-8/exclude. The following three examples explain the syntax and meaning of the rules specified in an exclude manifest. Example 1: Recursively exclude rule: - /tmp/** In the above rule, the – (minus) designates this rule as exclude. The directory to be excluded is specified after the minus sign. The ** (asterisks) specify that the rule applies to all files in all subdirectories of /tmp as well. Example 2: Recursively exclude but maintain directory structure rule: = /var/log/** In the above rule, the = (equal) sign designates that, while the contents of /var/log are to be excluded, any subdirectory structure of /var/log should be maintained. The ** (asterisks) denote that the files in /var/log and all subdirectories should be excluded as well. Example 3: Include regardless of other rules: + /etc/blkid/blkid.tab This rule specifies that the file /etc/blkid/blkid.tab should be retained (that is, not excluded from the Live* software disk image) regardless of any other rules which might exclude the file. Rules that include files are specified via the + (addition) operator, and always take precedence over rules that exclude files. When the exclude manifest is evaluated during the build process, a complete list of files to exclude is generated and stored in ${SOURCE_BASE}/runtime/imagemod/Fedora-8/exclude. 3.9 Generating the software partition of the Live* disk image At this point the build process is ready to generate partition 1 of the software disk image. Data comes from three sources: • The original (loopback-mounted) disk image • The directory ${BUILD_BASE}/runtime/imagemod/root, which contains files that have been built by previous steps in the build process. These files will take precedence over files with the same path that reside on the mounted image. • A list of files to not include from the original image. These are generally logs, caches, or system-specific data. The build process uses the Python script ${BUILD_BASE}/launchpad/imagetool to determine the space requirements and create the software disk image. The imagetool Python script takes 7 How to Build a Live* Disk Image the three aforementioned data sources as inputs and copies the appropriate files to the first partition of the new Live* software disk image. 3.10 Generating the generators partition of the Live* disk image The imagetool script also generates the second partition of the Live* software disk image. This is achieved copying the contents of ${SOURCE_BASE}/runtime/imagemod/Fedora-8 to the partition. The directory tree with the generators for the software disk image originates from the gen sub-directory. The file gen/MANIFEST the contains a list of generators, one per line, that designate which generators to execute during the early boot process. The path to each generator in the MANIFEST should be relative to the gen directory. The file PROPERTIES contains a set of default key-value pairs that are used by generators. 3.11 Appending Live* metadata The final step in the build process is to append Live* metadata to the software disk image. This metadata enables the Live* system to identify software disk images and include each in the virtual file system. Metadata is specified in key-value pairs, and each pair is delimited by the null character. The metadata is specified in ${SOURCE_BASE}/runtime/imagemod/Makefile. By default the metadata includes three parameters: the logical name of the image (e.g. name=Fedora 8), the kernel version kverrel (e.g. kverrel=2.6.24-3) and the image group. The group parameter specifies to which group this Live* software disk image belongs. For operating system disk images, the value of this key is os (i.e. group=os). 3.12 Location of the generated Live* software disk image. After Live* metadata is appended to the software disk image, the build process is complete. The generated software disk image is stored in ${BUILD_BASE}/runtime/imagemod. 8
© Copyright 2024