osbuilder: add dracut build method

Add the option to build image and initrd using dracut.

Fixes: #311

Suggested-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Marco Vedovati <mvedovati@suse.com>
This commit is contained in:
Marco Vedovati 2019-06-12 18:58:38 +02:00
parent 8ebaac02d1
commit 2f55017fea
6 changed files with 239 additions and 44 deletions

View File

@ -9,15 +9,17 @@ ROOTFS_BUILDER := $(MK_DIR)/rootfs-builder/rootfs.sh
INITRD_BUILDER := $(MK_DIR)/initrd-builder/initrd_builder.sh
IMAGE_BUILDER := $(MK_DIR)/image-builder/image_builder.sh
DISTRO := centos
BUILD_METHOD := distro
BUILD_METHOD_LIST := distro dracut
AGENT_INIT ?= no
DISTRO ?= centos
ROOTFS_BUILD_DEST := $(PWD)
IMAGES_BUILD_DEST := $(PWD)
DISTRO_ROOTFS := $(ROOTFS_BUILD_DEST)/$(DISTRO)_rootfs
ROOTFS_BUILD_DEST := $(shell pwd)
IMAGES_BUILD_DEST := $(shell pwd)
ROOTFS_MARKER_SUFFIX := _rootfs.done
DISTRO_ROOTFS_MARKER := $(ROOTFS_BUILD_DEST)/.$(DISTRO)$(ROOTFS_MARKER_SUFFIX)
DISTRO_IMAGE := $(IMAGES_BUILD_DEST)/kata-containers.img
DISTRO_INITRD := $(IMAGES_BUILD_DEST)/kata-containers-initrd.img
TARGET_ROOTFS := $(ROOTFS_BUILD_DEST)/$(DISTRO)_rootfs
TARGET_ROOTFS_MARKER := $(ROOTFS_BUILD_DEST)/.$(DISTRO)$(ROOTFS_MARKER_SUFFIX)
TARGET_IMAGE := $(IMAGES_BUILD_DEST)/kata-containers.img
TARGET_INITRD := $(IMAGES_BUILD_DEST)/kata-containers-initrd.img
VERSION_FILE := ./VERSION
VERSION := $(shell grep -v ^\# $(VERSION_FILE))
@ -25,6 +27,34 @@ COMMIT_NO := $(shell git rev-parse HEAD 2> /dev/null || true)
COMMIT := $(if $(shell git status --porcelain --untracked-files=no),${COMMIT_NO}-dirty,${COMMIT_NO})
VERSION_COMMIT := $(if $(COMMIT),$(VERSION)-$(COMMIT),$(VERSION))
ifeq ($(filter $(BUILD_METHOD),$(BUILD_METHOD_LIST)),)
$(error Invalid BUILD_METHOD value '$(BUILD_METHOD)'. Supported values: $(BUILD_METHOD_LIST))
endif
ifeq (dracut,$(BUILD_METHOD))
DISTRO :=
TARGET_ROOTFS := dracut_rootfs
TARGET_ROOTFS_MARKER := $(ROOTFS_BUILD_DEST)/.dracut$(ROOTFS_MARKER_SUFFIX)
# dracut specific variables
DRACUT_KVERSION :=
DRACUT_OVERLAY_DIR := $(MK_DIR)/dracut_overlay
DRACUT_DIR := $(MK_DIR)/dracut
DRACUT_CONF_DIR := $(DRACUT_DIR)/dracut.conf.d
DRACUT_OPTIONS := --no-compress --conf /dev/null --confdir $(DRACUT_CONF_DIR)
ifneq (,$(DRACUT_KVERSION))
# If a kernel version is not specified, do not make systemd load modules
# at startup
DRACUT_KMODULES := $(shell grep "^drivers=" $(DRACUT_CONF_DIR)/10-drivers.conf | sed -E "s,^drivers=\"(.*)\"$$,\1,")
else
DRACUT_OPTIONS += --no-kernel
endif
ifeq (,$(DRACUT_OVERLAY_DIR))
$(error DRACUT_OVERLAY_DIR cannot be empty)
endif
endif
# Set the variable to silent logs using chronic
OSBUILDER_USE_CHRONIC :=
@ -53,7 +83,17 @@ rootfs-%: $(ROOTFS_BUILD_DEST)/.%$(ROOTFS_MARKER_SUFFIX)
.PRECIOUS: $(ROOTFS_BUILD_DEST)/.%$(ROOTFS_MARKER_SUFFIX)
$(ROOTFS_BUILD_DEST)/.%$(ROOTFS_MARKER_SUFFIX):: rootfs-builder/%
$(call silent_run,Creating rootfs for "$*",$(ROOTFS_BUILDER) -o $(VERSION_COMMIT) -r $(ROOTFS_BUILD_DEST)/$*_rootfs $*)
touch $@
@touch $@
# To generate a dracut rootfs, we first generate a dracut initrd and then
# extract it in a local folder.
# Notes:
# - assuming a not compressed initrd.
.PRECIOUS: $(ROOTFS_BUILD_DEST)/.dracut$(ROOTFS_MARKER_SUFFIX)
$(ROOTFS_BUILD_DEST)/.dracut$(ROOTFS_MARKER_SUFFIX): $(TARGET_INITRD)
mkdir -p $(TARGET_ROOTFS)
cat $< | cpio --extract --preserve-modification-time --make-directories --directory=$(TARGET_ROOTFS)
@touch $@
image-%: $(IMAGES_BUILD_DEST)/kata-containers-image-%.img
@ # DONT remove. This is not cancellation rule.
@ -73,19 +113,37 @@ $(IMAGES_BUILD_DEST)/kata-containers-initrd-%.img: rootfs-%
all: image initrd
.PHONY: rootfs
rootfs: $(DISTRO_ROOTFS_MARKER)
rootfs: $(TARGET_ROOTFS_MARKER)
.PHONY: image
image: $(DISTRO_IMAGE)
image: $(TARGET_IMAGE)
$(TARGET_IMAGE): $(TARGET_ROOTFS_MARKER)
$(call silent_run,Creating image based on "$(TARGET_ROOTFS)",$(IMAGE_BUILDER) -o $@ "$(TARGET_ROOTFS)")
$(DISTRO_IMAGE): $(DISTRO_ROOTFS_MARKER)
$(call silent_run,Creating image based on "$(DISTRO_ROOTFS)",$(IMAGE_BUILDER) "$(DISTRO_ROOTFS)")
.PHONY: initrd
initrd: $(DISTRO_INITRD)
initrd: $(TARGET_INITRD)
$(DISTRO_INITRD): $(DISTRO_ROOTFS_MARKER)
$(call silent_run,Creating initrd image based on "$(DISTRO_ROOTFS)",$(INITRD_BUILDER) "$(DISTRO_ROOTFS)")
ifeq (distro,$(BUILD_METHOD))
$(TARGET_INITRD): $(TARGET_ROOTFS_MARKER)
$(call silent_run,Creating initrd image based on "$(TARGET_ROOTFS)",$(INITRD_BUILDER) "$(TARGET_ROOTFS)")
else
$(TARGET_INITRD): $(DRACUT_OVERLAY_DIR)
@echo Creating initrd image based on the host OS using dracut
dracut $(DRACUT_OPTIONS) --include $< / $@ $(DRACUT_KVERSION)
endif
# Notes on overlay dir:
# - If user specified any kernel module in the dracut conf file,
# we need to make sure these are pre-loaded at startup using
# systemd modules-load.d
$(DRACUT_OVERLAY_DIR):
mkdir -p $@
# Modules preload
$(ROOTFS_BUILDER) -o $(VERSION_COMMIT) -r $@
mkdir -p $@/etc/modules-load.d
echo $(DRACUT_KMODULES) | tr " " "\n" > $@/etc/modules-load.d/kata-modules.conf
.PHONY: test
test:
@ -140,7 +198,7 @@ install-scripts:
.PHONY: clean
clean:
rm -rf $(DISTRO_ROOTFS_MARKER) $(DISTRO_ROOTFS) $(DISTRO_IMAGE) $(DISTRO_INITRD)
rm -rf $(TARGET_ROOTFS_MARKER) $(TARGET_ROOTFS) $(TARGET_IMAGE) $(TARGET_INITRD) $(DRACUT_OVERLAY_DIR)
# Prints the name of the variable passed as suffix to the print- target,
# E.g., if Makefile contains:

100
README.md
View File

@ -2,18 +2,25 @@
# osbuilder
* [Introduction](#introduction)
* [Terms](#terms)
* [Usage](#usage)
* [osbuilder](#osbuilder)
* [Introduction](#introduction)
* [Terms](#terms)
* [Building](#building)
* [Rootfs creation](#rootfs-creation)
* [Rootfs with systemd as init](#rootfs-with-systemd-as-init)
* [Rootfs with the agent as init](#rootfs-with-the-agent-as-init)
* [dracut based rootfs](#dracut-based-rootfs)
* [Image creation](#image-creation)
* [Image with systemd as init](#image-with-systemd-as-init)
* [Image with the agent as init](#image-with-the-agent-as-init)
* [dracut based image](#dracut-based-image)
* [Initrd creation](#initrd-creation)
* [Tests](#tests)
* [Platform-Distro Compatibility Matrix](#platform-distro-compatibility-matrix)
* [Rootfs based initrd](#rootfs-based-initrd)
* [dracut based initrd](#dracut-based-initrd)
* [dracut options](#dracut-options)
* [Add kernel modules](#add-kernel-modules)
* [Testing](#testing)
* [Platform-Distro Compatibility Matrix](#platform-distro-compatibility-matrix)
## Introduction
@ -53,16 +60,39 @@ This section describes the terms used for all documentation in this repository.
A particular version of a Linux distribution used to create a rootfs from.
## Usage
- dracut
A guest OS build method where the building host is used as the Base OS.
For more information refer to the [dracut homepage](https://dracut.wiki.kernel.org/index.php/Main_Page).
## Building
The top-level `Makefile` contains an example of how to use the available components.
By default, components will run on the host system. However, some components
Two build methods are available, `distro` and `dracut`.
By default, the `distro` build method is used, and this creates a rootfs using
distro specific commands (e.g.: `debootstrap` for Debian or `yum` for CentOS).
The `dracut` build method uses the distro-agnostic tool `dracut` to obtain the same goal.
By default components are run on the host system. However, some components
offer the ability to run from within Docker (for ease of setup) by setting the
`USE_DOCKER=true` variable.
For more detailed information, consult the documentation for a particular component.
When invoking the appropriate make target as showed below, a single command is used
to generate an initrd or an image. This is what happens in details:
1. A rootfs is generated based on the specified target distribution.
2. The rootfs is provisioned with Kata-specific components and configuration files.
3. The rootfs is used as a base to generate an initrd or an image.
When using the dracut build method however, the build sequence is different:
1. An overlay directory is populated with Kata-specific components.
2. dracut is instructed to merge the overlay directory with the required host-side
filesystem components to generate an initrd.
3. When generating an image, the initrd is extracted to obtain the base rootfs for
the image.
### Rootfs creation
This section shows how to build a basic rootfs using the default distribution.
@ -81,6 +111,15 @@ $ sudo -E PATH=$PATH make USE_DOCKER=true rootfs
$ sudo -E PATH=$PATH make USE_DOCKER=true AGENT_INIT=yes rootfs
```
#### dracut based rootfs
> **Note**: the dracut build method does not need a rootfs as a base for an image or initrd.
However, a rootfs can be generated by extracting the generated initrd.
```
$ sudo -E PATH=$PATH make BUILD_METHOD=dracut rootfs
```
### Image creation
This section shows how to create an image from the already-created rootfs. For
@ -99,18 +138,55 @@ $ sudo -E PATH=$PATH make USE_DOCKER=true image
$ sudo -E PATH=$PATH make USE_DOCKER=true AGENT_INIT=yes image
```
#### dracut based image
> Note: the dracut build method generates an image by first building an initrd,
and then using the rootfs extracted from it.
```
$ sudo -E PATH=$PATH make BUILD_METHOD=dracut image
```
### Initrd creation
To create an initrd from the already-created rootfs with the agent acting as the init daemon:
#### Rootfs based initrd
Create an initrd from the already-created rootfs and with the agent acting as the init daemon
using:
```
$ sudo -E PATH=$PATH make AGENT_INIT=yes initrd
```
#### dracut based initrd
Create an initrd using the dracut build method with:
```
$ sudo -E PATH=$PATH make BUILD_METHOD=dracut AGENT_INIT=yes initrd
```
For further details,
see [the initrd builder documentation](initrd-builder/README.md).
### Tests
### dracut options
#### Add kernel modules
If the initrd or image needs to contain kernel modules, this can be done by:
1. Specify the name of the modules (as reported by `modinfo MODULE-NAME`) in
`dracut/dracut.conf.d/10-drivers.conf`. For example this file can contain:
```
drivers="9p 9pnet 9pnet_virtio"
```
2. Set the `DRACUT_KVERSION` make variable to the release name of the kernel that
is paired with the built image or initrd, using the `uname -r` format. For example:
```
$ make BUILD_METHOD=dracut DRACUT_KVERSION=5.2.1-23-kata AGENT_INIT=yes initrd
```
## Testing
```
$ make test
@ -120,6 +196,12 @@ For further details, see [the tests documentation](tests/README.md).
## Platform-Distro Compatibility Matrix
The following table illustrates what target architecture is supported for each
of the the osbuilder distributions.
> Note: this table is not relevant for the dracut build method, since it supports
any Linux distribution and architecture where dracut is available.
| |Alpine |CentOS |Clear Linux |Debian/Ubuntu |EulerOS |Fedora |openSUSE |
|-- |-- |-- |-- |-- |-- |-- |-- |
|**ARM64** |:heavy_check_mark:|:heavy_check_mark:| | |:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark:|

View File

@ -0,0 +1,17 @@
#
# Copyright (c) 2019 SUSE LLC
#
# SPDX-License-Identifier: Apache-2.0
# Main dracut config for Kata Containers
# do NOT combine early microcode with ramdisk
early_microcode="no"
# do NOT install only what's needed to boot the local host
hostonly="no"
# do NOT store the kernel command line arguments in the initramfs
hostonly_cmdline="no"
# create reproducible images
reproducible="yes"
# dracut modules to include (NOTE: these are NOT kernel modules)
dracutmodules="kernel-modules udev-rules syslog systemd"

View File

@ -0,0 +1,9 @@
#
# Copyright (c) 2019 SUSE LLC
#
# SPDX-License-Identifier: Apache-2.0
# Specify a space-separated set of kernel modules to copy from the host to
# the initramfs image. For example:
# drivers="9p 9pnet 9pnet_virtio"
drivers=""

View File

@ -11,7 +11,7 @@
* [Create template files](#create-template-files)
* [Modify template files](#modify-template-files)
* [Expected rootfs directory content](#expected-rootfs-directory-content)
* [Optional - Customise the rootfs](#optional---customise-the-rootfs)
* [Optional - Customize the rootfs](#optional---customize-the-rootfs)
* [Adding extra packages](#adding-extra-packages)
* [Arbitrary rootfs changes](#arbitrary-rootfs-changes)
@ -26,24 +26,24 @@ distribution. The script supports multiple distributions and can be extended
to add further ones.
### Extra features
#### Supported distributions list
Supported distributions can be listed with:
List the supported distributions by running the following:
```
$ ./rootfs.sh -l
```
#### Generate Kata specific files
`rootfs.sh` can be used to only populate a target directory with the set of Kata
specific files and components integrable into a generic Linux rootfs to generate
a Kata guest OS image.
This feature can be used when creating a rootfs with a distribution not officially
supported by osbuilder.
It is also used when building the rootfs using the 'dracut' build method.
The `rootfs.sh` script can be used to populate a directory with only Kata specific files and
components, without creating a full usable rootfs.
This feature is used to create a rootfs based on a distribution not officially
supported by osbuilder, and when building an image using the dracut build method.
To obtain this, simply invoke `rootfs.sh` without specifying a target rootfs, e.g.:
To achieve this, simply invoke `rootfs.sh` without specifying a target rootfs, e.g.:
```
mkdir kata-overlay
./rootfs.sh -r `pwd`/kata-overlay
$ mkdir kata-overlay
$ ./rootfs.sh -r "$PWD/kata-overlay"
```
## Rootfs requirements
@ -177,7 +177,7 @@ After the new directory structure is created:
After the function `build_rootfs` is called, the script expects the
rootfs directory to contain `/sbin/init` and `/sbin/kata-agent` binaries.
### Optional - Customise the rootfs
### Optional - Customize the rootfs
For particular use cases developers might want to modify the guest OS.

View File

@ -386,12 +386,15 @@ build_rootfs_distro()
# This is used when a distro is not specified.
prepare_overlay()
{
pushd "${ROOTFS_DIR}" >> /dev/null
pushd "${ROOTFS_DIR}" > /dev/null
mkdir -p ./etc ./lib/systemd ./sbin ./var
ln -sf ./usr/lib/systemd/systemd ./init
ln -sf ../../init ./lib/systemd/systemd
ln -sf ../init ./sbin/init
popd >> /dev/null
# Kata sytemd unit file
mkdir -p ./etc/systemd/system/basic.target.wants/
ln -sf /usr/lib/systemd/system/kata-containers.target ./etc/systemd/system/basic.target.wants/kata-containers.target
popd > /dev/null
}
# Setup an existing rootfs directory, based on the OPTIONAL distro name
@ -405,14 +408,40 @@ setup_rootfs()
if [ "$PWD" != "/" ] ; then
rm -rf ./var/cache/ ./var/lib ./var/log ./var/tmp
fi
ln -s ../tmp ./var/
# For some distros tmp.mount may not be installed by default in systemd paths
if ! [ -f "./etc/systemd/system/tmp.mount" ] && \
! [ -f "./usr/lib/systemd/system/tmp.mount" ] &&
[ "$AGENT_INIT" != "yes" ]; then
local unitFile="./etc/systemd/system/tmp.mount"
info "Install tmp.mount in ./etc/systemd/system"
cp ./usr/share/systemd/tmp.mount ./etc/systemd/system/tmp.mount
mkdir -p `dirname "$unitFile"`
cp ./usr/share/systemd/tmp.mount "$unitFile" || cat > "$unitFile" << EOT
# This file is part of systemd.
#
# systemd is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version.
[Unit]
Description=Temporary Directory (/tmp)
Documentation=man:hier(7)
Documentation=https://www.freedesktop.org/wiki/Software/systemd/APIFileSystems
ConditionPathIsSymbolicLink=!/tmp
DefaultDependencies=no
Conflicts=umount.target
Before=local-fs.target umount.target
After=swap.target
[Mount]
What=tmpfs
Where=/tmp
Type=tmpfs
Options=mode=1777,strictatime,nosuid,nodev
EOT
fi
popd >> /dev/null
@ -486,7 +515,7 @@ parse_arguments()
l) get_distros | sort && exit 0;;
o) OSBUILDER_VERSION="${OPTARG}" ;;
r) ROOTFS_DIR="${OPTARG}" ;;
t) get_test_config "${OPTARG}" && exit -1;;
t) get_test_config "${OPTARG}" && exit 0;;
*) die "Found an invalid option";;
esac
done