Skip to content

Upgrade firecracker from v1.1.0 to v.1.4.1 #768

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Next Next commit
Add self-contained kernel builder
Before the change, we relied on Firecracker's devtool to build a custom
kernel with our configs (which add FUSE support). The devtool's
build_kernel function is broken in Firecracker 1.4.1 and is completely
replaced by a non-containerized build script in main.

Rather than trying to get Firecracker's internal dev tooling to work for
our purposes, this change takes just the necessary scripts from
Firecracker to build a kernel in a container.

Signed-off-by: Kern Walster <[email protected]>
  • Loading branch information
Kern-- committed Sep 22, 2023
commit 7ea887b09d6fe2f737812a691072203816561fd3
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ tmp/
runtime/logs
*stamp
default-vmlinux.bin
vmlinux*
33 changes: 24 additions & 9 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,11 @@ ifeq ($(filter $(KERNEL_VERSION),$(KERNEL_VERSIONS)),)
$(error "Kernel version $(KERNEL_VERSION) is not supported. Supported versions are $(KERNEL_VERSIONS)")
endif

KERNEL_CONFIG_BASE=microvm-kernel-$(host_arch)-$(KERNEL_VERSION).config
KERNEL_CONFIG=tools/kernel-configs/$(KERNEL_CONFIG_BASE)
# Copied from https://github.com/firecracker-microvm/firecracker/blob/v1.1.0/tools/devtool#L2082
# This allows us to specify a kernel without the patch version, but still get the correct build path to reference the kernel binary
KERNEL_FULL_VERSION=$(shell cat "$(KERNEL_CONFIG)" | grep -Po "^\# Linux\/$(kernel_config_pattern) (([0-9]+.)[0-9]+)" | cut -d ' ' -f 3)
KERNEL_BIN=$(FIRECRACKER_DIR)/build/kernel/linux-$(KERNEL_FULL_VERSION)/vmlinux-$(KERNEL_FULL_VERSION)-$(host_arch).bin
KERNEL_BUILDER_DIR=tools/kernel-builder
KERNEL_CONFIG_BASE=kernel-configs/microvm-kernel-$(host_arch)-$(KERNEL_VERSION).config
KERNEL_CONFIG=$(KERNEL_BUILDER_DIR)/$(KERNEL_CONFIG_BASE)
KERNEL_BIN=$(KERNEL_BUILDER_DIR)/vmlinux-$(KERNEL_VERSION)-$(host_arch).bin
KERNEL_BUILDER_NAME?=kernel-builder

RUNC_DIR=$(SUBMODULES)/runc
RUNC_BIN=$(RUNC_DIR)/runc
Expand Down Expand Up @@ -355,12 +354,28 @@ firecracker-clean:
- rm $(FIRECRACKER_BIN)
- rm $(KERNEL_BIN)

##########################
# Kernel submodule
##########################
.PHONY: kernel
kernel: $(KERNEL_BIN)

$(KERNEL_BIN): $(KERNEL_CONFIG)
cp $(KERNEL_CONFIG) $(FIRECRACKER_DIR)
$(FIRECRACKER_DIR)/tools/devtool -y build_kernel --config $(KERNEL_CONFIG_BASE)
$(KERNEL_BUILDER_DIR)/builder_stamp: $(KERNEL_BUILDER_DIR)/Dockerfile.kernel-builder
docker build \
-t localhost/$(KERNEL_BUILDER_NAME):$(DOCKER_IMAGE_TAG) \
-f $(KERNEL_BUILDER_DIR)/Dockerfile.kernel-builder \
tools/
touch $@

$(KERNEL_BIN): $(KERNEL_CONFIG) $(KERNEL_BUILDER_DIR)/builder_stamp
exit 0
docker run --rm --user $(UID) \
--volume $(CURDIR)/$(KERNEL_BUILDER_DIR):/kernel-builder \
-e HOME=/tmp \
--workdir /kernel-builder \
--entrypoint ./build.sh \
localhost/$(KERNEL_BUILDER_NAME):$(DOCKER_IMAGE_TAG) \
/kernel-builder/$(KERNEL_CONFIG_BASE) # this is the arg to entrypoint

.PHONY: install-kernel
install-kernel: $(KERNEL_BIN)
Expand Down
13 changes: 13 additions & 0 deletions tools/kernel-builder/Dockerfile.kernel-builder
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
FROM debian:bullseye-slim

RUN apt update && apt install -y \
bc \
flex \
bison \
gcc \
make \
libelf-dev \
libssl-dev \
curl \
xz-utils

67 changes: 67 additions & 0 deletions tools/kernel-builder/build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
#!/bin/bash

set -euo pipefail

OUTPUT_DIR=$PWD

function get_linux_tarball {
local KERNEL_VERSION=$1
echo "Downloading the latest patch version for v$KERNEL_VERSION..."
local major_version="${KERNEL_VERSION%%.*}"
local url_base="https://cdn.kernel.org/pub/linux/kernel"
local LATEST_VERSION=$(
curl -fsSL $url_base/v$major_version.x/ \
| grep -o "linux-$KERNEL_VERSION\.[0-9]*\.tar.xz" \
| sort -rV \
| head -n 1 || true)
# Fetch tarball and sha256 checksum.
curl -fsSLO "$url_base/v$major_version.x/sha256sums.asc"
curl -fsSLO "$url_base/v$major_version.x/$LATEST_VERSION"
# Verify checksum.
grep "${LATEST_VERSION}" sha256sums.asc | sha256sum -c -
echo "Extracting the kernel source..."
tar -xaf $LATEST_VERSION
local DIR=$(basename $LATEST_VERSION .tar.xz)
ln -svfT $DIR linux
}

function cleanup {
rm sha256sums.asc
rm -r linux*
}

function build_linux {
local KERNEL_CFG=$1
# Extract the kernel version from the config file provided as parameter.
local KERNEL_VERSION=$(grep -Po "^# Linux\/\w+ \K(\d+\.\d+)" "$KERNEL_CFG")

get_linux_tarball $KERNEL_VERSION
pushd linux

arch=$(uname -m)
if [ "$arch" = "x86_64" ]; then
format="elf"
target="vmlinux"
binary_path="$target"
elif [ "$arch" = "aarch64" ]; then
format="pe"
target="Image"
binary_path="arch/arm64/boot/$target"
else
echo "FATAL: Unsupported architecture!"
exit 1
fi
cp "$KERNEL_CFG" .config

make olddefconfig
make -j $(nproc) $target
LATEST_VERSION=$(cat include/config/kernel.release)
OUTPUT_FILE=$OUTPUT_DIR/vmlinux-$KERNEL_VERSION-$arch.bin
cp -v $binary_path $OUTPUT_FILE
cp -v .config $OUTPUT_FILE.config
popd &>/dev/null
cleanup
}

build_linux $1