April 10, 2023

Deploy Arch Linux microVM with Firecracker

Firecracker is a virtual machine monitor that leverages KVM to rapidly launch Linux guest VMs. Its key advantage is its ability to quickly start up VMs.

Firecracker was created by AWS with the aim of boosting the speed and efficiency of AWS services such as AWS Lambda and AWS Fargate. Written in Rust, Firecracker is licensed under the Apache version 2.0.

Firecracker is an open source virtualization technology that is purpose-built for creating and managing secure, multi-tenant container and function-based services that provide serverless operational models

Install firecracker

$ pacman -S firecracker

Check the github repository for other method of installation.

Create a Kernel Image

Get the tarball of the kernel you want from https://kernel.org or git clone the repository from https://git.kernel.org and checkout the Linux version you want to build.

The linux kernel need to be configured and Firecracker has a recommended x86 config. Copy the config file to .config under the Linux source directory and launch make. After a successful build, the kernel image can be located under ./vmlinux.

Create Arch rootfs

Create a new disk image.

$ qemu-img create -f raw arch-rootfs.ext4 800M
Formatting 'arch-rootfs.ext4', fmt=raw size=838860800

Format the disk image to ext4

$ mkfs.ext4 arch-rootfs.ext4
mke2fs 1.47.0 (5-Feb-2023)
Discarding device blocks: done                            
Creating filesystem with 204800 4k blocks and 51296 inodes
Filesystem UUID: 48349973-58f1-4a8d-bb78-770e97590c2b
Superblock backups stored on blocks: 
	32768, 98304, 163840

Allocating group tables: done                            
Writing inode tables: done                            
Creating journal (4096 blocks): done
Writing superblocks and filesystem accounting information: done

Create the directory to mount the disk image.

$ mkdir /tmp/rootfs
$ mount arch-rootfs.ext4  /tmp/rootfs

Use mkarchroot to create an Arch Linux chroot at directory archrtfs with the base package.

$ cd /tmp/my-rootfs
$ mkarchroot archrtfs base 
==> Creating install root at /tmp/qemu/ar
==> Installing packages to /tmp/qemu/ar
:: Synchronizing package databases...
 core                                                                                               154.0 KiB   642 KiB/s 00:00 [#############################################################################] 100%
 extra                                                                                             1762.9 KiB  7.58 MiB/s 00:00 [#############################################################################] 100%
 community                                                                                            7.2 MiB  2.38 MiB/s 00:03 [#############################################################################] 100%
resolving dependencies...
looking for conflicting packages...

Packages (113) acl-2.3.1-3  archlinux-keyring-20230320-1  argon2-20190702-4  attr-2.5.1-3  audit-3.1-1  bash-5.1.016-3  brotli-1.0.9-10  bzip2-1.0.8-5  ca-certificates-20220905-1  ca-certificates-mozilla-3.89-1
               ca-certificates-utils-20220905-1  coreutils-9.2-3  cryptsetup-2.6.1-3  curl-8.0.1-1  dbus-1.14.6-2  device-mapper-2.03.20-1  e2fsprogs-1.47.0-1  expat-2.5.0-1  file-5.44-3  filesystem-2023.01.31-1
               findutils-4.9.0-3  gawk-5.2.1-2  gcc-libs-12.2.1-2  gdbm-1.23-2  gettext-0.21.1-5  glib2-2.76.1-1  glibc-2.37-2  gmp-6.2.1-2  gnupg-2.2.41-1  gnutls-3.8.0-1  gpgme-1.19.0-3  grep-3.10-1
               gzip-1.12-2  hwdata-0.369-1  iana-etc-20230405-1  icu-72.1-2  iproute2-6.2.0-2  iptables-1:1.8.9-1  iputils-20221126-1  json-c-0.16-1  kbd-2.5.1-1  keyutils-1.6.3-1  kmod-30-3  krb5-1.20.1-1
               less-1:608-2  libarchive-3.6.2-2  libassuan-2.5.5-2  libbpf-1.1.0-1  libcap-2.68-1  libcap-ng-0.8.3-1  libelf-0.189-1  libevent-2.1.12-4  libffi-3.4.4-1  libgcrypt-1.10.1-2  libgpg-error-1.46-2
               libidn2-2.3.4-3  libksba-1.6.3-1  libldap-2.6.4-1  libmnl-1.0.5-1  libnetfilter_conntrack-1.0.9-1  libnfnetlink-1.0.2-1  libnftnl-1.2.5-1  libnghttp2-1.52.0-2  libnl-3.7.0-3  libp11-kit-0.24.1-1
               libpcap-1.10.3-1  libpsl-0.21.2-1  libsasl-2.1.28-4  libseccomp-2.5.4-1  libsecret-0.20.5-2  libssh2-1.10.0-3  libsysprof-capture-3.48.0-1  libtasn1-4.19.0-1  libtirpc-1.3.3-2  libunistring-1.1-2
               libverto-0.3.2-4  libxcrypt-4.4.33-1  libxml2-2.10.3-2  licenses-20220125-2  linux-api-headers-6.1.9-1  lz4-1:1.9.4-1  mpfr-4.2.0-3  ncurses-6.4-1  nettle-3.8.1-1  npth-1.6-4  openssl-3.0.8-1
               p11-kit-0.24.1-1  pacman-6.0.2-6  pacman-mirrorlist-20230410-1  pam-1.5.2-1  pambase-20221020-1  pciutils-3.9.0-2  pcre2-10.42-2  pinentry-1.2.1-1  popt-1.19-1  procps-ng-3.3.17-1  psmisc-23.6-1
               readline-8.2.001-2  sed-4.9-3  shadow-4.13-2  sqlite-3.41.2-1  systemd-253.3-1  systemd-libs-253.3-1  systemd-sysvcompat-253.3-1  tar-1.34-2  tpm2-tss-3.2.0-3  tzdata-2023c-1  util-linux-2.38.1-3
               util-linux-libs-2.38.1-3  xz-5.4.2-1  zlib-1:1.2.13-2  zstd-1.5.4-1  base-3-1

Total Download Size:     0.40 MiB
Total Installed Size:  493.18 MiB

:: Proceed with installation? [Y/n] 
:: Retrieving packages...

Copy the filesystem from the temporary directory.

$ cp -r ar/* .
$ rm ar ar.lock  -rf 

Remove the root password.

$ arch-chroot /mnt/rootfs passwd -d root

Unmount the disk image and remove the directory.

$ umount /tmp/rootfs
$ rm -rf /tmp/rootfs

Move the kernel image and the filesystem to a new directory.

Start the MicroVM

Firecracker VMs can be started using the socket interface or configuration file.

We will use the configuration file method for better clarity. You can check the getting started instruction to create the API socket and feed data to it.

The configuration file is a JSON file.

{
  "boot-source": {
    "kernel_image_path": "vmlinux",
    "boot_args": "console=ttyS0 reboot=k panic=1 pci=off"
  },
  "drives": [
    {
      "drive_id": "rootfs",
      "path_on_host": "arch-rootfs.ext4",
      "is_root_device": true,
      "is_read_only": false
    }
  ],
  "machine-config": {
    "vcpu_count": 2,
    "mem_size_mib": 1024
  }
  
}

Starting the VM without an API socket and voila!

$ firecracker --no-api --config-file vm-config.json
[    0.000000] Linux version 5.10.177 (zain@code-lyoko) (gcc (GCC) 12.2.1 20230201, GNU ld (GNU Binutils) 2.40) #1 SMP Mon Apr 10 16:43:03 +04 2023
[    0.000000] Command line: console=ttyS0 reboot=k panic=1 pci=off root=/dev/vda rw virtio_mmio.device=4K@0xd0000000:5
[    0.000000] x86/fpu: Supporting XSAVE feature 0x001: 'x87 floating point registers'
[    0.000000] x86/fpu: Supporting XSAVE feature 0x002: 'SSE registers'
[    0.000000] x86/fpu: Supporting XSAVE feature 0x004: 'AVX registers'

...
...
...

[  OK  ] Reached target Basic System.
         Starting D-Bus System Message Bus...
         Starting User Login Management...
         Starting Permit User Sessions...
[  OK  ] Finished Permit User Sessions.
[  OK  ] Started Getty on tty1.
[  OK  ] Started D-Bus System Message Bus.
[  OK  ] Found device /dev/ttyS0.
[  OK  ] Started Serial Getty on ttyS0.
[  OK  ] Reached target Login Prompts.
[  OK  ] Started User Login Management.
[  OK  ] Reached target Multi-User System.
[  OK  ] Reached target Graphical Interface.

Arch Linux 5.10.177 (ttyS0)

archlinux login: root
Last login: Mon Apr 10 20:33:32 on ttyS0
[root@archlinux ~]# systemd-analyze 
Startup finished in 2.427s (kernel) + 2.017s (userspace) = 4.444s 
graphical.target reached after 2.009s in userspace.
[root@archlinux ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
[root@archlinux ~]# 

We have focus on getting the initial setup of our system up and running. However, at this point in time, we won’t have any network connectivity. Not to worry though, as we’ll cover how to configure the network in our upcoming blog series.

Resources

https://github.com/firecracker-microvm/firecracker

https://jvns.ca/blog/2021/01/23/firecracker--start-a-vm-in-less-than-a-second/

https://blog.herecura.eu/blog/2020-05-21-toying-around-with-firecracker/

Powered by Hugo & Kiss.