CLOVER🍀

That was when it all began.

vagrant-libvirtでSynced Foldersを使いたい

これは、なにをしたくて書いたもの?

自分はUbuntu Linux上でVagrantを使っていて、VagrantのProviderにはvagrant-libvirtを使っています。

Providers | Vagrant by HashiCorp

GitHub - vagrant-libvirt/vagrant-libvirt: Vagrant provider for libvirt.

Synced Foldersについてはあまり使っていなかったので困っていなかったのですが、ちょっと使いたいことが出てきたので
調べてみることにしました。

実は以前に軽く見ているのですが、その時はさらっと流してしまったんですよね。

vagrant-libvirtを使って仮想マシンを起動した時に、NFSが使えない場合にエラーになるのを回避する - CLOVER🍀

vagrant-libvirtとSynced Folders

vagrant-libvirtの、「Synced Folders」に関する記述を見てみます。

Synced Folders

以下の3つの方法が使えるようです。

  • NFS(デフォルト)
  • 9p
  • rsync

このうち、NFSはホスト側のサポートが必要になるので、ちょっと面倒…パスしたいです。

すると、9pかrsyncということになります。

vagrant-libvirtでホストとゲストの双方向のフォルダ同期が可能なのは、NFSと9pです。rsyncの場合は、起動時にホスト側から
ゲスト側に1度だけ同期されるものになります。

つまり、rsyncを選んだ場合は、ゲストOSの起動後に同期対象のフォルダをホスト側で変更しても、ゲスト側には反映されない
ということになります。実際、そうなります。

では、ちょっと試してみましょう。

環境。

$ vagrant --version
Vagrant 2.2.9


$ vagrant plugin list
vagrant-libvirt (0.0.45, global)
  - Version Constraint: > 0


$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 20.04.1 LTS
Release:    20.04
Codename:   focal


$ uname -srvmpio
Linux 4.15.0-112-generic #113-Ubuntu SMP Thu Jul 9 23:41:39 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux

まずは仮想マシンを作成しておきます。

$ vagrant init generic/ubuntu2004

rsync

まずは、rsyncを使ってみます。

Vagrantfileに、以下を追加します。

  config.vm.synced_folder "./", "/vagrant", type: "rsync"

コメントアウトされているSynced Foldersの定義があるので、このあたりに追加するのがいいでしょう。

  # Share an additional folder to the guest VM. The first argument is
  # the path on the host to the actual folder. The second argument is
  # the path on the guest to mount the folder. And the optional third
  # argument is a set of non-required options.
  # config.vm.synced_folder "../data", "/vagrant_data"

起動。

$ vagrant up

最後に、こんなメッセージが表示されます。

==> default: Rsyncing folder: /path/to/ => /vagrant

仮想マシンに入ってみましょう。

$ vagrant ssh

今回の設定では、「/vagrant」ディレクトリにSynced Folderで設定したディレクトリの中身が見えています。

$ ll /vagrant
total 12
drwxrwxr-x  2 vagrant vagrant 4096 Sep 10 08:50 ./
drwxr-xr-x 20 root    root    4096 Sep 10 08:51 ../
-rw-rw-r--  1 vagrant vagrant 3082 Sep 10 08:49 Vagrantfile

ここで、ホスト側で同期対象のディレクトリ上でファイルを作成してみます。

$ echo 'Hello World' > test.txt

ゲスト側には、反映されません。

$ ll /vagrant
total 12
drwxrwxr-x  2 vagrant vagrant 4096 Sep 10 08:50 ./
drwxr-xr-x 20 root    root    4096 Sep 10 08:51 ../
-rw-rw-r--  1 vagrant vagrant 3082 Sep 10 08:49 Vagrantfile

これを反映させたかったら、以下を実行。

$ vagrant reload

単純なOS再起動(「sudo reboot」など)ではダメです。

そもそも、ファイルシステムとしてマウントされているわけでもないですからね。

$ df -hT
Filesystem     Type      Size  Used Avail Use% Mounted on
udev           devtmpfs  951M     0  951M   0% /dev
tmpfs          tmpfs     199M  664K  199M   1% /run
/dev/vda3      ext4      124G  2.1G  115G   2% /
tmpfs          tmpfs     994M     0  994M   0% /dev/shm
tmpfs          tmpfs     5.0M     0  5.0M   0% /run/lock
tmpfs          tmpfs     994M     0  994M   0% /sys/fs/cgroup
/dev/vda1      ext4      456M  102M  321M  25% /boot
tmpfs          tmpfs     199M     0  199M   0% /run/user/1000

9p(Plan 9 Filesystem Protocol)

続いては、9pです。

これは、KVM環境でのVirFS(準仮想ファイルシステム)として機能します。

VirtFS - KVM

9p自体は、こちらを参照。

9P - Wikipedia

9p virtio - KVM

Documentation/9psetup - QEMU

9pを使ったファイルシステムを使うには、ゲスト側のサポートが必要になります。よって、利用できない状況もあるかも
しれません。

vagrant-libvirtのドキュメントでは、以下のどちらかを使え、と書いてあります。

  config.vm.synced_folder './', '/vagrant', type: '9p', disabled: false, accessmode: "squash", owner: "1000"

  # or

  config.vm.synced_folder './', '/vagrant', type: '9p', disabled: false, accessmode: "mapped", mount: false

違いはなんでしょう?

まず「mount: false」となっている場合は、起動時にマウントが行われません。

ownerは、文字通り所有者のuidを記述しています。1000は、vagrantユーザーのuidです。

accessmodeとは?

こちらを見るのが良さそうです。

21.16.2. ファイルシステム Red Hat Enterprise Linux 6 | Red Hat Customer Portal

passthrough - ゲスト仮想マシン内から設定されるユーザーのアクセス権でソースがアクセスされることを指定します。これは、いずれも指定されていない場合にデフォルトの accessmode になります。

mapped - ソースがハイパーバイザーのアクセス権でアクセスされることを指定します。

squash - 'passthrough' に似ていますが、例外は、chown のような権限による操作の失敗が無視されることです。これにより、ハイパーバイザーを root 以外で実行するユーザーにとって、passthrough のようなモードを使いやすいものとします。

squash、passthroughはゲスト側のユーザーが中心になり、mappedはホスト側の権限が中心になる、ということですね。

確認してみましょう。

こちらから。

  config.vm.synced_folder './', '/vagrant', type: '9p', disabled: false, accessmode: "squash", owner: "1000"

起動時には、こんな表示が出ます。

==> default: Should be mounting folders
==> default:  /vagrant, opts: {:disabled=>false, :guestpath=>"/vagrant", :hostpath=>"/path/to", :type=>:"9p", :accessmode=>"squash", :owner=>"1000", :__vagrantfile=>true, :target=>"/vagrant", :mount=>true, :readonly=>nil, :mount_tag=>"a68e78e76b9b38fcd41945093f0dfb1"}

仮想マシンにSSHで入って、マウントしているファイルシステムを見てみましょう。

$ df -hT
Filesystem                      Type      Size  Used Avail Use% Mounted on
udev                            devtmpfs  951M     0  951M   0% /dev
tmpfs                           tmpfs     199M  668K  199M   1% /run
/dev/vda3                       ext4      124G  2.1G  115G   2% /
tmpfs                           tmpfs     994M     0  994M   0% /dev/shm
tmpfs                           tmpfs     5.0M     0  5.0M   0% /run/lock
tmpfs                           tmpfs     994M     0  994M   0% /sys/fs/cgroup
/dev/vda1                       ext4      456M  102M  321M  25% /boot
a68e78e76b9b38fcd41945093f0dfb1 9p        269G  244G   12G  96% /vagrant
tmpfs                           tmpfs     199M     0  199M   0% /run/user/1000

「/vagrant」が「9p」ファイルシステムでマウントされています。

確認。

$ ll /vagrant/
total 16
drwxrwxr-x  3 vagrant vagrant 4096 Sep 10 09:35 ./
drwxr-xr-x 20 root    root    4096 Sep 10 08:51 ../
drwxrwxr-x  5 vagrant vagrant 4096 Sep 10 08:50 .vagrant/
-rw-rw-r--  1 vagrant vagrant 3192 Sep 10 09:35 Vagrantfile

ホスト側でファイルを作ってみます。

$ echo 'Hello World' > test.txt

すると、ゲスト側にも表示されます。

$ ll /vagrant/
total 20
drwxrwxr-x  3 vagrant vagrant 4096 Sep 10 09:37 ./
drwxr-xr-x 20 root    root    4096 Sep 10 08:51 ../
-rw-rw-r--  1 vagrant vagrant   12 Sep 10 09:37 test.txt
drwxrwxr-x  5 vagrant vagrant 4096 Sep 10 08:50 .vagrant/
-rw-rw-r--  1 vagrant vagrant 3192 Sep 10 09:35 Vagrantfile


$ cat /vagrant/test.txt 
Hello World

ただ、ここにファイルは作れなさそうですね。

$ mkdir /vagrant/dir
mkdir: cannot create directory ‘/vagrant/dir’: Permission denied


$ sudo mkdir /vagrant/dir
mkdir: cannot create directory ‘/vagrant/dir’: Operation not permitted

ホスト側から、緩いディレクトリを作ってみます。

$ mkdir dir

$ chmod 777 dir

確認。

$ ll /vagrant/
total 24
drwxrwxr-x  4 vagrant vagrant 4096 Sep 10 09:38 ./
drwxr-xr-x 20 root    root    4096 Sep 10 08:51 ../
drwxrwxrwx  2 vagrant vagrant 4096 Sep 10 09:38 dir/
-rw-rw-r--  1 vagrant vagrant   12 Sep 10 09:37 test.txt
drwxrwxr-x  5 vagrant vagrant 4096 Sep 10 08:50 .vagrant/
-rw-rw-r--  1 vagrant vagrant 3192 Sep 10 09:35 Vagrantfile

ゲスト側から見えます。

書き込んでみましょう。

$ echo 'from Guest' > /vagrant/dir/hello.txt

これならうまくいきました。

権限を見てみると、こんな感じに。

$ ll /vagrant/dir
total 12
drwxrwxrwx 2 vagrant vagrant 4096 Sep 10 09:39 ./
drwxrwxr-x 4 vagrant vagrant 4096 Sep 10 09:38 ../
-rw-rw-r-- 1   64055     127   11 Sep 10 09:39 hello.txt

ホスト側から見ると、こうなっています。

$ ls -l dir
合計 4
-rw-rw-r-- 1 libvirt-qemu kvm 11  9月 10 18:39 hello.txt

ゲスト側からも書き込めることは、確認できましたね。

1度、ホスト側からファイルやディレクトリを削除。

$ rm test.txt
$ rm -rf dir

最後に、こちらを確認してみます。

  config.vm.synced_folder './', '/vagrant', type: '9p', disabled: false, accessmode: "mapped", mount: false
==> default: Should be mounting folders
==> default:  /vagrant, opts: {:disabled=>false, :guestpath=>"/vagrant", :hostpath=>"/path/to", :type=>:"9p", :accessmode=>"mapped", :mount=>false, :__vagrantfile=>true, :target=>"/vagrant", :readonly=>nil, :mount_tag=>"a68e78e76b9b38fcd41945093f0dfb1"}

仮想マシンにSSHで入ってみると、ディレクトリはマウントされていません。

$ df -hT
Filesystem     Type      Size  Used Avail Use% Mounted on
udev           devtmpfs  951M     0  951M   0% /dev
tmpfs          tmpfs     199M  660K  199M   1% /run
/dev/vda3      ext4      124G  2.1G  115G   2% /
tmpfs          tmpfs     994M     0  994M   0% /dev/shm
tmpfs          tmpfs     5.0M     0  5.0M   0% /run/lock
tmpfs          tmpfs     994M     0  994M   0% /sys/fs/cgroup
/dev/vda1      ext4      456M  102M  321M  25% /boot
tmpfs          tmpfs     199M     0  199M   0% /run/user/1000

これは、「mount: false」にしてあるからですね。起動時にマウントされないのです。

マウントしましょう。起動時に表示されている、「:mount_tag=>"a68e78e76b9b38fcd41945093f0dfb1"」という「mount_tag」の
値を使います。

$ sudo mount -t 9p a68e78e76b9b38fcd41945093f0dfb1 /vagrant

マウントするファイルシステムの種類は、9pです。

見えるようになりました。

$ df -hT
Filesystem                      Type      Size  Used Avail Use% Mounted on
udev                            devtmpfs  951M     0  951M   0% /dev
tmpfs                           tmpfs     199M  660K  199M   1% /run
/dev/vda3                       ext4      124G  2.1G  115G   2% /
tmpfs                           tmpfs     994M     0  994M   0% /dev/shm
tmpfs                           tmpfs     5.0M     0  5.0M   0% /run/lock
tmpfs                           tmpfs     994M     0  994M   0% /sys/fs/cgroup
/dev/vda1                       ext4      456M  102M  321M  25% /boot
tmpfs                           tmpfs     199M     0  199M   0% /run/user/1000
a68e78e76b9b38fcd41945093f0dfb1 9p        269G  244G   12G  96% /vagrant

先ほどと同じように、ホスト側でファイルやディレクトリを作っておきます。
※ゲスト側から「/vagrant」ディレクトリにファイル等が作れないのは同じだったので

$ echo 'Hello World' > test.txt
$ mkdir dir
$ chmod 777 dir

ゲスト側からの書き込み。

$ echo 'from Guest' > /vagrant/dir/hello.txt

ゲスト側からは、こんな感じに見えます。

$ ll /vagrant
total 24
drwxrwxr-x  4 vagrant vagrant 4096 Sep 10 09:48 ./
drwxr-xr-x 20 root    root    4096 Sep 10 08:51 ../
drwxrwxrwx  2 vagrant vagrant 4096 Sep 10 09:48 dir/
-rw-rw-r--  1 vagrant vagrant   12 Sep 10 09:47 test.txt
drwxrwxr-x  5 vagrant vagrant 4096 Sep 10 08:50 .vagrant/
-rw-rw-r--  1 vagrant vagrant 3303 Sep 10 09:44 Vagrantfile


$ ll /vagrant/dir
total 16
drwxrwxrwx 2 vagrant vagrant 4096 Sep 10 09:48 ./
drwxrwxr-x 4 vagrant vagrant 4096 Sep 10 09:48 ../
-rw-rw-r-- 1 vagrant vagrant   11 Sep 10 09:48 hello.txt

一方、ホスト側からはこう見えます。

$ ls -l dir
合計 8
-rw------- 1 libvirt-qemu kvm 11  9月 10 18:48 hello.txt

違いは、ゲスト側から見た時の、ゲスト側で作ったファイルの所有者ですね。

$ ll /vagrant/dir
total 12
drwxrwxrwx 2 vagrant vagrant 4096 Sep 10 09:39 ./
drwxrwxr-x 4 vagrant vagrant 4096 Sep 10 09:38 ../
-rw-rw-r-- 1   64055     127   11 Sep 10 09:39 hello.txt


$ ll /vagrant/dir
total 16
drwxrwxrwx 2 vagrant vagrant 4096 Sep 10 09:48 ./
drwxrwxr-x 4 vagrant vagrant 4096 Sep 10 09:48 ../
-rw-rw-r-- 1 vagrant vagrant   11 Sep 10 09:48 hello.txt

ホスト側から見た時は変わらないのですが。

ちなみに、最後に試した設定でも

  config.vm.synced_folder './', '/vagrant', type: '9p', disabled: false, accessmode: "mapped", mount: true

というように「mount: true」としていれば、起動時にディレクトリをマウントしてくれます。

ただ、極力「squash」の方を使った方がいいんでしょうね。