Edited at

Mac上のNFSをasync書き込み許可してVagrantを爆速にする - NFS of Vagrant on the Mac to detonation velocity share folder

More than 3 years have passed since last update.

2015-04-29 更新

VMWareをお持ちであれば、Mac上のdockerでVMWareのネイティブフォルダシェアが実現した話をどうぞ。


まえおき

業務で実際に仮想環境としてよく使われるようになったVagrant,Macでのローカルのファイル同期はnfsを使うのが一般的だと思いますが,そのnfsの設定を変更して,Vagrantを爆速にする話.

手元の環境では,大体2倍の速度が出ています.

大体はタイトルの通りasyncを効かせるんですが,日本国内でVagrantに適応している情報がなかったので,書いておきます.

結構単純なのにあまり情報がないのと,計測方法が分からないので,実はプラシーボなのかもしれません.そしたらすみません.

いちおう,コメントかtweet頂ければ,出来る限りお手伝いします.


注意

Vagrantの今の使用層を考えて,黒い画面が不慣れでも分かりやすいようにかなり冗長に書いているので,nfs早くするだけならtl;dr見てください.

nfsについて知識があるわけでなく,海外で見つけた情報を元にした記事です

/etc/を触る比較的コアな設定ですので,自己責任にて.

また,自分はいまDockerのためにしかVagrantを使用していない( Mac -> Vagrant -> boot2docker -> Docker )ので,通常のVagrant運用でどうかは試していません.

気が向いたら.

また、サーバーとかクライアントとか言うと,VagrantでのそれとSSHでのそれとでは意味が少しだけ違ってきて分かりづらくなるので,ここぞという時にしか極力使わないようにします.

併せて,Vagrant記事では基本的にどっちで(Mac側なのかVagrant内のLinux等なのか)コマンド打っているか分かりづらいので,

Macであれば mac$ sudo vi hoge

Vagrantであれば vagrant$ sudo vi hoge

で統一します.


緩募


  • Vagrantとのnfs接続速度をbonnie++などで計る方法

  • 普通にUbuntuなどをVagrantで立ち上げた時の動作確認


tl;dr

On Mac,

mac$ sudo vi /etc/nfs.conf


mac$nfs.conf

nfs.server.async=1

nfs.server.verbose=3
nfs.server.nfsd_threads=512
nfs.server.tcp=1
nfs.server.verbose=3
nfs.server.wg_delay_v3=1
nfs.client.allow_async=1
nfs.client.nfsiod_thread_max=512
nfs.client.mount.options=async,nfsvers=3,mountvers=3,rsize=8192,wsize=8192,acdirmax=3600,soft,intr,tcp
nfs.statd.verbose=1

and, nfs daemon restart

mac$ sudo nfsd restart

check nfsd status,

mac$ sudo nfsd status


mac$sudo_nfsd_status_result

nfsd service is enabled

nfsd service is loaded
nfsd is running (pid 43918, 512 threads)
lockd service is enabled
lockd service is loaded
lockd is running (pid 278)
statd.notify service is enabled
statd.notify service is loaded
statd.notify is not running
statd service is loaded
statd is running (pid 279)
rquotad service is loaded
rquotad is running (pid 44194)

Your Vagrantfile,

mac$ vi Vagrantfile


mac$Vagrantfile

Vagrant.configure("2") do |config|

# ...
config.vm.synced_folder ".", "/vagrant", type: "nfs", mount_options: ["async", "nolock", "nfsvers=3", "vers=3", "tcp", "noatime", "soft", "rsize=8192", "wsize=8192"]
# ...
end

mac$ vagrant up

Done.


実現可能そうな環境


  • OS X 10.9 〜

  • Vagrant 1.7.2(2015/04/17 最新)

  • VirtualBox・Parallels Desktop(VMWareは使える環境ですが試していません)


実際動いてる,手元の環境

Mac (RubyMine etc...) -> Vagrant -> boot2docker -> Docker


  • OS X Yosemite 10.10.3

  • Vagrant 1.7.2

  • Parallels Desktop 10.2.0 (28956)

  • boot2docker 1.6(今朝でましたね)

  • Docker 1.6(今朝でましたね)


いつものVagrantfile

通常nfs設定を有効にするVagrantfileの設定は,

http://docs.vagrantup.com/v2/synced-folders/nfs.html


Vagrantfile

Vagrant.configure("2") do |config|

# ...

config.vm.synced_folder ".", "/vagrant", type: "nfs"
# ...
end


typeでnfsを指定することにより,nfsで共有可能になります.

これだけで通常のVirtualbox共有などより早くなるのは周知の事実ですね.Qiitaでもメモされている方がいっぱいいらっしゃいます.

この設定でmac$ vagrant upすると,Mac側の/etc/exportsに共有するフォルダ情報が書き込まれ,Macをサーバーとして,daemonを立ち上げnfs共有が開始され,Vagrantで立ち上げたOSにマウントされます.(あってる?)

具体的に/etc/exportsを見てみましょう.

mac$ cat /etc/exports

# VAGRANT-BEGIN: 501 5c******-c***-4684-8e21-35289a3c****

"/vagrant" "/path/in/dir" 10.211.55.33 -alldirs -mapall=501:20
# VAGRANT-END: 501 5c******-c***-4684-8e21-35289a3c****

想像で書いたので実際と違うかもしれませんが./path/in/dir10.211.55.33はそれぞれ皆さんの環境によって違い,-alldirs -mapall=501:20はもしかしたら普通は書いてないかもしれません.

ともかく,Macでnfs daemonを立ち上げているので,Vagrantの裏設定の闇に入らずとも,少しはMac側でカジュアルにいろいろと設定できそうな雰囲気がしてきます.


/etc/nfs.conf

Macでのnfs daemonの設定は./etc/nfs.confに記述します.

デフォルトでは,空のファイルだったかコメントがあるのみだったかと思います.

そこに,async(非同期)書き込みを許可する設定をします.

vimSublime Text(いまVagrant触ってるフロントエンドの人はSublime多そうな気がする.そしてThemeはSeti_UIな気がする.作者のctf0はいい人)でnfs.confを開きます.

ただ,/etc/内なので管理者権限が必要ですので,vimならsudoを付け,Sublimeの保存時にMacのパスワードを入れて保存してください.

mac$ sudo vi /etc/nfs.conf


mac$nfs.conf

nfs.server.async=1

nfs.server.verbose=3
nfs.server.nfsd_threads=512
nfs.server.tcp=1
nfs.server.verbose=3
nfs.server.wg_delay_v3=1
nfs.client.allow_async=1
nfs.client.nfsiod_thread_max=512
nfs.client.mount.options=async,nfsvers=3,mountvers=3,rsize=8192,wsize=8192,acdirmax=3600,soft,intr,tcp
nfs.statd.verbose=1

Screenshot 2015-04-18 00.40.41.png

大体設定内容は見ればわかりそうな感じです.

詳しくは記事下部にあるリンク,apple manpageを見てください.


nfs.server.async=1

async書き込み許可する.

デフォルトは0(許可しない)


nfs.server.verbose=3

nfsログをDEBUGモードにする.

デフォルトは0.


nfs.server.nfsd_threads=512

nfsスレッドを設定数に変更する

たぶんこれは多すぎます.Redhatのサイトとかだと20指定していました.

Macデフォルトは8.


nfs.server.tcp=1

nfsでのTCPを許可する.

デフォルトでも1.


nfs.server.wg_delay_v3=1

ちょっとよく覚えてませんが,設定するとオーバーヘッドが減るらしいです.

デフォルトは0.


nfs.client.***

nfs.client以下は.Macがserverにあたるのであまり意味がないように思いますが,後述するVagrantfileへの設定を,実は書かなくても自動でやってくれるんじゃないかという期待を胸に一応書いています.

ただ,試していません.

現状動いているので,試すよりRails書いてたいです.


nfsd restart

Macのnfs daemonを再起動して,設定を反映させましょう.

Macの場合は,以下で再起動できます.

mac$ sudo nfsd restart

何も表示されずに終わります.

不安なのでstatusをチェックします.

mac$ sudo nfsd status


mac$sudo_nfsd_status_result

nfsd service is enabled

nfsd service is loaded
nfsd is running (pid 43918, 512 threads)
lockd service is enabled
lockd service is loaded
lockd is running (pid 278)
statd.notify service is enabled
statd.notify service is loaded
statd.notify is not running
statd service is loaded
statd is running (pid 279)
rquotad service is loaded
rquotad is running (pid 44194)

Screenshot 2015-04-18 00.39.05.png

指定したスレッド数になっています.

それでも不安であれば,nfs.confのスレッドの数値を変更してrestartしましょう.

nfsd is runningが変化するはずです.


再度Vagrantfile

Mac側でasyncの設定を許可したので,クライアント側でもasyncを設定します.

ついでにprivate_networkも指定しましょう.特にDockerならあとで色々と楽です.

Vagrant自体がbuggyで何度もyakを刈っていたので嫌になり,今はDockerしか使っていないのなんとも言えませんが,原理的には,


Vagrantfile

Vagrant.configure("2") do |config|

# ...
config.vm.network 'private_network', ip: '192.168.55.33'
config.vm.synced_folder ".", "/vagrant", type: "nfs", mount_options: ["async", "nolock", "nfsvers=3", "vers=3", "tcp", "noatime", "soft", "rsize=8192", "wsize=8192"]
# ...
end

で良さそうな感じです.

動作確認している自分のVagrantfile


Vagrantfile

Vagrant.configure("2") do |config|

# ...
config.vm.network 'private_network', ip: '192.168.55.33'
config.vm.synced_folder ".", Dir.pwd, type: "nfs", mount_options: ["async", "nolock", "nfsvers=3", "vers=3", "tcp", "noatime", "soft", "rsize=8192", "wsize=8192"]
config.vm.synced_folder "/Users", "/Users", type: "nfs", mount_options: ["async", "nolock", "nfsvers=3", "vers=3", "tcp", "noatime", "soft", "rsize=8192", "wsize=8192"]
# ...
end

最初の設定と違い,かつ/Users以下すべてを共有する設定になっているのは,この設定がboot2docker用だからです.

お察しください.

ちなみにVagrantのデフォルトmount_optionsは

https://github.com/mitchellh/vagrant/search?utf8=%E2%9C%93&q=mount_options&type=Code

から適当に追ってください


Vagrant up

これでvagrant upをすれば,幾分普通に起動したときより早いはずです.


ベンチマーク

する方法がよく分からなくて困ってます.教えていただけると嬉しいです.

pythonサーバー建ててwrkで計測したりしましたが,単純な書き込み速度テストじゃない気がします.

bonnie++をDocker内で走らせてみましたが,なんか違う感じ.

本来はクライアントからnfsでマウントしてる/mntとかにbonnie++する気がするんですが,どこにあるか分からない.


体感

最初にも書きましたが,自分の環境では

Mac -> Vagrant -> boot2docker -> Docker

でnfsを効かせて接続しています.

すごいニッチですが,RubyMineでbundle installした際にSSHでMac側にgemをsyncするんですが,それが爆速になりました.

あとは,Dockerでdocker pullも早くなってます.


yak shaving

もしかしたら,他のVagrantを起動しようとしたときに/etc/exporsのPermission errorが起きるかもしれない.

その場合,

mac$ sudo rm -rf /etc/exports

mac$ sudo touch /etc/exports


終わりに

次はMacのboot2dockerでnfs使って動作を早くする方法

その後にRubyMineを使ってDocker上でRails開発する方法と,chown問題を書きたいと思います.


参考

nfsd(8)

https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man8/nfsd.8.html

nfs.conf(5)

https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man5/nfs.conf.5.html

mount(8)

https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man8/mount.8.html