Skip to content

Commit

Permalink
feat: add sysext build scripts
Browse files Browse the repository at this point in the history
  • Loading branch information
ctrox committed Jul 4, 2024
1 parent 20d1a19 commit 88ffaa3
Show file tree
Hide file tree
Showing 5 changed files with 222 additions and 2 deletions.
43 changes: 43 additions & 0 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
name: Build and release Systemd sysext images
on:
push:
tags:
- '*'

env:
RUNC_VERSION: v1.2.0-rc.2
CONTAINERD_VERSION: 2.0.0-rc.3

jobs:
build:
runs-on: ubuntu-22.04
permissions:
# allow the action to create a release
contents: write
steps:
# checkout the sources
- uses: actions/checkout@v4

# prepare build host
- name: install prerequisites
run: |
set -euxo pipefail
sudo apt update -qq && sudo apt install -yqq \
curl \
jq \
squashfs-tools \
xz-utils \
gawk
- name: build release artifacts
run: |
TAG=${{ github.ref_name }} ./create_containerd_sysext.sh $CONTAINERD_VERSION containerd-nine
- name: create a new latest release with all artifacts
uses: softprops/action-gh-release@v1
with:
files: |
SHA256SUMS
*.raw
*.conf
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
*.raw
*.conf
SHA256SUMS
13 changes: 11 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,11 @@
# -containerd-sysext
A systemd-sysext image that installs the latest containerd version
# containerd-sysext

A systemd-sysext image that installs the latest containerd version. Used to be
able to deploy containerd 2.0 on Flatcar before it is bundled with the OS.

The scripts in this repo have been adapted from [the Flatcar sysext-bakery](https://github.com/flatcar/sysext-bakery).

## Releasing

Simply merge to main and push a new tag. A github release with the
sysext-image as an artifact is automatically created.
75 changes: 75 additions & 0 deletions bake.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
#!/usr/bin/env bash
set -euo pipefail

OS="${OS-_any}"
FORMAT="${FORMAT:-squashfs}"
ARCH="${ARCH-}"
RELOAD="${RELOAD-}"
SOURCE_DATE_EPOCH="${SOURCE_DATE_EPOCH-0}"
export SOURCE_DATE_EPOCH

# This script is to be called as helper by other scripts but can also be used standalone
if [ $# -lt 1 ]; then
echo "Usage: $0 SYSEXTNAME"
echo "The script will make a SYSEXTNAME.raw image of the folder SYSEXTNAME, and create an os-release file in it, run with --help for the list of supported environment variables."
exit 1
elif [ "$1" = "-h" ] || [ "$1" = "--help" ]; then
echo "If ARCH is specified as environment variable the sysext image will be required to run on the given architecture."
echo "To build for a specific OS, pass 'OS=myosid' as environment variable (current value is '${OS}'), e.g., 'fedora' as found in 'ID' under '/etc/os-release', or pass 'OS=_any' for any OS."
echo "The '/etc/os-release' file of your OS has to include 'SYSEXT_LEVEL=1.0' as done in Flatcar (not needed for 'OS=_any')."
echo "To specify that systemd should do a daemon reload for the system when the extension is loaded/unloaded, set RELOAD=1 (current value is '${RELOAD}')."
echo "If the mksquashfs tool is missing you can pass FORMAT=btrfs, FORMAT=ext4, or FORMAT=ext2 as environment variable (current value is '${FORMAT}') but the script won't change the ownership of the files in the SYSEXTNAME directory, so make sure that they are owned by root before creating the sysext image to avoid any problems."
echo "To make builds reproducible the SOURCE_DATE_EPOCH environment variable will be set to 0 if not defined."
echo
exit 1
fi

SYSEXTNAME="$1"

if [ "${FORMAT}" != "squashfs" ] && [ "${FORMAT}" != "btrfs" ] && [ "${FORMAT}" != "ext4" ] && [ "${FORMAT}" != "ext2" ]; then
echo "Expected FORMAT=squashfs, FORMAT=btrfs, FORMAT=ext4, or FORMAT=ext2, got '${FORMAT}'" >&2
exit 1
fi

# Map to valid values for https://www.freedesktop.org/software/systemd/man/os-release.html#ARCHITECTURE=
if [ "${ARCH}" = "amd64" ] || [ "${ARCH}" = "x86_64" ]; then
ARCH="x86-64"
elif [ "${ARCH}" = "aarch64" ]; then
ARCH="arm64"
fi

mkdir -p "${SYSEXTNAME}/usr/lib/extension-release.d"
{
echo "ID=${OS}"
if [ "${OS}" != "_any" ]; then
echo "SYSEXT_LEVEL=1.0"
fi
if [ "${ARCH}" != "" ]; then
echo "ARCHITECTURE=${ARCH}"
fi
if [ "${RELOAD}" = 1 ]; then
echo "EXTENSION_RELOAD_MANAGER=1"
fi
} > "${SYSEXTNAME}/usr/lib/extension-release.d/extension-release.${SYSEXTNAME}"
rm -f "${SYSEXTNAME}".raw
if [ "${FORMAT}" = "btrfs" ]; then
# Note: We didn't chown to root:root, meaning that the file ownership is left as is
mkfs.btrfs --mixed -m single -d single --shrink --rootdir "${SYSEXTNAME}" "${SYSEXTNAME}".raw
# This is for testing purposes and makes not much sense to use because --rootdir doesn't allow to enable compression
elif [ "${FORMAT}" = "ext4" ] || [ "${FORMAT}" = "ext2" ]; then
# Assuming that 1 GB is enough
truncate -s 1G "${SYSEXTNAME}".raw
# Note: We didn't chown to root:root, meaning that the file ownership is left as is
mkfs."${FORMAT}" -E root_owner=0:0 -d "${SYSEXTNAME}" "${SYSEXTNAME}".raw
resize2fs -M "${SYSEXTNAME}".raw
else
VER=$({ mksquashfs -version || true ; } | head -n1 | cut -d " " -f 3)
VERMAJ=$(echo "${VER}" | cut -d . -f 1)
VERMIN=$(echo "${VER}" | cut -d . -f 2)
ARG=(-all-root -noappend)
if [ "${VERMAJ}" -gt 4 ] && [ "${VERMIN}" -gt 6 ]; then
ARG+=('-xattrs-exclude' '^btrfs.')
fi
mksquashfs "${SYSEXTNAME}" "${SYSEXTNAME}".raw "${ARG[@]}"
fi
echo "Created ${SYSEXTNAME}.raw"
90 changes: 90 additions & 0 deletions create_containerd_sysext.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
#!/usr/bin/env bash
set -euo pipefail

export ARCH="${ARCH-amd64}"
export RUNC_VERSION="${RUNC_VERSION-v1.2.0-rc.1}"
SCRIPTFOLDER="$(dirname "$(readlink -f "$0")")"
ONLY_CONTAINERD="${ONLY_CONTAINERD:-0}"

if [ $# -lt 2 ] || [ "$1" = "-h" ] || [ "$1" = "--help" ]; then
echo "Usage: $0 VERSION SYSEXTNAME"
echo "The script will download the containerd release tar ball and create a sysext squashfs image with the name SYSEXTNAME.raw in the current folder."
echo "A temporary directory named SYSEXTNAME in the current folder will be created and deleted again."
echo "All files in the sysext image will be owned by root."
echo "The necessary systemd services will be created by this script"
echo "To use arm64 pass 'ARCH=arm64' as environment variable (current value is '${ARCH}')."
"${SCRIPTFOLDER}"/bake.sh --help
exit 1
fi

VERSION="$1"
SYSEXTNAME="$2"

rm -f "containerd-${VERSION}.tgz"
curl -o "containerd-${VERSION}.tgz" -fsSL "https://github.com/containerd/containerd/releases/download/v${VERSION}/containerd-${VERSION}-linux-${ARCH}.tar.gz"
rm -f runc${ARCH}
curl -o runc -fsSL "https://github.com/opencontainers/runc/releases/download/${RUNC_VERSION}/runc.${ARCH}"
rm -rf "${SYSEXTNAME}"
mkdir -p "${SYSEXTNAME}"
tar --force-local -xf "containerd-${VERSION}.tgz" -C "${SYSEXTNAME}"
rm "containerd-${VERSION}.tgz"
mkdir -p "${SYSEXTNAME}"/usr/bin
mv "${SYSEXTNAME}"/bin/* "${SYSEXTNAME}"/usr/bin/
chmod +x runc
mv runc "${SYSEXTNAME}"/usr/bin
rmdir "${SYSEXTNAME}"/bin
mkdir -p "${SYSEXTNAME}/usr/lib/systemd/system"

cat > "${SYSEXTNAME}/usr/lib/systemd/system/containerd.service" <<-'EOF'
[Unit]
Description=containerd container runtime
After=network.target
[Service]
Delegate=yes
Environment=CONTAINERD_CONFIG=/usr/share/containerd/config.toml
ExecStart=/usr/bin/containerd --config ${CONTAINERD_CONFIG}
KillMode=process
Restart=always
# (lack of) limits from the upstream docker service unit
LimitNOFILE=1048576
LimitNPROC=infinity
LimitCORE=infinity
TasksMax=infinity
[Install]
WantedBy=multi-user.target
EOF
mkdir -p "${SYSEXTNAME}/usr/lib/systemd/system/multi-user.target.d"
{ echo "[Unit]"; echo "Upholds=containerd.service"; } > "${SYSEXTNAME}/usr/lib/systemd/system/multi-user.target.d/10-containerd-service.conf"
mkdir -p "${SYSEXTNAME}/usr/share/containerd"
cat > "${SYSEXTNAME}/usr/share/containerd/config.toml" <<-'EOF'
version = 2
# set containerd's OOM score
oom_score = -999
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc]
# setting runc.options unsets parent settings
runtime_type = "io.containerd.runc.v2"
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
SystemdCgroup = true
EOF
sed 's/SystemdCgroup = true/SystemdCgroup = false/g' "${SYSEXTNAME}/usr/share/containerd/config.toml" > "${SYSEXTNAME}/usr/share/containerd/config-cgroupfs.toml"

RELOAD=1 "${SCRIPTFOLDER}"/bake.sh "${SYSEXTNAME}"
rm -rf "${SYSEXTNAME}"

mv "${SYSEXTNAME}.raw" "${SYSEXTNAME}-${VERSION}.raw"

cat > containerd.conf << EOF
[Transfer]
Verify=false
[Source]
Type=url-file
Path=https://github.com/ninech/containerd-sysext/releases/${TAG}/download/
MatchPattern=${SYSEXTNAME}[email protected]
[Target]
InstancesMax=3
Type=regular-file
Path=/opt/extensions/containerd
CurrentSymlink=/etc/extensions/containerd.raw
EOF

sha256sum *.raw | tee SHA256SUMS

0 comments on commit 88ffaa3

Please sign in to comment.