クライアントのホスト名が重複しているとNFS v4でAmazon FSx for NetApp ONTAPのボリュームをマウントできない件

Auto Scalingするときは特に注意
2022.07.27

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

クライアントのホスト名が重複しているとマウントできないぞ

こんにちは、のんピ(@non____97)です。

皆さんは同じホスト名のクライアントからNFS v4でAmazon FSx for NetApp ONTAP(以降FSx for ONTAP)のボリュームをマウントしたいと思ったことはありますか? 私はあります。

例えば、EC2インスタンスをAuto Scalingさせて、複数のEC2インスタンスからFSx for ONTAP内のファイルにアクセスしたい場合があると思います。

その際、EC2インスタンスのホスト名が同じだと、2台目以降のEC2インスタンスはNFS v4でFSx for ONTAPのボリュームをマウントできないということをみなさんご存知でしょうか。

ということで、今回はその原因と対処方法を紹介します。

いきなりまとめ

  • クライアントのホスト名が重複しているとNFS v4でAmazon FSx for NetApp ONTAPのボリュームをマウントできない
  • NFS v4ではホスト名をクライアントIDとして使用する
  • クライアントIDは一意である必要がある
  • 回避策は以下2つ
    • ホスト名の変更
    • nfs4_unique_idの設定

検証の環境

説明するにあたって検証環境を用意します。

検証の環境は以下の通りです。

構成図

EC2インスタンス B以外は、AWS CDKで各種リソースをデプロイします。使用したコードは以下リポジトリに保存しています。

EC2インスタンス AからNFS v4でFSx for ONTAPのボリュームにマウントできているか確認

それではEC2インスタンス Aにログインして、NFS v4でFSx for ONTAPのボリュームにマウントできているかを確認します。

# ホスト名の確認
$ hostname
ec2-instance.corp.non-97.net

# IPアドレスの確認
$ ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc mq state UP group default qlen 1000
    link/ether 0e:84:4c:2f:e6:3b brd ff:ff:ff:ff:ff:ff
    inet 10.0.1.10/28 brd 10.0.1.15 scope global dynamic eth0
       valid_lft 3557sec preferred_lft 3557sec
    inet6 fe80::c84:4cff:fe2f:e63b/64 scope link
       valid_lft forever preferred_lft forever

# /etc/fstab の設定確認
$ cat /etc/fstab
#
UUID=11ea48e5-4a29-4c1e-bb12-8138651b1870     /           xfs    defaults,noatime  1   1
svm-094f0cf75b091424e.fs-013816ec87fee14ad.fsx.us-east-1.amazonaws.com:/nfs /mnt/fsx nfs4 nfsvers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2,noresvport,_netdev 0 0

# FSx for ONTAPのボリュームをNFSでマウントしているか確認
$ df -hT
Filesystem                                                                  Type      Size  Used Avail Use% Mounted on
devtmpfs                                                                    devtmpfs  471M     0  471M   0% /dev
tmpfs                                                                       tmpfs     479M     0  479M   0% /dev/shm
tmpfs                                                                       tmpfs     479M  352K  478M   1% /run
tmpfs                                                                       tmpfs     479M     0  479M   0% /sys/fs/cgroup
/dev/nvme0n1p1                                                              xfs       8.0G  1.6G  6.5G  20% /
svm-094f0cf75b091424e.fs-013816ec87fee14ad.fsx.us-east-1.amazonaws.com:/nfs nfs4      973M  320K  973M   1% /mnt/fsx

# NFS v4.1でマウントしていることを確認
$ mount | grep nfs
sunrpc on /var/lib/nfs/rpc_pipefs type rpc_pipefs (rw,relatime)
svm-094f0cf75b091424e.fs-013816ec87fee14ad.fsx.us-east-1.amazonaws.com:/nfs on /mnt/fsx type nfs4 (rw,relatime,vers=4.1,rsize=65536,wsize=65536,namlen=255,hard,noresvport,proto=tcp,timeo=600,retrans=2,sec=sys,clientaddr=10.0.1.10,local_lock=none,addr=10.0.1.20,_netdev)

OSのホスト名がec2-instance.corp.non-97.netで、NFS v4.1でFSx for ONTAPの/nfs/mnt/nfsにマウントできていることを確認できました。

EC2インスタンス BからNFS v4でFSx for ONTAPのボリュームにマウントできているか確認

次に、EC2インスタンス BからNFS v4でFSx for ONTAPのボリュームをマウントできているか確認します。

EC2インスタンス AのAMIを取得して、そのAMIを使ってEC2インスタンス Bを立てます。

EC2インスタンス B作成後、ログインしてFSx for ONTAPのボリュームをマウントできているかを確認します。

# ホスト名がEC2インスタンス Aと同じであることを確認
$ hostname
ec2-instance.corp.non-97.net

# IPアドレスの確認
$ ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc mq state UP group default qlen 1000
    link/ether 0e:2a:5c:c8:1e:51 brd ff:ff:ff:ff:ff:ff
    inet 10.0.1.13/28 brd 10.0.1.15 scope global dynamic eth0
       valid_lft 3508sec preferred_lft 3508sec
    inet6 fe80::c2a:5cff:fec8:1e51/64 scope link
       valid_lft forever preferred_lft forever

# FSx for ONTAPのボリュームをNFSでマウントしているか確認
$ df -hT
Filesystem     Type      Size  Used Avail Use% Mounted on
devtmpfs       devtmpfs  471M     0  471M   0% /dev
tmpfs          tmpfs     479M     0  479M   0% /dev/shm
tmpfs          tmpfs     479M  348K  478M   1% /run
tmpfs          tmpfs     479M     0  479M   0% /sys/fs/cgroup
/dev/nvme0n1p1 xfs       8.0G  1.6G  6.5G  20% /

$ mount | grep nfs
sunrpc on /var/lib/nfs/rpc_pipefs type rpc_pipefs (rw,relatime)

EC2インスタンス BではFSx for ONTAPのボリュームをNFSでマウントできていないようです。

/etc/fstabの設定を使用して手動でマウントしようとしても拒否されてしまいました。

$ sudo mount -a
mount.nfs4: Operation not permitted

EC2インスタンス AでアンマウントしたするとEC2インスタンス Bからマウントできるか確認

次に、EC2インスタンス AでアンマウントするとEC2インスタンス Bからマウントできるか確認してみましょう

EC2インスタンス AでFSx for ONTAPのボリュームをアンマウントします。

# EC2インスタンス AでFSx for ONTAPのボリュームをアンマウント
$ sudo umount /mnt/fsx

# アンマウントされたことを確認
$ df -hT
Filesystem     Type      Size  Used Avail Use% Mounted on
devtmpfs       devtmpfs  471M     0  471M   0% /dev
tmpfs          tmpfs     479M     0  479M   0% /dev/shm
tmpfs          tmpfs     479M  404K  478M   1% /run
tmpfs          tmpfs     479M     0  479M   0% /sys/fs/cgroup
/dev/nvme0n1p1 xfs       8.0G  1.6G  6.5G  20% /
tmpfs          tmpfs      96M     0   96M   0% /run/user/0

$ mount |grep nfs
sunrpc on /var/lib/nfs/rpc_pipefs type rpc_pipefs (rw,relatime)

次にEC2インスタンス BからFSx for ONTAPのボリュームをマウントします。

# EC2インスタンスからFSx for ONTAPのボリュームをマウント
$ sudo mount -a

# NFS v4でマウントできたことを確認
$ df -hT
Filesystem                                                                  Type      Size  Used Avail Use% Mounted on
devtmpfs                                                                    devtmpfs  471M     0  471M   0% /dev
tmpfs                                                                       tmpfs     479M     0  479M   0% /dev/shm
tmpfs                                                                       tmpfs     479M  408K  478M   1% /run
tmpfs                                                                       tmpfs     479M     0  479M   0% /sys/fs/cgroup
/dev/nvme0n1p1                                                              xfs       8.0G  1.6G  6.5G  20% /
tmpfs                                                                       tmpfs      96M     0   96M   0% /run/user/0
svm-094f0cf75b091424e.fs-013816ec87fee14ad.fsx.us-east-1.amazonaws.com:/nfs nfs4      973M  384K  973M   1% /mnt/fsx

# mount コマンドからも確認
$ mount | grep nfs
sunrpc on /var/lib/nfs/rpc_pipefs type rpc_pipefs (rw,relatime)
svm-094f0cf75b091424e.fs-013816ec87fee14ad.fsx.us-east-1.amazonaws.com:/nfs on /mnt/fsx type nfs4 (rw,relatime,vers=4.1,rsize=65536,wsize=65536,namlen=255,hard,noresvport,proto=tcp,timeo=600,retrans=2,sec=sys,clientaddr=10.0.1.13,local_lock=none,addr=10.0.1.20,_netdev)

EC2インスタンス Bからもマウントできました。

なぜ同じホスト名だとNFSでマウントにできないのか

同じホスト名だとNFSでマウントにできないのかという原因は、NFS v4の仕様にあります。

NFS v4のRFCであるRFC 7530 - Network File System (NFS) Version 4 Protocolを確認します。

その中に以下のような記載があります。

9.1.1. Client ID

For each LOCK request, the client must identify itself to the server.This is done in such a way as to allow for correct lock identification and crash recovery.

. . (中略) . .

There are several considerations for how the client generates the id string:

The string should be unique so that multiple clients do not present the same string. The consequences of two clients presenting the same string range from one client getting an error to one client having its leased state abruptly and unexpectedly canceled.

RFC 7530 - Network File System (NFS) Version 4 Protocol

要するに、ロックの識別やクラッシュからの回復のために、NFSサーバーがクライアントを一意に識別するためのIDが必要とのことです。

次に、NetApp ONTAPのNFSのプラクティスが記載されているドキュメントを確認してみます。

以下のような記載がありました。

Workaround #3: Change the client name used with NFSv4.x mounts

By default, NFSv4.x uses the client’s host name for the client ID value when mounting to the NFS server.

NFS best practice and implementation guide | TR-4067

どうやらNFS v4ではホスト名をクライアントIDとして使用するようですね。

そのため、ホスト名が重複している場合はNFS v4でマウントできないようです。

試しに、EC2インスタンス Aから手動でNFSのバージョンを指定せずにマウントしてみます。すると、NFS v3でマウントすることができました。

$ sudo mount -t nfs svm-094f0cf75b091424e.fs-013816ec87fee14ad.fsx.us-east-1.amazonaws.com:/nfs /mnt/fsx

$ mount | grep nfs
sunrpc on /var/lib/nfs/rpc_pipefs type rpc_pipefs (rw,relatime)
svm-094f0cf75b091424e.fs-013816ec87fee14ad.fsx.us-east-1.amazonaws.com:/nfs on /mnt/fsx type nfs (rw,relatime,vers=3,rsize=65536,wsize=65536,namlen=255,hard,proto=tcp,timeo=600,retrans=2,sec=sys,mountaddr=10.0.1.20,mountvers=3,mountport=635,mountproto=udp,local_lock=none,addr=10.0.1.20)

回避策

回避策を考えます。

一番簡単な方法はホスト名の変更です。

ホスト名をクライアントIDとして使用するので、ホスト名を[ホスト名]_[ランダムな文字列]としてしまえば、クライアントIDの重複を回避できます。

2つ目がnfs4_unique_idの設定です。

nfs4_unique_idに指定した文字列はNFSのクライアントIDとして動作します。

The nfs.nfs4_unique_id boot parameter specifies a unique string that can be used instead of a system’s node name when an NFS client identifies itself to a server. Thus, if the system’s node name is not unique, or it changes, its nfs.nfs4_unique_id stays the same, preventing collision with other clients or loss of state during NFS reboot recovery or transparent state migration.

NFS Client — The Linux Kernel documentation

一意な文字列をnfs4_unique_idに指定してあげればホスト名を変更する必要がありません。

nfs4_unique_idに設定するする文字列は一意であればなんでもよさそうです。

Given the above considerations, an example of a well-generated id string is one that includes:

  • The server's network address.
  • The client's network address.
  • For a user-level NFSv4 client, it should contain additional information to distinguish the client from other user-level clients running on the same host, such as a universally unique identifier (UUID).
  • Additional information that tends to be unique, such as one or more of:
    • The client machine's serial number (for privacy reasons, it is best to perform some one-way function on the serial number).
    • A MAC address (for privacy reasons, it is best to perform some one-way function on the MAC address).
    • The timestamp of when the NFSv4 software was first installed on the client (though this is subject to the previously mentioned caution about using information that is stored in a file, because the file might only be accessible over NFSv4).
    • A true random number. However, since this number ought to be the same between client incarnations, this shares the same problem as that of using the timestamp of the software installation.

RFC 7530 - Network File System (NFS) Version 4 Protocol

nfs4_unique_id を設定してマウント

それではnfs4_unique_idを設定してマウントしてみます。

まず、デフォルトのnfs4_unique_idの確認です。

カーネルモジュールのパラメータを確認することになるので、sysfsutilsをインストールします。

$ sudo yum install sysfsutils -y
Loaded plugins: extras_suggestions, langpacks, priorities, update-motd
amzn2-core                                                                                                            | 3.7 kB  00:00:00
Resolving Dependencies
--> Running transaction check
---> Package sysfsutils.x86_64 0:2.1.0-16.amzn2.0.2 will be installed
--> Finished Dependency Resolution

Dependencies Resolved

=============================================================================================================================================
 Package                         Arch                        Version                                   Repository                       Size
=============================================================================================================================================
Installing:
 sysfsutils                      x86_64                      2.1.0-16.amzn2.0.2                        amzn2-core                       41 k

Transaction Summary
=============================================================================================================================================
Install  1 Package

Total download size: 41 k
Installed size: 119 k
Downloading packages:
sysfsutils-2.1.0-16.amzn2.0.2.x86_64.rpm                                                                              |  41 kB  00:00:01
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
  Installing : sysfsutils-2.1.0-16.amzn2.0.2.x86_64                                                                                      1/1
  Verifying  : sysfsutils-2.1.0-16.amzn2.0.2.x86_64                                                                                      1/1

Installed:
  sysfsutils.x86_64 0:2.1.0-16.amzn2.0.2

Complete!

インストール後、nfs4_unique_idを確認します。

$ sudo systool -v -m nfs | grep -i nfs4_unique
    nfs4_unique_id      = ""

nfs4_unique_idは何も指定されていないようですね。

ランダムな文字列をnfs4_unique_idにしてOSを再起動させます。

# 設定ファイルがあるか確認する
$ ls -l /etc/modprobe.d/nfsclient.conf
ls: cannot access /etc/modprobe.d/nfsclient.conf: No such file or directory

# ランダムな文字列を nfs4_unique_id に指定
$ nfs4_unique_id=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9!@#$%^&*()_+-=[]{}<>?' | fold -w 32 | head -n 1)
$ echo options nfs nfs4_unique_id="$nfs4_unique_id" | sudo tee -a  /etc/modprobe.d/nfsclient.conf
options nfs nfs4_unique_id=l8{zqkNJ$enMUpveb:oDj5[}^x)_V{,q

# nfs4_unique_id が指定されたことを確認する
$ cat /etc/modprobe.d/nfsclient.conf
options nfs nfs4_unique_id=l8{zqkNJ$enMUpveb:oDj5[}^x)_V{,q

# OSの再起動
$ sudo systemctl reboot
Terminated

再起動後、NFS v4でマウントできているか確認します。

# FSx for ONTAPのボリュームをNFSでマウントしているか確認
$ df -hT
Filesystem                                                                  Type      Size  Used Avail Use% Mounted on
devtmpfs                                                                    devtmpfs  471M     0  471M   0% /dev
tmpfs                                                                       tmpfs     479M     0  479M   0% /dev/shm
tmpfs                                                                       tmpfs     479M  352K  478M   1% /run
tmpfs                                                                       tmpfs     479M     0  479M   0% /sys/fs/cgroup
/dev/nvme0n1p1                                                              xfs       8.0G  1.7G  6.4G  21% /
svm-094f0cf75b091424e.fs-013816ec87fee14ad.fsx.us-east-1.amazonaws.com:/nfs nfs4      973M  384K  973M   1% /mnt/fsx

# マウントオプションを確認
$ mount | grep nfs
sunrpc on /var/lib/nfs/rpc_pipefs type rpc_pipefs (rw,relatime)
svm-094f0cf75b091424e.fs-013816ec87fee14ad.fsx.us-east-1.amazonaws.com:/nfs on /mnt/fsx type nfs4 (rw,relatime,vers=4.1,rsize=65536,wsize=65536,namlen=255,hard,noresvport,proto=tcp,timeo=600,retrans=2,sec=sys,clientaddr=10.0.1.10,local_lock=none,addr=10.0.1.20,_netdev)

# ホスト名が ec2-instance.corp.non-97.net であることを確認
$ hostname
ec2-instance.corp.non-97.net

# EC2インスタンス AのIPアドレスであることを確認
$ ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc mq state UP group default qlen 1000
    link/ether 0e:84:4c:2f:e6:3b brd ff:ff:ff:ff:ff:ff
    inet 10.0.1.10/28 brd 10.0.1.15 scope global dynamic eth0
       valid_lft 3481sec preferred_lft 3481sec
    inet6 fe80::c84:4cff:fe2f:e63b/64 scope link
       valid_lft forever preferred_lft forever

# nfs4_unique_id が指定されていることを確認
$ sudo systool -v -m nfs | grep -i nfs4_unique
    nfs4_unique_id      = "l8{zqkNJ$enMUpveb:oDj5[}^x)_V{,q"

ホスト名が同じでもNFS v4でマウントできることを確認できました。

Auto Scalingの場合は、以下コマンドを起動設定のユーザーデータで行えばよさそうです。

nfs4_unique_id=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9!@#$%^&*()_+-=[]{}<>?' | fold -w 32 | head -n 1)
echo options nfs nfs4_unique_id="$nfs4_unique_id" >> /etc/modprobe.d/nfsclient.conf
systemctl reboot

なお、今回は32桁のランダムな文字列をnfs4_unique_idに設定しましたが、お好みでfold -w 32の数字を変更して、64桁や128桁などに変更してください。

EC2インスタンス Bのマウントの状態も確認しておきましょう。

# EC2インスタンス Bでも引き続きマウントできていることを確認
$ df -hT
Filesystem                                                                  Type      Size  Used Avail Use% Mounted on
devtmpfs                                                                    devtmpfs  471M     0  471M   0% /dev
tmpfs                                                                       tmpfs     479M     0  479M   0% /dev/shm
tmpfs                                                                       tmpfs     479M  408K  478M   1% /run
tmpfs                                                                       tmpfs     479M     0  479M   0% /sys/fs/cgroup
/dev/nvme0n1p1                                                              xfs       8.0G  1.7G  6.4G  21% /
tmpfs                                                                       tmpfs      96M     0   96M   0% /run/user/0
svm-094f0cf75b091424e.fs-013816ec87fee14ad.fsx.us-east-1.amazonaws.com:/nfs nfs4      973M  384K  973M   1% /mnt/fsx

# マウントオプションを確認
$ mount | grep nfs
sunrpc on /var/lib/nfs/rpc_pipefs type rpc_pipefs (rw,relatime)
svm-094f0cf75b091424e.fs-013816ec87fee14ad.fsx.us-east-1.amazonaws.com:/nfs on /mnt/fsx type nfs4 (rw,relatime,vers=4.1,rsize=65536,wsize=65536,namlen=255,hard,noresvport,proto=tcp,timeo=600,retrans=2,sec=sys,clientaddr=10.0.1.13,local_lock=none,addr=10.0.1.20,_netdev)

一度アンマウントして、再マウントも試してみます。

# アンマウント
$ sudo umount /mnt/fsx

# アンマウントされたことを確認
$ mount | grep nfs
sunrpc on /var/lib/nfs/rpc_pipefs type rpc_pipefs (rw,relatime)

# 再マウント
$ sudo mount -a

# 再マウントできたことを確認
$ mount | grep nfs
sunrpc on /var/lib/nfs/rpc_pipefs type rpc_pipefs (rw,relatime)
svm-094f0cf75b091424e.fs-013816ec87fee14ad.fsx.us-east-1.amazonaws.com:/nfs on /mnt/fsx type nfs4 (rw,relatime,vers=4.1,rsize=65536,wsize=65536,namlen=255,hard,noresvport,proto=tcp,timeo=600,retrans=2,sec=sys,clientaddr=10.0.1.13,local_lock=none,addr=10.0.1.20,_netdev)

マウントできますね。

ちなみに当然ですが、nfs4_unique_idが重複するとマウントできません。

# EC2インスタンス Aの nfs4_unique_id と同じ文字列を nfs4_unique_id に設定
$ echo options nfs nfs4_unique_id='l8{zqkNJ$enMUpveb:oDj5[}^x)_V{,q' | sudo tee -a /etc/modprobe.d/nfsclient.conf
options nfs nfs4_unique_id=l8{zqkNJ$enMUpveb:oDj5[}^x)_V{,q

$ cat /etc/modprobe.d/nfsclient.conf
options nfs nfs4_unique_id=l8{zqkNJ$enMUpveb:oDj5[}^x)_V{,q

# 設定を反映させるためにOSを再起動
$ sudo systemctl reboot
Terminated

[再起動後]

# マウントされていないことを確認
$ mount | grep nfs
sunrpc on /var/lib/nfs/rpc_pipefs type rpc_pipefs (rw,relatime)

# EC2インスタンス Aの nfs4_unique_id と同じ文字列が nfs4_unique_id に設定されていることを確認
$ sudo systool -v -m nfs | grep -i nfs4_unique
    nfs4_unique_id      = "l8{zqkNJ$enMUpveb:oDj5[}^x)_V{,q"

Auto Scalingするときは特に注意

クライアントのホスト名が重複しているとNFS v4でAmazon FSx for NetApp ONTAPのボリュームをマウントできない事象を紹介しました。

特に、Auto Scalingをするときにはどハマりすること間違い無いです。NFS v4で接続できない場合は各EC2インスタンスのホスト名を変更するか、一意なnfs4_unique_idを設定して再チャレンジしてみてください。

この記事が誰かの助けになれば幸いです。

以上、AWS事業本部 コンサルティング部の のんピ(@non____97)でした!