Skip to content

Commit 67a4df9

Browse files
pothoschewi
andcommitted
Use a minimal initrd to switch to the full initrd stored in /usr
The growth of binaries over time and the inclusion of new features filled the available boot partition space, so that the kernel+initrd almost couldn't fit twice anymore as required for updates. We employed workarounds such as wrapper scripts for ignition, afterburn and other binaries so that they are loaded from /usr. However, this was still not enough and we would have to do the same for (network) kernel modules and firmware. To avoid making this ever more complex we can use a dedicated initrd focused on loading the full initrd from /usr and then this full initrd can use dracut as before and even drop all the workarounds we accumulated. Generate a minimal initrd to use instead of the full bootengine initrd. The bootengine initrd gets stored as squashfs on /usr. The minimal initrd still includes the early_cpio for amd64 microcode updates. We have a fixed list of modules or module directories to include, only focused on loading /usr and any emergency console interaction. This requires also checking for module dependencies to copy over. The busybox, veritysetup, and kmod binaries are needed and get their required libraries resolved and copied over. They are not static and use shared libraries which should be ok for now. The resulting vmlinuz file is 27 MB for amd64, down from ~60 MB, so we have enough room to include more kernel modules and so on for the next years while we also grow the boot partition and wait for users to redeploy until we can rely on a larger boot partition and eventually drop the minimal initrd again. Pulls in flatcar/bootengine#110 for the minimal initrd script and flatcar/seismograph#12 for making the device mapper discovery for the "rootdev" command more reliable. This also requied a backport of a kernel patch from 2017 that exposes the PARTUUID in the /sys uevent file. Co-authored-by: James Le Cuirot <[email protected]> Signed-off-by: Kai Lueke <[email protected]>
1 parent 88cb9c9 commit 67a4df9

File tree

9 files changed

+158
-3
lines changed

9 files changed

+158
-3
lines changed

build_library/build_image_util.sh

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -582,6 +582,8 @@ finish_image() {
582582
local image_initrd_contents="${11}"
583583
local image_initrd_contents_wtd="${12}"
584584
local image_disk_space_usage="${13}"
585+
local image_realinitrd_contents="${14}"
586+
local image_realinitrd_contents_wtd="${15}"
585587

586588
local install_grub=0
587589
local disk_img="${BUILD_DIR}/${image_name}"
@@ -877,6 +879,20 @@ EOF
877879
rm -rf "${BUILD_DIR}/tmp_initrd_contents"
878880
fi
879881

882+
if [[ -n "${image_realinitrd_contents}" ]] || [[ -n "${image_realinitrd_contents_wtd}" ]]; then
883+
mkdir -p "${BUILD_DIR}/tmp_initrd_contents"
884+
sudo mount "${root_fs_dir}/usr/lib/flatcar/bootengine.img" "${BUILD_DIR}/tmp_initrd_contents"
885+
if [[ -n "${image_realinitrd_contents}" ]]; then
886+
write_contents "${BUILD_DIR}/tmp_initrd_contents" "${BUILD_DIR}/${image_realinitrd_contents}"
887+
fi
888+
889+
if [[ -n "${image_realinitrd_contents_wtd}" ]]; then
890+
write_contents_with_technical_details "${BUILD_DIR}/tmp_initrd_contents" "${BUILD_DIR}/${image_realinitrd_contents_wtd}"
891+
fi
892+
sudo umount "${BUILD_DIR}/tmp_initrd_contents"
893+
rm -rf "${BUILD_DIR}/tmp_initrd_contents"
894+
fi
895+
880896
if [[ -n "${image_disk_space_usage}" ]]; then
881897
write_disk_space_usage "${root_fs_dir}" "${BUILD_DIR}/${image_disk_space_usage}"
882898
fi

build_library/prod_image_util.sh

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,8 @@ create_prod_image() {
8383
local image_initrd_contents="${image_name%.bin}_initrd_contents.txt"
8484
local image_initrd_contents_wtd="${image_name%.bin}_initrd_contents_wtd.txt"
8585
local image_disk_usage="${image_name%.bin}_disk_usage.txt"
86+
local image_realinitrd_contents="${image_name%.bin}_realinitrd_contents.txt"
87+
local image_realinitrd_contents_wtd="${image_name%.bin}_realinitrd_contents_wtd.txt"
8688
local image_sysext_base="${image_name%.bin}_sysext.squashfs"
8789

8890
start_image "${image_name}" "${disk_layout}" "${root_fs_dir}" "${update_group}"
@@ -180,7 +182,9 @@ EOF
180182
"${image_kconfig}" \
181183
"${image_initrd_contents}" \
182184
"${image_initrd_contents_wtd}" \
183-
"${image_disk_usage}"
185+
"${image_disk_usage}" \
186+
"${image_realinitrd_contents}" \
187+
"${image_realinitrd_contents_wtd}"
184188

185189
# Official builds will sign and upload these files later, so remove them to
186190
# prevent them from being uploaded now.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
- Reduced the kernel+initrd size on `/boot` to the half. Flatcar now uses a minimal first initrd only to access the `/usr` partition and switch to the full initrd that does the full system preparation as before. Since this means that the set of kernel modules available in the first initrd is reduced, please report any impacts.

ci-automation/image_changes.sh

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -729,6 +729,15 @@ function print_image_reports() {
729729
echo "Note that vmlinuz-a also contains the kernel code, which might have changed too, so the reported difference does not accurately describe the change in initrd."
730730
echo
731731

732+
yell "Real/full init ramdisk (bootengine.img) differences compared to ${previous_version_description}"
733+
underline "Real/full init ramdisk (bootengine.img) file changes, compared to ${previous_version_description}:"
734+
env \
735+
"${package_diff_env[@]}" FILE=flatcar_production_image_realinitrd_contents.txt FILESONLY=1 CUTKERNEL=1 \
736+
"${flatcar_build_scripts_repo}/package-diff" "${package_diff_params[@]}" 2>&1 || true
737+
738+
underline "Real/full init ramdisk (bootengine.img) file size changes, compared to ${previous_version_description}:"
739+
"${size_changes_invocation[@]}" "${size_change_report_params[@]/%/:realinitrd-wtd}" 2>&1 || true
740+
732741
local base_sysext
733742
for base_sysext in "${base_sysexts[@]}"; do
734743
yell "Base sysext ${base_sysext} changes compared to ${previous_version_description}"

sdk_container/src/third_party/coreos-overlay/sys-apps/seismograph/seismograph-9999.ebuild

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ EGIT_REPO_URI="https://github.com/flatcar/seismograph.git"
77
if [[ "${PV}" == 9999 ]]; then
88
KEYWORDS="~amd64 ~arm ~arm64 ~x86"
99
else
10-
EGIT_COMMIT="e32ac4d13ca44333dc77e5872dbf23f964b6f1e2" # main
10+
#EGIT_COMMIT="e32ac4d13ca44333dc77e5872dbf23f964b6f1e2" # main
11+
EGIT_BRANCH="kai/fix-lookup"
1112
KEYWORDS="amd64 arm arm64 x86"
1213
fi
1314

sdk_container/src/third_party/coreos-overlay/sys-kernel/bootengine/bootengine-9999.ebuild

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ EGIT_REPO_URI="https://github.com/flatcar/bootengine.git"
77
if [[ "${PV}" == 9999 ]]; then
88
KEYWORDS="~amd64 ~arm ~arm64 ~x86"
99
else
10-
EGIT_COMMIT="31ba2964ce5e77ae5553eb0a3624afcc7078bb09" # flatcar-master
10+
#EGIT_COMMIT="31ba2964ce5e77ae5553eb0a3624afcc7078bb09" # flatcar-master
11+
EGIT_BRANCH="kai/initrd-in-usr"
1112
KEYWORDS="amd64 arm arm64 x86"
1213
fi
1314

@@ -23,6 +24,7 @@ src_install() {
2324
insinto /usr/lib/dracut/modules.d/
2425
doins -r dracut/.
2526
dosbin update-bootengine
27+
dosbin minimal-init
2628

2729
# must be executable since dracut's install scripts just
2830
# re-use existing filesystem permissions during initrd creation.

sdk_container/src/third_party/coreos-overlay/sys-kernel/coreos-kernel/coreos-kernel-6.12.47.ebuild

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ DEPEND="
2626
coreos-base/coreos-init:=
2727
sys-apps/azure-vm-utils[dracut]
2828
sys-apps/baselayout
29+
sys-apps/busybox
2930
sys-apps/coreutils
3031
sys-apps/findutils
3132
sys-apps/grep
@@ -72,6 +73,16 @@ src_prepare() {
7273
use amd64 && config_update "CONFIG_EXTRA_FIRMWARE_DIR=\"${fw_dir}\""
7374
}
7475

76+
copy_in() {
77+
# Simple setup, assume we only have /lib64 to care about
78+
cp "${ESYSROOT}"/usr/"$1" ./"$1"
79+
for LIBFILE in $(patchelf --print-needed ./"$1"); do
80+
if [ ! -e ./lib64/"${LIBFILE}" ]; then
81+
copy_in /lib64/"${LIBFILE}"
82+
fi
83+
done
84+
}
85+
7586
src_compile() {
7687
local BE_ARGS=()
7788

@@ -89,6 +100,77 @@ src_compile() {
89100

90101
tc-export PKG_CONFIG
91102
"${ESYSROOT}"/usr/bin/update-bootengine -k "${KV_FULL}" -o "${S}"/build/bootengine.cpio "${BE_ARGS[@]}" || die
103+
# Copy full initrd over to /usr as filesystem image
104+
mkdir "${S}"/build/bootengine || die
105+
pushd "${S}"/build/bootengine || die
106+
sudo lsinitrd --unpack "${S}"/build/bootengine.cpio || die
107+
sudo mksquashfs . "${S}"/build/bootengine.img -noappend -xattrs-exclude ^btrfs. || die
108+
popd || die
109+
# Create minimal initrd
110+
if use amd64; then
111+
microcode=$(cpio -t < "${S}"/build/bootengine.cpio 2>&1 > /dev/null | cut -d " " -f 1)
112+
# Only keep early cpio for microcode
113+
truncate -s $((microcode*512)) "${S}"/build/bootengine.cpio || die
114+
# Debug: List contents after truncation
115+
cpio -t < "${S}"/build/bootengine.cpio
116+
else
117+
# No early cpio, drop full initrd
118+
> "${S}"/build/bootengine.cpio
119+
fi
120+
mkdir "${S}"/build/minimal || die
121+
pushd "${S}"/build/minimal || die
122+
mkdir -p {etc,bin,sbin,dev,proc,sys,dev,lib,lib64,usr/bin,usr/sbin,usr/lib,usr/lib64,realinit,sysusr/usr}
123+
mkdir -p lib/modules/"${KV_FULL}"/
124+
# Instead from ESYSROOT we can also copy kernel modules from the dracut pre-selection
125+
cp "${S}"/build/bootengine/usr/lib/modules/"${KV_FULL}"/modules.* lib/modules/"${KV_FULL}"/
126+
mkdir -p lib/modprobe.d/
127+
cp "${S}"/build/bootengine/lib/modprobe.d/* lib/modprobe.d/
128+
# Only include modules related to mounting /usr and for interacting with the emergency console
129+
MODULES=("fs/overlayfs" "fs/squashfs" "drivers/md/dm-verity.ko.xz" "drivers/md/dm-mod.ko.xz" "drivers/block/loop.ko.xz" "fs/btrfs" "drivers/nvme" "drivers/scsi" "drivers/ata" "drivers/block" "drivers/pci" "drivers/char/virtio_console.ko.xz" "drivers/hv" "drivers/input/serio" "drivers/mmc" "drivers/usb" "drivers/hid" "security/keys")
130+
for MODULE in "${MODULES[@]}"; do
131+
if [ -f "${S}"/build/bootengine/usr/lib/modules/"${KV_FULL}"/kernel/"${MODULE}" ]; then
132+
MODULE_DIR=$(dirname "${MODULE}")
133+
mkdir -p lib/modules/"${KV_FULL}"/kernel/"${MODULE_DIR}"
134+
cp "${S}"/build/bootengine/usr/lib/modules/"${KV_FULL}"/kernel/"${MODULE}" lib/modules/"${KV_FULL}"/kernel/"${MODULE}"
135+
elif [ -d "${S}"/build/bootengine/usr/lib/modules/"${KV_FULL}"/kernel/"${MODULE}" ]; then
136+
mkdir -p lib/modules/"${KV_FULL}"/kernel/"${MODULE}"
137+
cp -r "${S}"/build/bootengine/usr/lib/modules/"${KV_FULL}"/kernel/"${MODULE}"/* lib/modules/"${KV_FULL}"/kernel/"${MODULE}"/
138+
else
139+
die "wrong module type/not found: ${S}"/build/bootengine/usr/lib/modules/"${KV_FULL}"/kernel/"${MODULE}"
140+
fi
141+
done
142+
# Copy module dependencies
143+
for MODULE in $(find ./lib/modules/"${KV_FULL}"/ -type f); do
144+
MODULE=$(basename "${MODULE}" | sed "s/\.ko\.xz$//")
145+
for DEP in $(modprobe -S "${KV_FULL}" -d "${S}"/build/bootengine -D "${MODULE}" | grep "^insmod " | sed "s/^insmod //"); do
146+
DEP=$(echo "${DEP}" | sed "s,${S}/build/bootengine,/,")
147+
DEP_DIR=$(dirname "${DEP}")
148+
mkdir -p ./"${DEP_DIR}"
149+
cp "${S}"/build/bootengine/"${DEP}" ./"${DEP}"
150+
done
151+
done
152+
echo '$MODALIAS=.* 0:0 660 @/sbin/modprobe "$MODALIAS"' > ./etc/mdev.conf
153+
copy_in /bin/veritysetup
154+
copy_in /bin/dmsetup
155+
copy_in /bin/busybox
156+
# We can't use busybox's modprobe because it doesn't support the globs in module.alias, breaking module loading
157+
copy_in /sbin/kmod
158+
ln -s /sbin/kmod ./sbin/modprobe
159+
if use arm64; then
160+
ln -s ../lib64/ld-linux-aarch64.so.1 ./lib/ld-linux-aarch64.so.1
161+
fi
162+
cp -a "${ESYSROOT}"/usr/bin/minimal-init ./init
163+
# Make it easier to debug by not relying too much on the first commands
164+
ln -s /bin/busybox ./bin/sh
165+
mknod ./dev/console c 5 1
166+
mknod ./dev/null c 1 3
167+
mknod ./dev/tty c 5 0
168+
mknod ./dev/urandom c 1 9
169+
mknod ./dev/random c 1 8
170+
mknod ./dev/zero c 1 5
171+
# No compression because CONFIG_INITRAMFS_COMPRESSION_XZ should take care of it
172+
find . -print0 | cpio --null --create --verbose --format=newc >> "${S}"/build/bootengine.cpio
173+
popd || die
92174
kmake "$(kernel_target)"
93175

94176
# sanity check :)
@@ -111,4 +193,7 @@ src_install() {
111193
# For easy access to vdso debug symbols in gdb:
112194
# set debug-file-directory /usr/lib/debug/usr/lib/modules/${KV_FULL}/vdso/
113195
kmake INSTALL_MOD_PATH="${ED}/usr/lib/debug/usr" vdso_install
196+
197+
insinto "/usr/lib/flatcar"
198+
doins build/bootengine.img
114199
}

sdk_container/src/third_party/coreos-overlay/sys-kernel/coreos-sources/coreos-sources-6.12.47.ebuild

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,5 @@ UNIPATCH_LIST="
4343
${PATCH_DIR}/z0006-mtd-disable-slram-and-phram-when-locked-down.patch \
4444
${PATCH_DIR}/z0007-arm64-add-kernel-config-option-to-lock-down-when.patch \
4545
${PATCH_DIR}/z0008-tools-hv-fix-cross-compilation-for-ARM64.patch \
46+
${PATCH_DIR}/z0009-block-add-partition-uuid-into-uevent.patch \
4647
"
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
From 758737d86f8a2d74c0fa9f8b2523fa7fd1e0d0aa Mon Sep 17 00:00:00 2001
2+
From: Konstantin Khlebnikov <[email protected]>
3+
Date: Fri, 4 Oct 2024 17:13:43 -0700
4+
Subject: [PATCH] block: add partition uuid into uevent as "PARTUUID"
5+
6+
Both most common formats have uuid in addition to partition name:
7+
GPT: standard uuid xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
8+
DOS: 4 byte disk signature and 1 byte partition xxxxxxxx-xx
9+
10+
Tools from util-linux use the same notation for them.
11+
12+
Signed-off-by: Konstantin Khlebnikov <[email protected]>
13+
Reviewed-by: Kyle Fortin <[email protected]>
14+
[dianders: rebased to modern kernels]
15+
Signed-off-by: Douglas Anderson <[email protected]>
16+
Signed-off-by: Douglas Anderson <[email protected]>
17+
Reviewed-by: Christoph Hellwig <[email protected]>
18+
Link: https://lore.kernel.org/r/20241004171340.v2.1.I938c91d10e454e841fdf5d64499a8ae8514dc004@changeid
19+
Signed-off-by: Jens Axboe <[email protected]>
20+
---
21+
block/partitions/core.c | 2 ++
22+
1 file changed, 2 insertions(+)
23+
24+
diff --git a/block/partitions/core.c b/block/partitions/core.c
25+
index cdad05f9764768..815ed33caa1b86 100644
26+
--- a/block/partitions/core.c
27+
+++ b/block/partitions/core.c
28+
@@ -256,6 +256,8 @@ static int part_uevent(const struct device *dev, struct kobj_uevent_env *env)
29+
add_uevent_var(env, "PARTN=%u", bdev_partno(part));
30+
if (part->bd_meta_info && part->bd_meta_info->volname[0])
31+
add_uevent_var(env, "PARTNAME=%s", part->bd_meta_info->volname);
32+
+ if (part->bd_meta_info && part->bd_meta_info->uuid[0])
33+
+ add_uevent_var(env, "PARTUUID=%s", part->bd_meta_info->uuid);
34+
return 0;
35+
}
36+

0 commit comments

Comments
 (0)