Skip to content

Commit 330777e

Browse files
authored
Image build time improvements (#10104)
* [build]: Patch debootstrap to not unmount the host's /proc filesystem Currently, when the final image is being built (sonic-vs.img.gz, sonic-broadcom.bin, or similar), each invocation of sudo in the build_debian.sh script takes 0.8 seconds to run and execute the actual command. This is because the /proc filesystem in the slave container has been unmounted somehow. This is happening when debootstrap is running, and it incorrectly unmounts the host's (in our case, the slave container's) /proc filesystem because in the new image being built, /proc is a symlink to the host's (the slave container's) /proc. Because of that, /proc is gone, and each invocation of sudo adds 0.8 seconds overhead. As a side effect, docker exec into the slave container during this time will fail, because /proc/self/fd doesn't exist anymore, and docker exec assumes that that exists. Debootstrap has fixed this in 1.0.124 and newer, so backport the patch that fixes this into the version that Bullseye has. Signed-off-by: Saikrishna Arcot <sarcot@microsoft.com> * [build_debian.sh]: Use eatmydata to speed up deb package installations During package installations, dpkg calls fsync multiples times (for each package) to ensure that tht efiles are written to disk, so that if there's some system crash during package installation, then it is in at least a somewhat recoverable state. For our use case though, we're installing packages in a chroot in fsroot-* from a slave container and then packaging it into an image. If there were a system crash (or even if docker crashed), the fsroot-* directory would first be removed, and the process would get restarted. This means that the fsync calls aren't really needed for our use case. The eatmydata package includes a library that will block/suppress the use of fsync (and similar) system calls from applications and will instead just return success, so that the application is not blocked on disk writes, which can instead happen in the background instead as necessary. If dpkg is run with this library, then the fsync calls that it does will have no effect. Therefore, install the eatmydata package at the beginning of build_debian.sh and have dpkg be run under eatmydata for almost all package installations/removals. At the end of the installation, remove it, so that the final image uses dpkg as normal. In my testing, this saves about 2-3 minutes from the image build time. Signed-off-by: Saikrishna Arcot <sarcot@microsoft.com> * Change ln syntax to use chroot Signed-off-by: Saikrishna Arcot <sarcot@microsoft.com>
1 parent 598ab99 commit 330777e

7 files changed

Lines changed: 91 additions & 0 deletions

File tree

build_debian.sh

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,12 @@ sudo cp files/apt/apt.conf.d/{81norecommends,apt-{clean,gzip-indexes,no-language
113113
## Note: set lang to prevent locale warnings in your chroot
114114
sudo LANG=C chroot $FILESYSTEM_ROOT apt-get -y update
115115
sudo LANG=C chroot $FILESYSTEM_ROOT apt-get -y upgrade
116+
117+
echo '[INFO] Install and setup eatmydata'
118+
sudo LANG=C chroot $FILESYSTEM_ROOT apt-get -y install eatmydata
119+
sudo LANG=C chroot $FILESYSTEM_ROOT ln -s /usr/bin/eatmydata /usr/local/bin/dpkg
120+
echo 'Dir::Bin::dpkg "/usr/local/bin/dpkg";' | sudo tee $FILESYSTEM_ROOT/etc/apt/apt.conf.d/00image-install-eatmydata > /dev/null
121+
116122
echo '[INFO] Install packages for building image'
117123
sudo LANG=C chroot $FILESYSTEM_ROOT apt-get -y install makedev psmisc
118124

@@ -586,6 +592,10 @@ scripts/collect_host_image_version_files.sh $TARGET_PATH $FILESYSTEM_ROOT
586592
# Remove GCC
587593
sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get -y remove gcc
588594

595+
# Remove eatmydata
596+
sudo rm $FILESYSTEM_ROOT/etc/apt/apt.conf.d/00image-install-eatmydata $FILESYSTEM_ROOT/usr/local/bin/dpkg
597+
sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get -y remove eatmydata
598+
589599
## Clean up apt
590600
sudo LANG=C chroot $FILESYSTEM_ROOT apt-get -y autoremove
591601
sudo LANG=C chroot $FILESYSTEM_ROOT apt-get autoclean

rules/debootstrap.dep

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
2+
SPATH := $($(DEBOOTSTRAP)_SRC_PATH)
3+
DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/debootstrap.mk rules/debootstrap.dep
4+
DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST)
5+
DEP_FILES += $(shell git ls-files $(SPATH))
6+
7+
$(DEBOOTSTRAP)_CACHE_MODE := GIT_CONTENT_SHA
8+
$(DEBOOTSTRAP)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST)
9+
$(DEBOOTSTRAP)_DEP_FILES := $(DEP_FILES)
10+

rules/debootstrap.mk

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# debootstrap package
2+
3+
DEBOOTSTRAP_VERSION = 1.0.123
4+
5+
export DEBOOTSTRAP_VERSION
6+
7+
DEBOOTSTRAP = debootstrap_$(DEBOOTSTRAP_VERSION)_all.deb
8+
$(DEBOOTSTRAP)_SRC_PATH = $(SRC_PATH)/debootstrap
9+
SONIC_MAKE_DEBS += $(DEBOOTSTRAP)

slave.mk

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -992,6 +992,7 @@ $(addprefix $(TARGET_PATH)/, $(SONIC_INSTALLERS)) : $(TARGET_PATH)/% : \
992992
$$(addprefix $(TARGET_PATH)/,$$($$*_DOCKERS)) \
993993
$$(addprefix $(TARGET_PATH)/,$$(SONIC_PACKAGES_LOCAL)) \
994994
$$(addprefix $(FILES_PATH)/,$$($$*_FILES)) \
995+
$(addsuffix -install,$(addprefix $(IMAGE_DISTRO_DEBS_PATH)/,$(DEBOOTSTRAP))) \
995996
$(if $(findstring y,$(ENABLE_ZTP)),$(addprefix $(IMAGE_DISTRO_DEBS_PATH)/,$(SONIC_ZTP))) \
996997
$(addprefix $(PYTHON_WHEELS_PATH)/,$(SONIC_UTILITIES_PY3)) \
997998
$(addprefix $(PYTHON_WHEELS_PATH)/,$(SONIC_PY_COMMON_PY2)) \

src/debootstrap/.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
debootstrap*.udeb
2+
debootstrap*.dsc
3+
debootstrap-*/

src/debootstrap/Makefile

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
.ONESHELL:
2+
SHELL = /bin/bash
3+
.SHELLFLAGS += -e
4+
5+
MAIN_TARGET = debootstrap_$(DEBOOTSTRAP_VERSION)_all.deb
6+
7+
$(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% :
8+
# Remove any stale files
9+
rm -rf ./debootstrap-$(DEBOOTSTRAP_VERSION) ./debootstrap*.{deb,udeb,dsc}
10+
11+
# Get source package
12+
dget https://deb.debian.org/debian/pool/main/d/debootstrap/debootstrap_$(DEBOOTSTRAP_VERSION).dsc
13+
14+
# Build source and Debian packages
15+
pushd debootstrap-$(DEBOOTSTRAP_VERSION)
16+
patch -p1 -i ../proc-mount.patch
17+
dpkg-buildpackage -rfakeroot -b -us -uc -j$(SONIC_CONFIG_MAKE_JOBS) --admindir $(SONIC_DPKG_ADMINDIR)
18+
popd
19+
20+
# Move the newly-built .deb packages to the destination directory
21+
mv $(DERIVED_TARGETS) $* $(DEST)/
22+
23+
$(addprefix $(DEST)/, $(DERIVED_TARGETS)): $(DEST)/% : $(DEST)/$(MAIN_TARGET)
24+

src/debootstrap/proc-mount.patch

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
From 87cdebbcad6f4e16ba711227cbbbd70039f88752 Mon Sep 17 00:00:00 2001
2+
From: YunQiang Su <syq@debian.org>
3+
Date: Mon, 7 Sep 2020 09:29:37 +0800
4+
Subject: [PATCH] stage1: re-mkdir /proc instead of umount if it is a symlink
5+
6+
In docker, the TARGET/proc will be a symlink to /proc.
7+
And if the docker instance is called with --privileged, it will umount
8+
the /proc of the whole instance in setup_proc.
9+
---
10+
debian/changelog | 3 +++
11+
functions | 7 ++++++-
12+
2 files changed, 9 insertions(+), 1 deletion(-)
13+
14+
diff --git a/functions b/functions
15+
index 1ac63f7..065320d 100644
16+
--- a/functions
17+
+++ b/functions
18+
@@ -1183,7 +1183,12 @@ setup_proc () {
19+
umount_on_exit /dev/shm
20+
umount_on_exit /proc
21+
umount_on_exit /proc/bus/usb
22+
- umount "$TARGET/proc" 2>/dev/null || true
23+
+ if [ -L "$TARGET/proc" ];then
24+
+ rm -f $TARGET/proc
25+
+ mkdir $TARGET/proc
26+
+ else
27+
+ umount "$TARGET/proc" 2>/dev/null || true
28+
+ fi
29+
30+
# some container environment are used at second-stage, it already treats /proc and so on
31+
if [ -z "$(ls -A "$TARGET/proc")" ]; then
32+
--
33+
GitLab
34+

0 commit comments

Comments
 (0)