CUBE SUGAR CONTAINER

技術系のこと書きます。

Multipass を使って Apple Silicon 版の Mac で Ubuntu の仮想マシンを扱う

Apple Silicon (M1) の載った Mac mini を購入してからというもの、ローカルで仮想マシンを手軽に立ち上げる方法を模索している。 Intel 版の Mac であれば Vagrant + VirtualBox を使っていたけど、残念ながら VirtualBox は ISA が x86 / amd64 のシステムでしか動作しない。 Docker for Mac も使っているけど、コンテナではなく仮想マシンが欲しいという状況も往々にしてある。 そんな折、Multipass を使うとデフォルトではゲスト OS が Ubuntu に限られる 1 ものの、Vagrant 並に仮想マシンを手軽に扱えることがわかった。 今回は、そんな Multipass の使い方について書いてみる。

multipass.run

使った環境は次のとおり。

$ sw_vers
ProductName:    macOS
ProductVersion: 12.0.1
BuildVersion:   21A559
$ uname -m
arm64
$ sysctl machdep.cpu.brand_string
machdep.cpu.brand_string: Apple M1
$ multipass version                        
multipass   1.8.1+mac
multipassd  1.8.1+mac

もくじ

Multipass とは

Multipass は、Ubuntu の開発をしている Canonical 社が提供しているツール。 Windows, Linux, macOS それぞれのプラットフォームで、同じ操作感で Ubuntu の仮想マシンを扱うことができる。 操作は基本的に CUI (Character User Interface) で実施する。

バックエンドのハイパーバイザとして、各 OS のネイティブなフレームワークを利用できる点が特徴的。 たとえば、デフォルトだと Windows であれば Hyper-V 2、macOS だとHyperKit 3、Linux は QEMU/KVM が使える。

下準備

Multipass は Homebrew を使ってインストールできる。

$ brew install --cask multipass

インストールすると multipass コマンドが使えるようになる。

$ multipass version                        
multipass   1.8.1+mac
multipassd  1.8.1+mac

仮想マシンを起動する

仮想マシンを起動するには multipass launch コマンドを使う。 --name オプションを使うと仮想マシンに名前をつけられる。 ここでは focal という名前をつけた。 また、末尾には Ubuntu のバージョン番号を指定する。 バージョン番号を省略した場合には、最新の LTS (Long Term Support) リリースが使われるらしい。

$ multipass launch --name focal 20.04

初回の起動時にはイメージのダウンロードや検証が入るので、少し時間がかかる。

なお、指定できるバージョン番号 (ディストリビューション) は multipass find コマンドで確認できる。

$ multipass find
Image                       Aliases           Version          Description
18.04                       bionic            20211109         Ubuntu 18.04 LTS
20.04                       focal,lts         20211108         Ubuntu 20.04 LTS
21.04                       hirsute           20211110         Ubuntu 21.04
21.10                       impish            20211103         Ubuntu 21.10
anbox-cloud-appliance                         latest           Anbox Cloud Appliance
minikube                                      latest           minikube is local Kubernetes

起動が終わると multipass ls コマンド (または multipass list) に仮想マシンが表示されるようになる。

$ multipass ls                       
Name                    State             IPv4             Image
focal                   Running           192.168.64.2     Ubuntu 20.04 LTS

仮想マシンのより詳しい情報は multipass info コマンドで確認できる。 デフォルトでは 1GB のメモリと 5GB のディスクが割り当てられるらしい。

$ multipass info focal
Name:           focal
State:          Running
IPv4:           192.168.64.2
Release:        Ubuntu 20.04.3 LTS
Image hash:     a83b747df657 (Ubuntu 20.04 LTS)
Load:           0.62 0.22 0.08
Disk usage:     1.2G out of 4.7G
Memory usage:   135.6M out of 974.8M
Mounts:         --

仮想マシンに割り当てる CPU やメモリ、ディスクの容量などは起動時にカスタマイズできる。 具体的には multipass launch コマンドで --cpus--mem--disk といったオプションを指定すれば良い。 詳細は multipass launch --help から確認できる。

仮想マシンでコマンドを実行する

起動した仮想マシンでは、multipass exec コマンドを使ってコマンドが実行できる。 仮想マシンの名前と、ハイフンを 2 つはさんで実行したいコマンドを指定しよう。

$ multipass exec focal -- lsb_release --description
Description:    Ubuntu 20.04.3 LTS
$ multipass exec focal -- uname -m                 
aarch64

仮想マシンの ISA も、ちゃんと aarch64 になっている。

また、multipass shell コマンドを使えばシェルにログインできる。

$ multipass shell focal                            
Welcome to Ubuntu 20.04.3 LTS (GNU/Linux 5.4.0-90-generic aarch64)

... (snip) ...

ubuntu@focal:~$ 

通常はこちらを使って操作することになりそうだ。

仮想マシンを停止・再開・削除する

仮想マシンを停止するには multipass stop コマンドを使う。 ちなみに -t オプションを使えば分単位で停止するタイミングを遅らせることもできる。

$ multipass stop focal
$ multipass ls           
Name                    State             IPv4             Image
focal                   Stopped           --               Ubuntu 20.04 LTS

同様に、再開するときは multipass start コマンドを使う。

$ multipass start focal
$ multipass ls
Name                    State             IPv4             Image
focal                   Running           192.168.64.2     Ubuntu 20.04 LTS

仮想マシンを削除するときは multipass delete コマンドを使う。 ただし、この時点では完全に削除されてはいない。

$ multipass delete focal
$ multipass ls          
Name                    State             IPv4             Image
focal                   Deleted           --               Not Available

Deleted な状態であれば、まだ multipass recover コマンドで復旧できる。

$ multipass recover focal
$ multipass ls           
Name                    State             IPv4             Image
focal                   Stopped           --               Ubuntu 20.04 LTS
$ multipass start focal
$ multipass exec focal -- lsb_release --description
Description:    Ubuntu 20.04.3 LTS

仮想マシンを完全に削除するには、multipass delete した後に multipass purge する。 これで Deleted な状態の仮想マシンが完全に削除される。

$ multipass delete focal
$ multipass purge
$ multipass ls   
No instances found.

次の検証に移る前に、削除してしまった仮想マシンを作り直しておこう。

$ multipass launch --name focal 20.04

ホスト OS のストレージをゲスト OS でマウントして使う

Multipass にはホスト OS のストレージをゲスト OS でマウントする機能がある。 この機能は両者でファイルを共有するときに有用。

機能を使うときは multipass mount コマンドを使う。 このコマンドは次のような書式になっている。

$ multipass mount <source> <target>

ここで、<target><vm-name><vm-name>:<path> の指定ができる。 :<path> を省略すると <source> と同じパスでマウントしようとする。 試しにカレントディレクトリをマウントしてみよう。 動作確認用にファイルを作っておく。

$ echo "Hello, World" > greet.txt
$ ls
greet.txt

カレントディレクトリを指定して仮想マシンにマウントする。 ・・・が、これは指定するパスにもよるけど次のようなエラーになる恐れがある。

$ multipass mount $(pwd) focal:/mnt
mount failed: source "/Users/amedama/Documents/temporary/multipass" is not readable

上記のエラーは macOS の設定に起因している。 というのも、デフォルトでは Multipass に $HOME 以下の任意のディレクトリはアクセスが許可されていない。

このエラーを解消するには「システム環境設定 > セキュリティとプライバシー > プライバシー > フルディスクアクセス」を選択して、multipassd にチェックを入れる必要がある。 もちろん、これはセキュリティ保護に関係ないパスを使っていれば問題にはならない。

操作した上で、改めてマウントを試みると今度はエラーにならず成功する。

$ multipass mount $(pwd) focal:/mnt

マウントすると、次のようにちゃんと仮想マシンからホスト OS のディレクトリが見られるようになっている。

$ multipass exec focal -- ls /mnt
greet.txt
$ multipass exec focal -- cat /mnt/greet.txt
Hello, World

ゲスト OS がマウントしている情報は multipass info コマンドから確認できる。

$ multipass info focal                      
Name:           focal
State:          Running
IPv4:           192.168.64.3
Release:        Ubuntu 20.04.3 LTS
Image hash:     a83b747df657 (Ubuntu 20.04 LTS)
Load:           0.07 0.05 0.03
Disk usage:     1.2G out of 4.7G
Memory usage:   150.5M out of 974.8M
Mounts:         /Users/amedama/Documents/temporary/multipass => /mnt
                    UID map: 501:default
                    GID map: 20:default

マウントを解除したいときは multipass umount コマンドを使えば良い。

$ multipass umount focal

Multipass の設定を読み書きする

Multipass の設定は multipass get コマンドと multipass set コマンドで読み書きできる。 設定項目自体は multipass help get コマンドから確認できる。

たとえばバックエンドのハイパーバイザは local.driver という設定項目になっている。 Apple Silicon の Mac では、デフォルトで QEMU が使われているようだ。

$ multipass get local.driver
qemu

設定は multipass set コマンドを使って <key>=<value> 形式で書きかえられる。 試しに local.driverhyperkit に切り替えてみようとすると、無効なドライバだとエラーになってしまった。

$ multipass set local.driver=hyperkit
Invalid setting 'local.driver=hyperkit': Invalid driver

ちなみに Intel 版の Mac であれば、デフォルトでは以下のように hyperkit が使われていた。

$ sw_vers                        
ProductName:    macOS
ProductVersion: 12.0.1
BuildVersion:   21A559
$ uname -m
x86_64
$ multipass version   
multipass   1.8.1+mac
multipassd  1.8.1+mac
$ multipass get local.driver
hyperkit

試しに上記 Intel 版の環境を使って、バックエンドを VirtualBox に変更してみよう。

$ brew install --cask virtualbox
$ multipass set local.driver=virtualbox

設定を変更すると Multipass のデーモンが再起動する。 再起動が終わらないうちに操作しようとすると、次のようなエラーになる。

launch failed: cannot connect to the multipass socket                           
Please ensure multipassd is running and '/var/run/multipass_socket' is accessible

少し待つと、ちゃんと使えるようになる。 バックエンドを切りかえた上で、試しに Ubuntu 18.04 LTS を起動してみよう。

$ multipass launch --name bionic 18.04

VBoxManage list vms コマンドで確認すると、ちゃんと VirtualBox 上で仮想マシンが立ち上がっているようだ。 ちなみに sudo をつけていることからわかるようにスーパーユーザで実行されている。

$ sudo VBoxManage list vms
"bionic" {afb0cdcb-fbd2-4d01-9310-4abd63fa2b9d}

ゲスト OS 上で IP アドレスを確認すると 、10.0.2.15/24 と、たしかに VirtualBox っぽいアドレスが振られている。

$ multipass exec bionic -- ip address show | grep inet
    inet 127.0.0.1/8 scope host lo
    inet6 ::1/128 scope host 
    inet 10.0.2.15/24 brd 10.0.2.255 scope global dynamic enp0s3
    inet6 fe80::5054:ff:fe0e:1caa/64 scope link 

バックエンドを元に戻したいときは、また HyperKit を使うように local.driver を設定すれば良い。

$ sudo multipass set local.driver=hyperkit

まとめ

Multipass を使うことで、Apple Silicon 版の Mac であっても、デフォルトでゲスト OS は Ubuntu に限られるものの簡単に仮想マシンを扱えることがわかった。 最近は、仮想マシンを立ち上げたいときが大体 Ubuntu を動かしたいときとほぼイコールだったので、ひとまず自分的にはこれで十分かもしれない。 IaaS のインスタンスを立ち上げて使うほどでもないくらいの簡単な検証がローカルでやりやすくなるのは嬉しい。


  1. 自分でイメージを作ることもできるらしい。

  2. ただし、利用できる Windows のエディションやバージョンには制約があるようだ。

  3. 裏側で Hypervisor.framework が動作する。なお、Apple Silicon ではデフォルトで QEMU が使われるようだ。