LeavaTailの日記

LeavaTailの日記

Linuxエンジニアを目指した技術者の備忘録

Ubuntu-base-20.04 を QEMU から NFSRootで起動する

概要

QEMUでエミュレートした armhfプロセッサ に Linuxを起動させ 、Ubuntu-base-20.04イメージをNFS mountする。

はじめに

Ubuntu baseは、最低限のUbuntuのrootfsである。 そのため、LXCやDockerのコンテナイメージで使われることがある。

一方でrootfsをNFS server上に置き、rootfsをNFS経由でmountする手法は、(主に組込み機器の)開発において有効である。*1

そこで、本記事では、QEMU上でarmhfプロセッサをエミュレートさせて、Ubuntu-base-20.04をrootfsとしてNFS mountする方法を記述する。

QEMUでarmhf用 Linuxカーネルを起動させる方法は、下記の記事を流用する。

leavatail.hatenablog.com

leavatail.hatenablog.com

実行環境

Host PCは下記のような環境で実験する。

項目 概要
Host PC (OS) Ubuntu 20.04.02
Architecture x86_64
QEMU qemu v5.1.0
nfs-kernlel-server 1:1.3.4-2.5ubuntu3.4
buildroot buildroot-2020.11

上記の環境で、QEMUを実行しゲストOSとしてLinux v5.10.1を起動させる。

動作環境の全体像

手順

  1. Host PCに下記パッケージをインストールする。

     $ sudo apt-get install nfs-kernel-server
    
  2. Host PCでNFSサーバの設定する

     $ echo "/srv/rootfs     127.0.0.1(rw,wdelay,insecure,no_root_squash,no_subtree_check,sec=sys,rw,insecure,no_root_squash,no_all_squash)" | sudo tee -a /etc/exports
     $ sudo exportfs -v
    
  3. Host PCにUbuntu-base-20.04 のイメージをダウンロードする

     $ wget -P /tmp http://cdimage.ubuntu.com/ubuntu-base/releases/20.04/release/ubuntu-base-20.04.3-base-armhf.tar.gz
     $ sudo tar xf /tmp/ubuntu-base-20.04.3-base-armhf.tar.gz -C /srv/rootfs/armhf
    
  4. [任意] Host PCに下記パッケージをインストールする。

     $ sudo apt-get install qemu-user-static
    
  5. [任意] Ubuntu-base-20.04 の rootfs に qemu-arm-staticをコピーする

     $ sudo update-binfmts --display | grep arm
     qemu-arm (enabled):
      interpreter = /usr/bin/qemu-arm-static
     qemu-armeb (enabled):
      interpreter = /usr/bin/qemu-armeb-static
    
     $ sudo cp /usr/bin/qemu-arm-static /srv/rootfs/armhf/usr/bin/    
    
  6. rootfs の initスクリプトを追加する

#!/bin/bash

PATH=/sbin:/bin:/usr/sbin:/usr/sbin

set -em
trap rescue ERR

function rescue {
        echo -e "\e[31m NG \e[m"
        exec /bin/sh
}

echo -n "[init] Connect console:"
if (exec 0</dev/console) 2>/dev/null; then
    exec 0</dev/console
    exec 1>/dev/console
    exec 2>/dev/console
fi
echo -e "\e[32m OK \e[m"

echo -n "[init] Mount filesystem:"
# mount -t devtmpfs udev /dev
mount -t proc /proc /proc
mount -t sysfs sysfs /sys
echo -e "\e[32m OK \e[m"

echo -n "[init] Mount filesystem additionaly:"
mount -t tmpfs -o size=32m tmpfs /tmp
if [ -d "/dev/pts" ]; then
        mount -t devpts /dev/pts /dev/pts
fi

if [ -d "/sys/kernel/debug" ]; then
        mount -t debugfs none /sys/kernel/debug
fi
echo -e "\e[32m OK \e[m"

exec setsid /sbin/agetty --long-hostname --autologin root -s ttyAMA0 115200,38400,9600 linux

起動確認

$ sudo qemu-system-arm -M vexpress-a9 \
        -smp 1 \
        -m 1024 \
        -kernel output/images/zImage \
        -dtb output/images/vexpress-v2p-ca9.dtb \
        -append "console=ttyAMA0,115200 rootwait ip=on root=/dev/nfs nfsroot=/srv/rootfs/armhf user_debug=31 rw" \
        -net nic,model=lan9118 \
        -net user \
        -nographic

... 

VFS: Mounted root (nfs filesystem) on device 0:14.
devtmpfs: mounted
Freeing unused kernel memory: 1024K
Run /sbin/init as init process
random: fast init done
[init] Connect console: OK 
[init] Mount filesystem: OK 
[init] Mount filesystem additionaly: OK 

Ubuntu 20.04.3 LTS 10.0.2.15 ttyAMA0

10.0.2.15 login: root (automatic login)

Welcome to Ubuntu 20.04.3 LTS (GNU/Linux 5.10.1 armv7l)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

This system has been minimized by removing packages and content that are
not required on a system that users do not log into.

To restore this content, you can run the 'unminimize' command.
Last login: Sun Oct 10 11:57:52 JST 2021 on ttyAMA0
root@10:~# 

補足

ここでは、手順や起動確認で解説できなかった内容について補足する。

NFSの設定について

QEMUのネットワークは複数の設定ができる。

Documentation/Networking - QEMU

今回は、User Networking を使用しているため、ゲストからホストはNATで扱われる。
そのため、NFSの設定でローカルループバックアドレスに任意のポートから受け付けるようにしている。*2

rootfsの更新について

x86_64アーキテクチャから、armhfのrootfsを直接chrootすることはできない。
そこで、qemu-user-staticを介することでrootfsを操作できるようにしている。

このようにしておくことで、Ubuntu-base 20.04に、systemdがインストールするなどが容易にできる。
その場合は、名前解決できるように適切に設定しておく必要はある。

  # echo  nameserver 8.8.8.8 >> /etc/resolv.conf

おわりに

本記事では、QEMU上でarmhfプロセッサをエミュレートさせて、Ubuntu-base-20.04をrootfsとしてNFS mountする方法を記述した。

Ubuntu baseイメージは最小のrootfsであるため、systemdを追加でインストールしたりなどカスタマイズ性が高い。

変更履歴

  • 2021/10/10: 記事公開

参考

QEMUの設定関連

Ubuntu-base関連

initramfs関連

rootfs関連

*1:今回はQEMUで起動させているので、恩恵は小さいが

*2:ポートフォワーディングやブリッジ接続をすれば、ここも@変えることはできる