Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 59 additions & 0 deletions .github/workflows/capmvm-kubernetes-arm-manual.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
name: CAPMVM (ARM, experimental) - Build and release

on:
workflow_dispatch:
inputs:
k8s_version:
description: "K8s version (major.minor). For example 1.30"
required: true
k8s_patch_version:
description: "K8s patch version"
required: true
default: "0"
containerd_version:
description: "Containerd version (major.minor.patch). For example 1.7.27"
required: true
ubuntu_version:
description: "Ubuntu version"
required: true
default: "22.04"
type: choice
options:
- "22.04"
- "24.04"
- "20.04"

permissions:
id-token: write
contents: read
packages: write

defaults:
run:
working-directory: experimental/arm/capmvm/kubernetes

jobs:
buildandpublish:
name: Build and publish CAPMVM (ARM64)
runs-on: ubuntu-latest
env:
REGISTRY: ghcr.io/${{ vars.REGISTRY_OWNER || github.repository_owner }}
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to container registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push ARM image
run: |
RELEASE_VERSIONS=${{ inputs.k8s_version }}.${{ inputs.k8s_patch_version }} \
CONTAINERD_VERSION=${{ inputs.containerd_version }} \
UBUNTU_VERSION=${{ inputs.ubuntu_version }} \
make build-and-push
3 changes: 3 additions & 0 deletions .github/workflows/capmvm-kubernetes-manual.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ jobs:
buildandpublish:
name: Build and publish CAPMVM
runs-on: ubuntu-latest
env:
# Push to this repo's GHCR (e.g. ghcr.io/myownusername on a fork). Set vars.REGISTRY_OWNER to override.
REGISTRY: ghcr.io/${{ vars.REGISTRY_OWNER || github.repository_owner }}
steps:
- name: checkout code
uses: actions/checkout@v5
Expand Down
62 changes: 54 additions & 8 deletions .github/workflows/kernel-images-manual.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,71 @@ name: Kernel (manual) - Build and release

on:
workflow_dispatch:
branches: [main]
inputs:
arch:
description: 'Architecture to build'
required: true
default: 'amd64'
type: choice
options:
- amd64
- arm64

defaults:
run:
working-directory: kernel

jobs:
release-firecracker:
release-firecracker-amd64:
if: inputs.arch == 'amd64'
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
strategy:
fail-fast: false
matrix:
version: [ 4.19.215, 5.10.77 ]
version: [4.19.215, 5.10.77, 6.1.102]
env:
REGISTRY: ghcr.io/${{ vars.REGISTRY_OWNER || github.repository_owner }}
ARCH: amd64
FC_KERNEL_VERSIONS: ${{ matrix.version }}
PUSH: --push
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Login to container registry
uses: docker/login-action@v1.10.0
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push
run: |
make build-fc
make push-fc
release-firecracker-arm64:
if: inputs.arch == 'arm64'
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
strategy:
fail-fast: false
matrix:
version: [5.10.77, 6.1.102]
env:
REGISTRY: ghcr.io/${{ vars.REGISTRY_OWNER || github.repository_owner }}
ARCH: arm64
FC_KERNEL_VERSIONS: ${{ matrix.version }}
PUSH: --push
steps:
- uses: actions/checkout@v4
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to container registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
Expand All @@ -33,20 +76,23 @@ jobs:
make build-fc
make push-fc
Copy link

Copilot AI Mar 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the arm64 manual job, PUSH=--push means the build step uses docker buildx build --push and won’t leave local images behind. Running make push-fc afterwards (docker push) is likely to fail because the tags aren’t present locally. Either skip make push-fc for arm64, or change the build to --load and then push, or update the Makefile push logic for buildx.

Suggested change
make push-fc

Copilot uses AI. Check for mistakes.
release-cloudhypervisor:
if: inputs.arch == 'amd64'
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
strategy:
fail-fast: false
matrix:
version: [ 5.12 ]
version: [5.12, 5.15.12]
env:
REGISTRY: ghcr.io/${{ vars.REGISTRY_OWNER || github.repository_owner }}
ARCH: amd64
CH_KERNEL_VERSIONS: ${{ matrix.version }}
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Login to container registry
uses: docker/login-action@v1.10.0
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
Expand Down
71 changes: 56 additions & 15 deletions .github/workflows/kernel-images.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,59 +8,98 @@ on:
push:
paths:
- 'kernel/**'
branches: [main]
branches: [main, issue/*]
workflow_dispatch:

defaults:
run:
working-directory: kernel

jobs:
build-firecracker:
if: github.event_name != 'push'
if: github.event_name == 'pull_request'
runs-on: ubuntu-latest
permissions:
contents: read
strategy:
fail-fast: false
matrix:
version: [ 4.19.215, 5.10.77 ]
# arm64 has configs only for 5.10.77 and 6.1.102
include:
- arch: amd64
version: 4.19.215
- arch: amd64
version: 5.10.77
- arch: amd64
version: 6.1.102
- arch: arm64
version: 5.10.77
- arch: arm64
version: 6.1.102
env:
ARCH: ${{ matrix.arch }}
FC_KERNEL_VERSIONS: ${{ matrix.version }}
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Set up QEMU (arm64)
if: matrix.arch == 'arm64'
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx (arm64)
if: matrix.arch == 'arm64'
uses: docker/setup-buildx-action@v3
- name: Build kernel
run: make build-fc
build-cloudhypervisor:
if: github.event_name != 'push'
if: github.event_name == 'pull_request'
runs-on: ubuntu-latest
permissions:
contents: read
strategy:
fail-fast: false
matrix:
version: [ 5.12 ]
version: [5.12, 5.15.12]
env:
ARCH: amd64
CH_KERNEL_VERSIONS: ${{ matrix.version }}
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Build kernel
run: make build-ch
release-firecracker:
if: github.event_name != 'pull_request'
if: github.event_name == 'push' || github.event_name == 'workflow_dispatch'
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
strategy:
fail-fast: false
matrix:
version: [ 4.19.215, 5.10.77 ]
include:
- arch: amd64
version: 4.19.215
- arch: amd64
version: 5.10.77
- arch: amd64
version: 6.1.102
- arch: arm64
version: 5.10.77
- arch: arm64
version: 6.1.102
env:
REGISTRY: ghcr.io/${{ vars.REGISTRY_OWNER || github.repository_owner }}
ARCH: ${{ matrix.arch }}
FC_KERNEL_VERSIONS: ${{ matrix.version }}
PUSH: --push
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Set up QEMU (arm64)
if: matrix.arch == 'arm64'
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx (arm64)
if: matrix.arch == 'arm64'
uses: docker/setup-buildx-action@v3
- name: Login to container registry
uses: docker/login-action@v1.10.0
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
Expand All @@ -70,21 +109,23 @@ jobs:
make build-fc
make push-fc
Copy link

Copilot AI Mar 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this job, PUSH=--push causes arm64 builds to use docker buildx build --push (see kernel/Makefile), which does not load images into the local Docker daemon. The subsequent make push-fc (docker push) will then fail for arm64. Consider either skipping make push-fc when matrix.arch == 'arm64', or switching to a buildx mode that produces local images (e.g. --load) before pushing, or updating the Makefile push targets to use buildx instead of docker push for arm64.

Suggested change
make push-fc
if [ "${{ matrix.arch }}" != "arm64" ]; then
make push-fc
fi

Copilot uses AI. Check for mistakes.
release-cloudhypervisor:
if: github.event_name != 'pull_request'
if: github.event_name == 'push' || github.event_name == 'workflow_dispatch'
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
strategy:
fail-fast: false
matrix:
version: [ 5.12 ]
version: [5.12, 5.15.12]
env:
REGISTRY: ghcr.io/${{ vars.REGISTRY_OWNER || github.repository_owner }}
ARCH: amd64
CH_KERNEL_VERSIONS: ${{ matrix.version }}
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Login to container registry
uses: docker/login-action@v1.10.0
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
Expand Down
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,17 @@ For OS/k8s image builder instructions, see the doc [here][os-docs].

Experimental images can be found [here][exp].

## Publishing and forks

Workflows push images to the **repository’s GitHub Container Registry** by default:

- **Upstream** (`liquidmetal-dev/image-builder`): images go to `ghcr.io/liquidmetal-dev/...`
- **Forks** (e.g. `my-fork/liquidmetal-image-builder`): images go to `ghcr.io/my-fork/...`

So you can run the same workflows on a fork and publish to your own GHCR without changing the workflow files.

To use a different registry owner (e.g. for the official Liquid Metal org), set the repository variable **`REGISTRY_OWNER`** in the repo’s GitHub settings (e.g. `liquidmetal-dev`). The workflows will then use `ghcr.io/<REGISTRY_OWNER>/...` instead of `ghcr.io/<repository_owner>/...`.

[capmvm]: https://github.com/liquidmetal-dev/cluster-api-provider-microvm
[flint]: https://github.com/liquidmetal-dev/flintlock
[k-docs]: https://github.com/liquidmetal-dev/image-builder/tree/main/kernel
Expand Down
2 changes: 1 addition & 1 deletion capmvm/kubernetes/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ CONTAINERD_VERSION?=1.7.27
K8S_MAJOR_MINOR?=1.30
K8S_FULL_VERSION?=$(K8S_MAJOR_MINOR).14
UBUNTU_VERSION?=22.04
IMAGE_NAME?=$(REGISTRY)/capmvm-k8s-ubuntu-$(UBUNTU_VERSION)
IMAGE_NAME?=$(REGISTRY)/capmvm-k8s-ubuntu-$(UBUNTU_VERSION)-amd64
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need the ability to overwrite the amd64? Perhaps via passed in ARCH

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually i see there is separate Makefile later for arm :)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@richardcase Should we merge the Makefiles?
It was a bit confusing for me with ARM initially. Maybe a single file that handles all architectures?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So arm was experimental; I did not want to merge them initially as I was concerned it could break others' workflows; however, I think a single Makefile might be nicer. Let me know your thoughts.
@richardcase Maybe as a separate PR where we merge them?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah i think a single makefile would be easier ultimately.

IMAGE?=$(IMAGE_NAME):$(K8S_FULL_VERSION)

build:
Expand Down
2 changes: 1 addition & 1 deletion capmvm/kubernetes/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ The builder can be found at `capmvm/kubernetes`.
The resulting images can be added to Microvm specs like so:

```text
docker pull ghcr.io/liquidmetal-dev/capmvm-k8s-ubuntu-22.04:1.28.4
docker pull ghcr.io/liquidmetal-dev/capmvm-k8s-ubuntu-22.04-amd64:1.28.4
```

## Publishing new images
Expand Down
22 changes: 11 additions & 11 deletions experimental/arm/capmvm/kubernetes/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ ARG OS_VERSION=20.04
FROM ubuntu:${OS_VERSION}

ARG ARCH="arm64"
ARG CONTAINERD_VERSION=1.6.0
# Kubernetes version will be used to keep the kubeadm, kubelet, and kubectl version consistent
ARG KUBERNETES_VERSION=1.21.8
ARG CONTAINERD_VERSION=1.7.27
ARG KUBERNETES_MAJOR_MINOR=1.30
ARG KUBERNETES_FULL_VERSION=1.30.14

RUN apt-get update && apt-get install -y \
kmod \
Expand Down Expand Up @@ -51,19 +51,18 @@ kernel.panic_on_oops = 1" >> /etc/sysctl.d/99-kubernetes-cri.conf
# Apply sysctl params without reboot
RUN sysctl --system

# Install Containerd
# Install Containerd (same artifact pattern as x86 capmvm)
RUN wget https://github.com/containerd/containerd/releases/download/v${CONTAINERD_VERSION}/cri-containerd-cni-${CONTAINERD_VERSION}-linux-${ARCH}.tar.gz
RUN tar --no-overwrite-dir -C / -xzf cri-containerd-cni-${CONTAINERD_VERSION}-linux-${ARCH}.tar.gz && rm -f cri-containerd-cni-${CONTAINERD_VERSION}-linux-${ARCH}.tar.gz

### Add apt repos
# Kubeadm, Kubelet, and Kubectl
RUN curl -fsSLo /usr/share/keyrings/kubernetes-archive-keyring.gpg https://packages.cloud.google.com/apt/doc/apt-key.gpg
RUN echo "deb [signed-by=/usr/share/keyrings/kubernetes-archive-keyring.gpg] https://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kubernetes.list
### Add apt repos (pkgs.k8s.io, same as x86 capmvm)
RUN curl -fsSL https://pkgs.k8s.io/core:/stable:/v${KUBERNETES_MAJOR_MINOR}/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
Copy link

Copilot AI Mar 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This writes the keyring to /etc/apt/keyrings/... but the Dockerfile never creates /etc/apt/keyrings. On Ubuntu 20.04 (the default OS_VERSION here), that directory is typically absent, so this step can fail with a “No such file or directory”. Add a mkdir -p /etc/apt/keyrings before the gpg --dearmor -o ... step.

Suggested change
RUN curl -fsSL https://pkgs.k8s.io/core:/stable:/v${KUBERNETES_MAJOR_MINOR}/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
RUN mkdir -p /etc/apt/keyrings && curl -fsSL https://pkgs.k8s.io/core:/stable:/v${KUBERNETES_MAJOR_MINOR}/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg

Copilot uses AI. Check for mistakes.
RUN echo "deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v${KUBERNETES_MAJOR_MINOR}/deb/ /" | sudo tee /etc/apt/sources.list.d/kubernetes.list

RUN apt-get update && apt-get install -y \
kubeadm=${KUBERNETES_VERSION}-00 \
kubelet=${KUBERNETES_VERSION}-00 \
kubectl=${KUBERNETES_VERSION}-00 && \
kubeadm=${KUBERNETES_FULL_VERSION}-1.1 \
kubelet=${KUBERNETES_FULL_VERSION}-1.1 \
kubectl=${KUBERNETES_FULL_VERSION}-1.1 && \
apt-get clean && \
rm -rf /var/lib/apt/lists/* && \
apt-mark hold kubelet kubeadm kubectl
Expand All @@ -72,6 +71,7 @@ RUN mkdir -p /etc/containerd && containerd config default > /etc/containerd/conf
RUN rm /etc/cni/net.d/10-containerd-net.conflist
RUN systemctl enable containerd

RUN mkdir -p /etc/systemd/system/kubelet.service.d
RUN echo '[Service] \n\
Environment="KUBELET_EXTRA_ARGS=--container-runtime=remote --runtime-request-timeout=15m --container-runtime-endpoint=unix:///run/containerd/containerd.sock"' \
>> /etc/systemd/system/kubelet.service.d/0-containerd.conf
Expand Down
Loading