EC2⇔WindowsServerでNFSる

## 先に結論
めんどい！EFSを使おう！！


## なぜEFSでなく、NFS？
NFSなんぞ使わず、EFSやら何かしらのマネージド使えばええやん…となるが、実現するとなると下記問題が生じた。

 - EFS  
    - そもそもEFSはNFSを包括したサービスらしい  
    - WindowsServer2012に標準搭載されているNFSクライアントはv3だが、EFSはNFSv4でないと使用できない
    - それでも非公式のNFSクライアント導入することで<a href="https://qiita.com/zakky/items/b0c4df1ee7cb75830186">使えるっぽい</a>
        - この方法だと、Windows側からLinux側へファイルを書き込めないらしい
        - 自環境で動作しなかった → 今思い返すと、色々設定忘れがあった気がするし、ここをきちんと動作確認すべきだった…
 - FSx
    - NFSクライアントのバージョンに関係なく使用できるとのことだが、コスト高になりそう
 - StorageGateway
    - 推奨インスタンスタイプが `m4.xlarge` や推奨EBSサイズが `150GB` と貴族でないとやっていられなそう


これらの問題からNFSを使用することに。。。


## 環境構成
実現するにあたって、構成は下図のイメージ。
![Untitled Diagram(2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531023/3bd69819-1ef1-9e8b-2fd1-f3777b193ff2.png)
Linux側では、 `/linux-dir` を操作ディレクトリとし、Windows側では、 `Z:\\windows-dir` が操作ディレクトリとなる。
`/windows-dir` やら `fuse-convmvfs` については後述。


## 検証環境
Linux(NFS-Server) `Amazon Linux AMI release 2018.03`
Windows(NFS-Client) `WindowsServer 2012 R2`


## NFSサーバ(AmazonLinux)側の設定
### nfs-utilsのチェック  
AmazonLinuxであれば標準でnfs-utilsがインストールされているはず。
されていない場合は、 `yum install nfs-utils` でインストールする。

### NFSで使用されるポート番号の固定
- [ここを参考に](https://hacknote.jp/archives/2018/)
- `/etc/sysconfig/nfs` の以下コメントアウトを外す

```shell:/etc/sysconfig/nfs
# Port rquotad should listen on.
RQUOTAD_PORT=875
...
# TCP port rpc.lockd should listen on.
LOCKD_TCPPORT=32803
# UDP port rpc.lockd should listen on.
LOCKD_UDPPORT=32769
...
# Port rpc.mountd should listen on.
MOUNTD_PORT=892
...
# Port rpc.statd should listen on.
STATD_PORT=662
```

- `/etc/nfsmount.conf` の以下コメントアウトを外す  

```shell:/etc/nfsmount.conf
# Server Port
Port=2049
```
- AWS上のSecurityGroupで以下ポートのinboundを開放する
    - **TCP**: `111, 892, 2049, 32803`
    - **UDP**: `111, 892, 2049, 32769`

### NFSをサービスとして登録する
```shell
$ chkconfig rpcbind on
$ chkconfig nfs on
$ chkconfig nfslock on

$ service rpcbind start
$ service nfs start
$ service nfslock start
```

### /etc/exportsに共有情報を記述
WindowsServer側のIPアドレスがa.b.c.d/32とした場合、

```shell:/etc/exports
/windows-dir a.b.c.d/32(rw,fsid=1,sync,no_root_squash,no_all_squash)
```

なお、ここで `fsid=1` の記述が無いと以下エラーが出る場合がある

```
exportfs requires fsid= for nfs export
```

追記したら、以下を実行

```
$ exportfs -ar
```

↓で反映状態を確認し、 `/etc/exports` に記述した内容が表示されればOK

```
$ exportfs -v
```

### /etc/hosts.allow にNFSクライアントからのアクセスを許可する
```shell:/etc/hosts.allow
portmap: a.b.c.d/32
lockd: a.b.c.d/32
rquotad: a.b.c.d/32
mountd: a.b.c.d/32
statd: a.b.c.d/32
```

### fuse-convmvfsをビルド/インストールする
- [ここを参考に](http://electronekowd.blog.fc2.com/blog-entry-7.html)
- Linux⇔Windows間だと、文字エンコーディングの問題でファイル名が化けてしまう
- この問題をfuse-convmvfs(以下convmvfs)で解決する
- convmvfsとは、[こちらの記事](http://electronekowd.blog.fc2.com/blog-entry-7.html)によると以下の機能を持ったツールとなる。細かな導入作業については、この記事を参考にしてもらいたい

> ◆fuse-convmvfsってなんぞ？ 
fuseという、ファイルシステム単位でシンボリックリンクっぽいものを張る(暴論)機能をラッピングして、このエイリアスパスを通したときだけファイル名の変換を行うためのユーティリティ。

- つまるところ、 `/windows-dir` は特段触れないディレクトリとなる
- fuseは[ここ](https://github.com/libfuse/libfuse/releases)、fuse-convmvfsは[ここ](http://fuse-convmvfs.sourceforge.net/)からダウンロードする
- 当環境では、 `fuse-2.9.9` および `fuse-convmvfs-0.2.5` で動作を確認した

**1: fuseの導入**

```
$ tar -zxvf fuse-2.9.9.tar.gz fuse-2.9.9
$ cd fuse-2.9.9 && make
$ make install
```

**2: fuse.pcをpkg-configで読めるようにする**

```
# fuse.pcファイルを探す
$ find / -name fuse.pc

# 見つけたファイルが /usr/lib64/pkgconfig/ に存在しなければコピーする
$ cp /path/to/fuse.pc /usr/lib64/pkgconfig/

# 下記コマンドを実行し、同じ出力がでればOK
$ pkg-config --libs fuse
-pthread -L/usr/local/lib -lfuse
```

**3: fuse-convmvfsの導入**

```
$ tar -zxvf fuse-convmvfs-0.2.5.tar.gz fuse-convmvfs-0.2.5
$ cd fuse-convmvfs-0.2.5 && make
$ make install
```

**4: convmvfsの動作確認**

```
$ convmvfs --help
usage: convmvfs mountpoint [options]
...
```

### convmvfs用のマウントポイントを作成
構成図にも書いたが、Linux側で操作するディレクトリを `linux-dir`、WindowsServer側でマウントするディレクトリを `windows-dir` とする。
なお、今回は `/` 直下に両ディレクトリがあることを想定する。

Linuxサーバ側では、

```
$ convmvfs /windows-dir -o ocharset=CP932,srcdir=/linux-dir,allow_other
```
でマウントする。
これで、 `/linux-dir` に作成されたファイルは、 `/windows-dir` に自動リンクされ、Windosサーバ上では、文字化けしていないファイル名のファイルが共有される。
**\# 後述するが、文字化けしないのはファイル名のみで、例えばテキストファイルであると、中身についてはがっつり文字化けしたままとなる。**


### インスタンス再起動時に自動マウントするようにする
crontabに `@reboot` をつけることでインスタンス再起動のたびに自動マウントできる。

```
$ crontab -e
@reboot convmvfs /windows-dir -o ocharset=CP932,srcdir=/linux-dir,allow_other
```

なお、アンマウントについては以下コマンドで可能。

```
$ fusermount -u /windows-dir
# buzyでアンマウントできない場合は `-z` オプション付与で強制断できる
```


## NFSクライアント(WindowsServer)側の設定
- [ここを参考に](http://electronekowd.blog.fc2.com/blog-entry-7.html)


### WindowsServerのmountコマンド有効化
WindowsServerはデフォルトでNFSクライアントが有効でない(= `mount` コマンドが有効でない)ので、有効化する。  

1.  サーバーマネージャーを起動し、「役割と機能の追加」を選択する
2.  「機能の選択」で「Client for NFS」にチェック。「次へ」を選択
3.  次へを押し、インストール(再起動については必要に応じて)
4.  コマンドプロンプトで `mount` と打ち、実行できることを確認


### WindowsServer側からNFSマウント
LinuxServerのIPがd.e.f.g、WindowsServerログオン時ユーザがAdministratorだった場合

```
C:\> mount -o mtype=soft -o lang=shift-jis -u:Administrator \\d.e.f.g\windows-dir Z:
# このコマンドをbatファイルに記述し、スタートアップディレクトリに放り込めば
# 起動時に自動的にマウントさせることが可能
```

でマウントする。
成功すると、エクスプローラー上にZドライブが出現する。  


### LinuxとWindows間のユーザーマッピングを行う
Windows側から共有ドライブ(今回のケースだとZドライブ)上に作成したファイルは、所有者、グループのuidとgidがLinux側に存在しないことになる。
そのため、Windows側から書き込んだ場合にLinuxのec2-userが所有者、グループになるようにユーザマッピングを行う。  

Linux側で以下コマンドを実行

```
$ cat /etc/passwd | grep ec2-user
ec2-user:x:500:500:EC2 Default User:/home/ec2-user:/bin/bash
```

上記実行内容をもとに
`C:\Windows\System32\drivers\etc` 内で 新規ファイル `passwd` と `group` を作成する。 
**passwd**

```
Administrator:x:500:500:EC2 Default User:/home/ec2-user:/bin/bash
```

**group**
Administratorsグループに所属するユーザの場合はユーザ名の前に `BUILTIN\` をつける。

```
BUILTIN\Administrators:x:500:
```

これで、Windows側から作成したファイルの所有者およびグループはec2-userになる。


## 問題点
 - 構築がめんどい
 - ディスク容量がEBSマターになる。S3をローカルに仮想マウントさせて、それをNFSのマウントポイントにすることってできるのかね
 - 途中記述したが、convmvfsによって、Linux側で作成した **ファイル名** はWindows上でも文字化けせずに見ることが可能だが、中身については、化け化けな点。もちろん逆の場合も同様となる。これについては、nkfとかで頑張るしかない？
 - データ転送速度は、自検証環境ではプライベートサブネットでのNFSだったこともあり、レイテンシの問題があるように感じなかった。インターネット経由するとなったらどうなるかは知らん
 - 保守性とか可用性を考えると憂鬱になるね。やはりマネージドはすごい


## 結論
めんどい！
おそらくみなさんは選ばれし人なので、非公式NFSクライアントを経由してEFSを使おう！
貴族はFSxやらStorageGatewayを使おう！


## 参考
- [Amazon Linuxでnfsを使ったディレクトリ共有](https://hacknote.jp/archives/2018/)
- [LinuxのNFSディレクトリをWindows Serverからマウントしユーザマッピングする](http://totech.hateblo.jp/category/Linux?page=1522399251)
- [CentOSにWindowsからNFSで接続する　#1　NFSサーバーでShift-JISを扱えるようにする。](http://electronekowd.blog.fc2.com/blog-entry-7.html)
- [Amazon EFS へ Windows EC2インスタンスから接続する](https://qiita.com/zakky/items/b0c4df1ee7cb75830186)