Skip to content
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

improve support for out-of-tree kernel modules #1220

Merged
merged 7 commits into from
Dec 1, 2020

Conversation

bcressey
Copy link
Contributor

Issue number:
#1141

Description of changes:
This overhauls our packaging of kernel development sources, so that they can be used on an architecture that differs from the build host, and can be extracted for use outside of a running host.

Testing done:
Tests were repeated across this matrix:

  • x86_64 image and kmod kit built on an x86_64 host
  • x86_64 image and kmod kit built on an aarch64 host
  • aarch64 image and kmod kit built on an x86_64 host
  • aarch64 image and kmod kit built on an aarch64 host

Images were tested by launching nodes, logging into a Fedora-based admin container, building the Wireguard out-of-tree module, and then running make prepare.

x86_64 images were additionally tested by using Helm to install Falco, and verifying that the module could be built by DKMS and loaded:

helm install falco falcosecurity/falco \
  --namespace kube-system \
  --set docker.enabled=false

The kmod kits were tested on Fedora 32 and Amazon Linux 2, by building the Wireguard and ZFS out-of-tree modules, using snippets like this:

FROM base as wireguard-build
ARG VARIANT="aws-k8s-1.18"
ARG ARCH="x86_64"
ARG VERSION="1.0.3"
ARG KIT="${VARIANT}-${ARCH}-kmod-kit-v${VERSION}"
ARG KERNELDIR="/tmp/${KIT}/kernel-devel"
ARG CROSS_COMPILE="${ARCH}-bottlerocket-linux-musl-"
ARG INSTALL_MOD_STRIP=1
RUN \
  export PATH="/tmp/${KIT}/toolchain/usr/bin:${PATH}" && \
  make -C wireguard-linux-compat/src module

The modules were then loaded on a running instance to confirm they were built correctly.

x86_64 kmod kits were additionally tested by building the Falco module.

Terms of contribution:

By submitting this pull request, I agree that this contribution is dual-licensed under the terms of both the Apache License, version 2.0, and the MIT license.

packages/kernel/kernel.spec Show resolved Hide resolved
Makefile.toml Show resolved Hide resolved
Makefile.toml Outdated Show resolved Hide resolved
Makefile.toml Outdated Show resolved Hide resolved
Copy link
Contributor

@sam-aws sam-aws left a comment

Choose a reason for hiding this comment

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

🎄

It's times like these that make me look fondly back on Buildroot

Copy link
Contributor

@zmrow zmrow left a comment

Choose a reason for hiding this comment

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

The kernel.spec changes are over my head a bit, but everything else looks good!

🦃

We use squashfs archives for files that must be included, but which
are rarely or never accessed on most running systems. zstd offers
compression ratios similar to xz, and decompression speeds like lz4.
This saves space while keeping reads fast.

Signed-off-by: Ben Cressey <bcressey@amazon.com>
Previously, we included host programs like `objtool` which are built
with the default `gcc` compiler and not our cross-compiler toolchain.

This works as long as the running system matches our build host, but
would break if we began building x86_64 images on an aarch64 system.
The reverse is not true today, but only because `objtool` is not yet
required for the arm64 target.

Ideally, we'd be able to cross-compile these host programs, but that
isn't supported by the kernel's build system, and would be hard to
implement. For example, `fixdep` is both a tool we'd want to ship,
meaning it would need to be cross-compiled, and a tool that's used
to build `objtool`, meaning it couldn't be cross-compiled and still
run on the build host.

Instead we push the problem out to the downstream consumer, who can
be relied on to have a compiler that can build native versions of the
host programs. This requires shipping all the headers, tools, and
scripts needed to run `make prepare`.

For compatibility with solutions like DKMS, which do not expect to
run anything but the module build, we add a minimal prepare target
to this path so that the host programs will be automatically rebuilt.
We also make some edits and exclude some files to avoid dependencies
on bison, flex, and OpenSSL.

Signed-off-by: Ben Cressey <bcressey@amazon.com>
The squashfs filesystem is meant to be used on a running host, while
a tarball is easier to work with when assembling a combined archive
that also includes our toolchain.

Signed-off-by: Ben Cressey <bcressey@amazon.com>
Apply the same options we use for the kernel-devel squashfs.

Signed-off-by: Ben Cressey <bcressey@amazon.com>
With the changes to our packaging of kernel development sources, any
out-of-tree module builds will need to run `make prepare` in order to
compile dependencies like `objtool`. These binaries need to land in
the same directory tree as the other development files we ship.

Using an overlayfs mount allows writes to the otherwise read-only
content from the squashfs. We purge the upper directory on reboot so
changes do not persist across system upgrades.

Signed-off-by: Ben Cressey <bcressey@amazon.com>
This directory needs to be writable in order to build out-of-tree
modules inside a superpowered container.

Signed-off-by: Ben Cressey <bcressey@amazon.com>
To support compiling out-of-tree modules ahead of time, rather than
on a running Bottlerocket host, we need to provide two things: the
kernel development sources, such as headers and Makefiles; and the
toolchain we use to build our kernel.

Our toolchain is built separately as part of our cross-compiling SDK,
and it's possible, if unlikely, that we would ship two releases with
the same kernel version built with a different GCC.

It's also possible that variants will use different kernels, so we
cannot have just one development kit per release. This is not yet
supported, but we need the ecosystem to anticipate the requirement
for a per-variant, per-architecture kit.

The build target combines the archives from the toolchain matching
the SDK we used to build the kernel, and kernel development sources
from the most recent build. This produces a single artifact that
can be uploaded for later retrieval by a consumer that knows the
variant, architecture, and version that they are targeting.

Signed-off-by: Ben Cressey <bcressey@amazon.com>
@bcressey bcressey merged commit c06a812 into bottlerocket-os:develop Dec 1, 2020
@bcressey bcressey deleted the kmod-kit branch December 1, 2020 22:27
@tjkirch tjkirch mentioned this pull request Jan 11, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants