Provisioning Fedora/CentOS bootc on Amazon Web Services

This guide shows how to provision new Fedora/CentOS bootc instances on the Amazon Web Services (AWS) cloud platform.

Prerequisites

It is possible to directly run the base images, without creating a customized one. This can be useful for experimentation. However, an important use case here for Fedora/CentOS bootc is to create custom derived container images, and then instantiate them.

In this example, you must have access to an AWS account. The examples below use the aws command-line tool, which must be separately installed and configured beforehand.

No cloud-init or hypervisor-specific metadata tools included by default

Unlike Fedora Cloud or Fedora CoreOS (or in general many pre-generated disk images) the default base image does not include a tool such as cloud-init or afterburn to fetch SSH keys or execute scripts from the hypervisor.

For more on this, see Cloud Agents.

No separate pre-generated AMIs

At the current time, the Fedora/CentOS bootc project does not produce pre-built AMIs for the base images. There are two primary paths to running in AWS:

Understanding bootc install to-existing-root

A very useful and low-cost mechanism for provisioning a container image without generating a disk image is to use the bootc install to-existing-root flow, where the container image "installs itself" alongside an existing root filesystem, setting it up for the next boot. ( Upstream documentation )

Understanding bootc-image-builder

The bootc-image-builder tool can generate a disk image (such as an AMI) from a given container image.

Provisioning

With bootc install to-existing-root

The fundamental architecture here is:

Launch existing package based + cloud-init Fedora/CentOS AMI, with attached cloud-init metadata that installs podman, which fetch your target container that install itself to the target root.

Then on reboot, your system has been replaced with the container image content.

Save the following file as e.g. run-bootc-install:

#!/bin/bash
dnf -y install podman
podman run --rm --privileged -v /dev:/dev -v /var/lib/containers:/var/lib/containers -v /:/target \
             --pid=host --security-opt label=type:unconfined_t \
             <image> \
             bootc install to-existing-root

Replace <image> with your container image in this text file.

The default base image does not include cloud-init; so any keys fetched from the instance metadata will not by default be re-applied on the subsequent boot. As the bootc documentation notes, there is special case support for injecting a SSH key from the initial running system.

To do this, add --root-ssh-authorized-keys /target/root/.ssh/authorized_keys (or /target/home/cloud-user/.ssh/authorized_keys, depending on your cloud-init configuration).

The SSH authorized_keys data will be copied from the host system into the target system.

Launching an instance
NAME='instance1'
SSHKEY='my-key'     # optional: the name of your SSH key: `aws ec2 describe-key-pairs`
IMAGE='ami-xxx'     # the AMI ID as used by e.g. https://fedoraproject.org/cloud/download or https://www.centos.org/download/aws-images/
DISK='20'           # the size of the hard disk
REGION='us-east-1'  # the target region
TYPE='m5.large'     # the instance type
SUBNET='subnet-xxx' # the subnet: `aws ec2 describe-subnets`
SECURITY_GROUPS='sg-xx' # the security group `aws ec2 describe-security-groups`
USERDATA='/path/to/run-bootc-install' # path to your user-data script
aws ec2 run-instances                     \
    --region $REGION                      \
    --image-id $IMAGE                     \
    --instance-type $TYPE                 \
    ${SSHKEY:+--key-name $SSHKEY}         \
    --subnet-id $SUBNET                   \
    --security-group-ids $SECURITY_GROUPS \
    --user-data "file://${USERDATA}"      \
    --tag-specifications "ResourceType=instance,Tags=[{Key=Name,Value=${NAME}}]" \
    --block-device-mappings "VirtualName=/dev/xvda,DeviceName=/dev/xvda,Ebs={VolumeSize=${DISK}}"

Creating an AMI with bootc-image-builder

The canonical documentation is in the bootc-image-builder upstream site. Conceptually, the tool takes as input a bootc container image, and can create disk images such as AMIs and also help upload them to cloud infrastructure.

Additionally, "static" configuration can be injected as part of the disk image.

Once you have generated an AMI, subsequent operating system changes can be made by just building and pushing a new container image to the registry; any existing instances will fetch updates from it automatically and synchronize to that state. Hence, you do not need to produce a new AMI for every container image change.

A generally useful pattern is to only produce new AMIs periodically, when you want to ensure that newly provisioned instances boot directly into the latest container image state.