Kata Containers enable containers to be seamlessly executed in Virtual Machines. Kata Containers are as light and fast as containers and integrate with the container management layers, while also delivering the security advantages of VMs. Kata Containers is the result of merging two existing open source projects: Intel Clear Containers and Hyper runV.

Kata Containers consist of several components. For amd64 machines, binaries are provided through the formal release process. However, for arm64, binary files are not available (just yet).

In this post, we will be going through the steps to build kata containers from source, both for amd64 and arm64 architectures. In follow-up posts, we go through the steps to build and configure QEMU and AWS Firecracker as VMMs for Kata Containers.

Install requirements Link to heading

To build Kata Containers we need to install Rust v1.58.1, Go v1.16.10, Docker and some apt/snap packages. The specific versions may change, so make sure to check the versions database.

Apt/Snap Packages: Link to heading

We need to install gcc, make and yq v3. containerd and runc are installed by the Docker install script, in the following steps.

1sudo apt update && sudo apt upgrade -y
2sudo apt install gcc make snapd -y
3sudo snap install yq --channel=v3/stable

Rust (version 1.58.1): Link to heading

We will use rustup to install and set Rust 1.58.1 as our default toolchain:

1down_dir=$(mktemp -d)
2pushd $down_dir
3wget -q https://static.rust-lang.org/rustup/dist/$(uname -p)-unknown-linux-gnu/rustup-init
4sudo chmod +x rustup-init
5./rustup-init -q -y --default-toolchain 1.58.1
6source $HOME/.cargo/env
8rm -rf $down_dir

Go (version 1.16.10) Link to heading

We will download the appropriate Go binaries and add them to the PATH environment variable:

1down_dir=$(mktemp -d)
2pushd $down_dir
3wget -q https://go.dev/dl/go1.16.10.linux-$(dpkg --print-architecture).tar.gz
4sudo mkdir -p /usr/local/go1.16
5sudo tar -C /usr/local/go1.16 -xzf go1.16.10.linux-$(dpkg --print-architecture).tar.gz
6echo 'export PATH=$PATH:/usr/local/go1.16/go/bin' >> $HOME/.profile
7source $HOME/.profile
9rm -rf $down_dir

Docker Link to heading

We will install Docker using the provided convenience script:

 1sudo apt-get remove docker docker-engine docker.io containerd runc -y > /dev/null 2>&1
 2sudo rm -rf /var/lib/docker/
 3down_dir=$(mktemp -d)
 4pushd $down_dir
 5curl -fsSL https://get.docker.com -o get-docker.sh
 6sudo sh get-docker.sh
 7# Optionally add user to docker group to run docker without sudo
 8# sudo usermod -aG docker $USER
10rm -rf $down_dir

Build Kata components Link to heading

Build kata-runtime Link to heading

First, we need to set the correct Go environment variables:

1export PATH=$PATH:$(go env GOPATH)/bin && \
2  export GOPATH=$(go env GOPATH) && \
3  export GO111MODULE=off

We will use go get to download kata-containers source code:

1go get -d -u github.com/kata-containers/kata-containers

We are now ready to build the kata-runtime:

1pushd $GOPATH/src/github.com/kata-containers/kata-containers/src/runtime
2export GO111MODULE=on
3export PREFIX=/opt/kata

To install the binaries to a specific path (say /opt/kata) we need to specify the PREFIX environment variable prior to installing:

1pushd $GOPATH/src/github.com/kata-containers/kata-containers/src/runtime
2export PREFIX=/opt/kata
3sudo -E PATH=$PATH -E PREFIX=$PREFIX make install

Kata binaries are now installed in /opt/kata/bin and configs are installed in /opt/kata/share/defaults/kata-containers/.

It is recommended you add a symbolic link to /opt/kata/bin/kata-runtime and /opt/kata/bin/containerd-shim-kata-v2 in order for containerd to reach these binaries from the default system PATH.

1sudo ln -s /opt/kata/bin/kata-runtime /usr/local/bin
2sudo ln -s /opt/kata/bin/containerd-shim-kata-v2 /usr/local/bin

Create a rootfs & initrd image Link to heading

We can use either a rootfs or initrd image to launch Kata Containers with Qemu. However, AWS Firecracker does not work with initrd images, so we will be using a rootfs image for Kata with Firecracker. If you do not want to use QEMU or QEMU with initrd, you can skip building the initrd image.

Create the rootfs base image:

1export ROOTFS_DIR=${GOPATH}/src/github.com/kata-containers/kata-containers/tools/osbuilder/rootfs-builder/rootfs
2cd $GOPATH/src/github.com/kata-containers/kata-containers/tools/osbuilder/rootfs-builder
3# you may change the distro (in this case we used ubuntu). to get supported distros list, run ./rootfs.sh -l
4script -fec 'sudo -E GOPATH=$GOPATH AGENT_INIT=yes USE_DOCKER=true ./rootfs.sh ubuntu'

Note for arm64:

We noticed that in some instances the kata-agent compilation failed. A possible workaround was to remove the USE_DOCKER variable. This requires qemu-img command to be available on your system. You can install it with sudo apt install -y qemu-utils.

1export ROOTFS_DIR="${GOPATH}/src/github.com/kata-containers/kata-containers/tools/osbuilder/rootfs-builder/rootfs"
2sudo rm -rf ${ROOTFS_DIR}
3cd $GOPATH/src/github.com/kata-containers/kata-containers/tools/osbuilder/rootfs-builder
4script -fec 'sudo -E GOPATH=$GOPATH AGENT_INIT=yes ./rootfs.sh ubuntu'

Build a kata rootfs image:

1cd $GOPATH/src/github.com/kata-containers/kata-containers/tools/osbuilder/image-builder && \
2  script -fec 'sudo -E USE_DOCKER=true -E AGENT_INIT=yes ./image_builder.sh ${ROOTFS_DIR}'

Install the kata rootfs image:

1export PREFIX=/opt/kata
2commit=$(git log --format=%h -1 HEAD) && \
3  date=$(date +%Y-%m-%d-%T.%N%z) && \
4  image="kata-containers-${date}-${commit}" && \
5  sudo install -o root -g root -m 0640 -D kata-containers.img "$PREFIX/share/kata-containers/${image}" && \
6  (cd $PREFIX/share/kata-containers && sudo ln -sf "$image" kata-containers.img)

(OPTIONAL) Next we will build an initrd image:

1cd $GOPATH/src/github.com/kata-containers/kata-containers/tools/osbuilder/initrd-builder
2script -fec 'sudo -E AGENT_INIT=yes USE_DOCKER=true ./initrd_builder.sh ${ROOTFS_DIR}'

(OPTIONAL) Once the image is built, we install it:

1export PREFIX=/opt/kata
2commit=$(git log --format=%h -1 HEAD) && \
3  date=$(date +%Y-%m-%d-%T.%N%z) && \
4  image="kata-containers-initrd-${date}-${commit}" && \
5  sudo install -o root -g root -m 0640 -D kata-containers-initrd.img "$PREFIX/share/kata-containers/${image}" && \
6  (cd $PREFIX/share/kata-containers && sudo ln -sf "$image" kata-containers-initrd.img)

Build Kata Containers kernel Link to heading

First, we need some additional packages to build the kernel:

1sudo apt install -y libelf-dev bison flex

Setup the kernel source code:

1cd $GOPATH/src/github.com/kata-containers/kata-containers/tools/packaging/kernel
2./build-kernel.sh -d setup

Build the kernel:

1./build-kernel.sh -d build

Install the kernel in the default path for Kata:

1export PREFIX=/opt/kata
2sudo -E PATH=$PATH -E PREFIX=$PREFIX ./build-kernel.sh -d install


We noticed that in some instances the installation or build process failed with the following error: ERROR: path to kernel does not exist, use build-kernel.sh setup. We mitigated this problem by specifying the version:

1./build-kernel.sh -d -v 5.15.26 build
2export PREFIX=/opt/kata
3sudo -E PATH=$PATH -E PREFIX=$PREFIX ./build-kernel.sh -d -v 5.15.26 install

Next steps Link to heading

At this point we have successfully built all the Kata components. All the binaries we built are stored under the /opt/kata/bin dir:

1$ ls -l /opt/kata/bin/
2total 142296
3-rwxr-xr-x 1 root root 50919312 Mar  25 15:32 containerd-shim-kata-v2
4-rwxr-xr-x 1 root root    16691 Mar  25 15:32 kata-collect-data.sh
5-rwxr-xr-x 1 root root 42093616 Mar  25 15:32 kata-monitor
6-rwxr-xr-x 1 root root 52673784 Mar  25 15:32 kata-runtime

The rootfs image, the initrd image and the kernel are stored under the /opt/kata/share/defaults/kata-containers dir:

 1$ ls -l /opt/kata/share/kata-containers/
 2total 221972
 3-rw-r--r-- 1 root root     72480 Μαρ  25 15:51 config-5.15.26
 4-rw-r----- 1 root root 134217728 Μαρ  25 15:41 kata-containers-2022-03-25-15:41:55.534872004+0200-486322a0
 5lrwxrwxrwx 1 root root        59 Μαρ  25 15:41 kata-containers.img -> kata-containers-2022-03-25-15:41:55.534872004+0200-486322a0
 6-rw-r----- 1 root root  27627256 Μαρ  24 14:43 kata-containers-initrd-2022-03-24-14:43:59.501993241+0200-853dd98b
 7-rw-r----- 1 root root  27626874 Μαρ  25 15:42 kata-containers-initrd-2022-03-25-15:42:28.034074480+0200-486322a0
 8lrwxrwxrwx 1 root root        66 Μαρ  25 15:42 kata-containers-initrd.img -> kata-containers-initrd-2022-03-25-15:42:28.034074480+0200-486322a0
 9-rw-r--r-- 1 root root  38736168 Μαρ  25 15:51 vmlinux-5.15.26-90
10lrwxrwxrwx 1 root root        18 Μαρ  25 15:51 vmlinux.container -> vmlinux-5.15.26-90
11-rw-r--r-- 1 root root   5795664 Μαρ  25 15:51 vmlinuz-5.15.26-90
12lrwxrwxrwx 1 root root        18 Μαρ  25 15:51 vmlinuz.container -> vmlinuz-5.15.26-90

The configuration files are stored under the /opt/kata/share/defaults/kata-containers dir:

1ls -l /opt/kata/share/defaults/kata-containers
2total 72
3-rw-r--r-- 1 root root  9717 Μαρ  25 15:32 configuration-acrn.toml
4-rw-r--r-- 1 root root 13535 Μαρ  25 15:32 configuration-clh.toml
5-rw-r--r-- 1 root root 15364 Μαρ  25 15:32 configuration-fc.toml
6-rw-r--r-- 1 root root 25701 Μαρ  25 15:32 configuration-qemu.toml
7lrwxrwxrwx 1 root root    23 Μαρ  25 15:32 configuration.toml -> configuration-qemu.toml

Now, we need to install a hypervisor (eg QEMU or Firecracker) and configure Kata Containers and containerd accordingly. In our upcoming posts we will go through the process of building and configuring both QEMU and AWS Firecracker for x86 and arm64 hosts. Happy hacking!