Thankfully the Fedora Project provides cloud images that can be directly used or easily modified to run on almost any cloud environment. Though sometimes, it can be handy to build your own image.
0. Prerequisites
Fedora images in general and the cloud images especially are built using ImageFactory which itself uses Oz. The latest versions can always be found on koji. To recreate an image locally, there are a couple of tools needed:
dnf install imagefactory imagefactory-plugins* pykickstart
1. Kickstart and template
To build an image with ImageFactory, you’ll need two files: a kickstart file and an imagefactory template.
The kickstart files for the (official) Fedora images are part of the fedora-kickstarts package and be installed locally with dnf
dnf install fedora-kickstarts
of pulled from the fedora-kickstarts git repository at https://pagure.io/fedora-kickstarts.
The template file is an xml decription of what to build (OS version, architecture, etc.). A sample template file can be seen below:
<template> <name>fedora-cloud-custom</name> <os> <name>Fedora</name> <version>27</version> <arch>x86_64</arch> <install type='url'> <url>https://dl.fedoraproject.org/pub/fedora/linux/releases/27/Everything/x86_64/os/</url> </install> </os> </template>
The template file can either have an .xml or a .tdl extension and is usually automatically generated by the koji build deamon (see https://pagure.io/koji/blob/dad74a3/f/builder/kojid#_4040 and https://pagure.io/koji/blob/dad74a3/f/builder/kojid#_3517)
2. Modifying Oz default config
ImageFactory will create a temporary virtual machine that’s used to install Fedora into a raw disk file. Depending on the package selection you might need more that 1GB of RAM which is the Oz default on Fedora. To modify the memory limit, change the memory parameter in the Oz configuration file
... [libvirt] uri = qemu:///system image_type = raw # type = kvm # bridge_name = virbr0 # cpus = 1 memory = 2048
You can either use your favourite editor or run
sed -i -e 's/# memory = 1024/memory = 2048/' /etc/oz/oz.cfg
3. Building a raw disk image
Now it’s time to build the actual image. Since the kickstart file might be hierarchical, i.e. contain %include statements to point to user kickstart files, we need to create a ‘flat’ version first:
tempfile=$(mktemp --suffix=.ks) ksflatten -v F27 -c /usr/share/spin-kickstarts/fedora-cloud-base.ks > ${tempfile}
Of course, the kickstart file can be customized first.
To build the image, run
imagefactory base_image \ --file-parameter install_script ${tempfile} fedora-cloud-custom.tdl \ --parameter offline_icicle true
The offline_icicle parameter is necessary to tell Oz that it should rather mount the disk image and chroot into it instead of spawning a temporary throwaway VM and ssh-ing into it to run RPM commands.
After a short while ImageFactory will print the UUID of the created image:
============ Final Image Details ============ UUID: 925b9ac8-7dca-4a9f-b055-330b23e45923 Type: base_image Image filename: /var/lib/imagefactory/storage/925b9ac8-7dca-4a9f-b055-330b23e45923.body Image build completed SUCCESSFULLY!
4. Creating a Google Compute Engine image
There is a GCE plugin for ImageFactory that allows you to easily package the created raw disk image:
imagefactory target_image --id <UUID> gce
Unfortunately, that plugin is not packaged for Fedora yet, so this needs to be done manually. Looking at the plugin source code, we’ll have to reproduce what the builder_did_create_target_image function does:
qemu-img convert -O raw \ /var/lib/imagefactory/storage/925b9ac8-7dca-4a9f-b055-330b23e45923.body \ /var/lib/imagefactory/storage/80e6d1d6-0207-4831-a68f-6a1f06a6841f.body.tmp tar cfz fedora-cloud-custom.tar.gz \ /var/lib/imagefactory/storage/80e6d1d6-0207-4831-a68f-6a1f06a6841f.body.tmp \ --sparse --transform=s/.*tmp/disk.raw/
The resulting fedora-cloud-custom.tar.gz tarball can then be used to create a GCE image:
gsutil cp fedora-cloud-custom.tar.gz gs://<bucket>/ gcloud compute images create --source-uri gs://<bucket>/fedora-cloud-custom.tar.gz fedora-cloud-custom gcloud compute instances create fedora --machine-type f1-micro --image fedora-cloud-custom --zone us-east1-b
Resources:
https://fedoramagazine.org/building-fedora-rawhide-images-imagefactory/