Skip to content

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

1 watching

Forks

Latest commit

 

History

98 Commits

Folders and files

Repository files navigation

mikrolite-images

Kernel and rootfs images for microVMs, built for Flintlock / the Liquidmetal microVM stack.

Kernel (FC) - Build and publish Kernel for k8s (FC) - Build and publish Kernel (CH) - Build and publish Kernel for k8s (CH) - Build and publish Ubuntu - Build and publish RKE2 - Build and publish Lint kernel configs - No modules License: Apache-2.0

The six "Build and publish" workflows above are triggered manually (workflow_dispatch) rather than on every push, so their badges reflect the result of the last manual run, not continuous build status. The "Lint kernel configs" workflow runs automatically on every pull request that touches a .config file.

Overview

This repository builds the kernel and root filesystem images consumed by Flintlock-managed microVMs. It does not contain a runnable application — it is a collection of Dockerfiles and Makefiles that each produce one OCI image, published to ghcr.io/liquidmetal-dev/*, which Flintlock then uses as the kernel and/or disk image source when creating a microVM.

Images are built for two hypervisors:

and two rootfs flavours:

  • A general-purpose Ubuntu guest image with the guest-agent pre-installed
  • An airgapped RKE2 node image, bundling RKE2 install artifacts for offline Kubernetes node bootstrap

Why the kernels have no loadable modules

MicroVMs booted by Flintlock have no mechanism to load kernel modules at runtime. Most boot straight into the kernel with no initrd. Flintlock's overlay volume mode boots with an initrd that Flintlock provides, and that initrd carries no modules either. Every driver a guest needs (virtio, networking, filesystem, etc.) must therefore be built directly into the kernel (=y), not built as a loadable module (=m).

This invariant is enforced twice:

  • At build time, each kernel Dockerfile fails the build if the merged kernel .config contains any =m line.
  • In CI, hack/check-no-modules.sh runs against every *.config file in the repo and is wired into lint-kernel-config.yml, which runs on any pull request touching a .config file.

Images

Directory Image Description
kernel-fc/ ghcr.io/liquidmetal-dev/firecracker-kernel Bare Firecracker-compatible kernel. Builds three variants: 6.1, 5.10, 5.10-no-acpi.
kernel-k8s-fc/ ghcr.io/liquidmetal-dev/firecracker-kernel-k8s Firecracker kernel with additional netfilter/IPVS/bridge config needed for Kubernetes nodes (kube-proxy, CNI). Variants: 6.1, 5.10.
kernel-ch/ ghcr.io/liquidmetal-dev/cloudhypervisor-kernel Bare Cloud Hypervisor kernel (6.2) plus a matching 6.2-headers image.
kernel-k8s-ch/ ghcr.io/liquidmetal-dev/cloudhypervisor-kernel-k8s Cloud Hypervisor kernel (6.2) with the same Kubernetes networking config additions as kernel-k8s-fc.
ubuntu/ ghcr.io/liquidmetal-dev/ubuntu Ubuntu 24.04 rootfs with networking, systemd and cloud-init configured, and guest-agent installed and enabled as a systemd service.
rke2/ ghcr.io/liquidmetal-dev/node-rke2-airgapped Ubuntu 22.04-based RKE2 node rootfs, pre-loaded with RKE2 release artifacts for airgapped/offline installation.

Each kernel image is built from real upstream linux-stable source, using kernel .configs sourced from the Firecracker/Cloud Hypervisor projects and merged with the additional config fragments in each directory's configs/ folder (kernel-k8s-ch/ keeps its fragments at the directory root).

Kernel images are published under a moving tag and a timestamped one, see Kernel image tags.

Every kernel also gets the erofs.config fragment, which enables the EROFS filesystem. Flintlock's overlay volume mode presents the root filesystem as a read-only EROFS image. The fragment is copied into each kernel directory because each directory is its own docker build context; hack/check-fragments-match.sh fails the lint when a copy is missing or the copies differ.

Kernel image tags

Every kernel build is published under two tags:

Tag Example Behaviour
<version>-<build id> 6.1-20260929-1432 Names one build and is never overwritten.
<version> 6.1 Moves to the newest build each time one is published.

The build id is the UTC time the build started, as YYYYMMDD-HHMM, so the tags of an image sort from oldest to newest. Variants keep their suffix ahead of the build id: 5.10-no-acpi-20260929-1432, 6.2-headers-20260929-1432. All the variants from one publish share a build id.

Use the short tag to follow the latest kernel, and a timestamped tag to stay on a known build or to go back to an older one:

ghcr.io/liquidmetal-dev/firecracker-kernel:6.1-20260929-1432

Each image also carries labels that say what is inside it:

Label Value
org.opencontainers.image.version The timestamped tag the image was published as.
org.opencontainers.image.created When the build started.
org.opencontainers.image.revision The commit of this repository it was built from.
dev.liquidmetal.kernel.version The linux-stable tag that was compiled, e.g. 5.10.245.
docker buildx imagetools inspect ghcr.io/liquidmetal-dev/firecracker-kernel:6.1 \
  --format '{{json .Image.Config.Labels}}'

make push never replaces a timestamped tag that is already in the registry. If the tag holds a different image, nothing is pushed. If it holds the image being pushed, the tag is skipped, so a make push that failed part way can be run again. The publish workflows run one at a time for each image.

Building locally

Every component follows the same make interface:

cd <component>       # e.g. ubuntu, kernel-fc, rke2, ...
make build            # docker build
make push             # docker push

The target registry defaults to ghcr.io/liquidmetal-dev and can be overridden:

make build REGISTRY=my-registry.example.com

For the kernel images, make build records the build id it used in out/build-id and make push publishes that build. Set BUILD_ID on both to choose the value yourself:

make build BUILD_ID=20260929-1432
make push BUILD_ID=20260929-1432

Docker (with buildx) is the only required tool — kernel builds compile the actual Linux kernel inside the build container, so expect kernel-image builds to take a while.

Repository layout

kernel-fc/          Bare Firecracker kernel (6.1, 5.10, 5.10-no-acpi)
kernel-k8s-fc/       Firecracker kernel with Kubernetes networking config
kernel-ch/           Bare Cloud Hypervisor kernel (6.2)
kernel-k8s-ch/       Cloud Hypervisor kernel with Kubernetes networking config
ubuntu/              Ubuntu rootfs image with guest-agent
rke2/                Airgapped RKE2 node rootfs image
hack/                Repo-wide dev/CI scripts (e.g. check-no-modules.sh) and the shared kernel tagging
.github/workflows/   CI: per-image build-and-publish workflows, kernel-config lint

License

Apache License 2.0, see LICENSE.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages