1と16のリビジョン間の差分 (その間の編集: 15回)
2016-06-08 01:07:51時点のリビジョン1
サイズ: 7519
コメント:
2016-06-11 16:31:54時点のリビジョン16
サイズ: 13702
コメント:
削除された箇所はこのように表示されます。 追加された箇所はこのように表示されます。
行 5: 行 5:
 * FreeBSD/amd64 10.3-RELEASE をNFSv4サーバーとする。  * FreeBSD/amd64 10.3-RELEASE をNFSv4サーバーとする。
行 7: 行 7:
 * NFSv4 on ZFS で、使用するプロトコルはNFSv4に絞る。
 * ZFSはUFSでもかまわない。
 * UFSの場合、sharenfs でなく、/etc/exports で反映を行う。
 * 過去との互換性?今時 v2 はおろか、v3 でもないでしょ。v4 ないしは v4.1 で。
 * 使用するプロトコルはNFSv4に絞る(重要なので2回ry)。
 * NFSv4 on ZFS 構成とし、/etc/exports ではなく sharenfs プロパティによりNFS共有設定を制御する。
 * また1つのディレクトリ(≒Zプール)以下に集約する(NFSv4の名前空間的要求による)。
 * もちろんバックエンドストレージをZFSにしようがUFSにしようが、違いは無い。UFSの場合、sharenfs でなく、/etc/exports で設定を行うくらいの違いで。
 * 今回ディレクトリ作成(mkdir)=ファイルシステム作成(zfs create)としているが、sharenfs プロパティの設定をそのまま /etc/exports に転載したものと思えばよい。
 * また、ZFSでもUFSでもそうだが、階層外にあるものをNFS共有したいなら、nullfs で引っ張れば良い。
 * バージョンの選択についてだが、過去との互換性?今時 v2 はおろか、v3 でもないでしょ、ということで、v4 ないしは v4.1(pNFS はまだ使えない orz)一択で。

<<Include(MemoOfNFSセキュリティメモ, "NFSセキュリティメモ", 2)>>
行 21: 行 26:
 * 今回、/export 上にNFS共有するファイルシステムを専用に用意するものとする。  * 今回、/export 上にNFS共有するファイルシステムを専用に用意するものとする(必須ではない)
行 23: 行 28:
 * sharenfs プロパティを設定すると、/etc/zfs/exports に展開された上、mountd(8)にHUPシグナルを送られる。
行 29: 行 35:
※VMware ESXi 上(LSI Logic SAS アダプタ)では TRIM/UNMAP が効かないのでオフにする。
基本的に物理環境下ならHDDと言えど TRIM/UNMAP 試してエラーになることは無いと思われるので、CAMのエラーメッセージがうるさい時だけ設定する。

== /etc/rc.conf(NICチューニング) ===
※検証環境に使用した VMware ESXi 6.0U2 上(5.5/5.5U1/5.5U2/6.0/6.0U1 でも確認、いずれも LSI Logic SAS アダプタによる)では TRIM/UNMAP がエラーになってログがウザいので ZFS TRIM 機能をオフにする。

物理環境下なら今時のHDDであれば TRIM/UNMAP 試してエラーになることは無いと思われるので、CAMのエラーメッセージがうるさい時だけ設定する。

どういうエラーメッセージが表示されるかというと、下記のようなカーネルメッセージ(SCSI/SAS なので TRIM というよりは UNMAP が実行された)で3回リトライするので3セット出力される。

{{{
(da1:mpt1:0:0:0): UNMAP. CDB: 42 00 00 00 00 00 00 00 18 00
(da1:mpt1:0:0:0): CAM status: SCSI Status Error
(da1:mpt1:0:0:0): SCSI status: Check Condition
(da1:mpt1:0:0:0): SCSI sense: Vendor Specific asc:0,0 (No additional sense information)
(da1:mpt1:0:0:0): Error 5, Unretryable error
}}}

このあたり、dmesg(5) コマンドの結果や /var/log/messages ファイルの中を確認のこと。

== /etc/rc.conf(NICチューニング) ==
行 39: 行 58:
MTU値はネットワーク依存で、通信に絡んでいる一番小さな値を指定することになるが、最近だと9000バイトあたりに収束つつあるのかなぁと思いつつ

なお手動で設定できるが、MTU値を反映するため一度下記のようにインターフェースをダウンさせる必要がある。
MTU値はネットワーク依存で、通信に絡んでいる一番小さな値を指定することになる。必ずしも9000バイト)とは限らないので、ちゃんと調べよう(&設定よう)

なお手動で設定できるが、その場合、MTU値を反映するため一度下記のようにインターフェースをダウンさせる必要がある。
行 65: 行 84:
特に async_write_max_active はドライブが対応しているNCQ・TCQの数(-1)を指定する。 特に async_write_max_active はドライブが対応しているNCQ・TCQの数(-1)を指定する(台数があれば台数分を乗算する)
行 73: 行 92:
==== vfs.nfsd.issue_delegations ====
行 74: 行 94:
 * しかし、調べた範囲だと、NFSクライアントで使用が明言されてないので、とりあえずオフっておく。

 * ロックについて、NFSサーバーとNFSクライアント間でのロック共有ができるようになる。
 * しかし、調べた範囲だと、NFSクライアントで使用が明言されてない」というか確認できなかったので、とりあえずオフっておく。

==== vfs.nfsd.enable_locallocks ====
* ロックについて、NFSサーバーとNFSクライアント間でのロック共有ができるようになる。
行 80: 行 101:
 * 調査が足りてないので、とりあえずオフっておく。  * この問題について調査が足りてないので、とりあえずオフっておく。
 * もちろんこの設定があろうが、なかろうが、NFSv4の売り文句であるところの、NFSクライアント(内の複数のプロセス)でのロック取得について問題無し。
 * また、この話とは別に、NFSクライアント間のロック共有が可能かは未検証。
行 87: 行 110:
とりあえず、/export がNFSv4共有できるようになる。ただし、/export 自体は sharenfs=off なので、どこからからもマウントできない(できるけどアクセスできない)。 とりあえず、/export がNFSv4共有できるようになる。ただし、/export 自体は sharenfs=off なので、どこからからもマウントできない(厳密にはできるけどアクセスできない)。
行 90: 行 113:
 * NFSv4サーバーとして運用するために必要なデーモン(およびオプション)は以下の通り。  * NFSv4サーバーとして運用するために必要なデーモンは以下の通り。
行 98: 行 121:
 * また、以下の設定の設定によりある程度のアクセス制限を行う。
{{{
rpcbind_flags="-h 公開するNFSv4サーバーのIPアドレス"
 * また、以下の設定によりある程度のアクセス制限を行う。
{{{
rpcbind_flags="-h 公開するNFSサーバーのIPアドレス"
行 102: 行 125:
mountd_flags="-l -h 公開するNFSv4サーバーのIPアドレス"
nfs_server_flags="-t -h 公開するNFSv4サーバーのIPアドレス"
mountd_flags="-l -h 公開するNFSサーバーのIPアドレス"
nfs_server_flags="-t -h 公開するNFSサーバーのIPアドレス"
行 109: 行 132:
これは厳密にはサーバーのドメインとは別物であるため、別途決め打ちする必要がある。 これはNFS共有するようなサーバー群では、同じドメインである場合、本設定を省略しても良い。

しかし、ホスティング環境でのバックアップサーバー提供のような、NFSクライアントのサーバーのドメインが統一できないような場合、サービス提供者側として、別途決め打ちする必要がある。
行 112: 行 137:
 * 先にも述べたがNFSv4におけるサーバーとクライアント間のアカウント識別は「ユーザー@ドメイン」である。
 * これはNFSv3/v2までと違い、UID、GIDという数字では識別していないことを意味する。
 * 先にも述べたがNFSv4におけるNFSサーバーとNFSクライアント間のアカウント識別は「ユーザー@ドメイン」である。
 * これはNFSv3/v2までと違い、UID、GIDという数字では識別していないことを意味する(問題については後述)
行 130: 行 155:
== CentOS 6.x での相互運用問題 ==
CentOS 6.8(おそらく CentOS 5.11 も) との相互運用では以下の点に注意する必要がある。

 * NFSサーバー・クライアント間でUID/GIDを合致させないといけないバグがある(NFSv4の仕様上、バグ認定)。
 * というのもNFSクライアント(CentOS 6.8)で postgres(26):postgres(26) のプロセスがアクセス(cd など)した時の、NFSサーバーへのユーザー問い合わせ結果を tcpdump(8)した結果、「postgres」ではなく「26」という文字列をNFSサーバーに問い合わせ(fattr_owner)ている現象を確認した。
 * なお、chown(8) や ls(1) した時には問題無い。
 * 本現象について調査したところ、下記のバグがレポートされていることを確認した。
   * [[https://bugzilla.redhat.com/show_bug.cgi?id=829362|Bug 829362 - wrong username/domain passed in nfs4 attribute requests]]
 * バグレポートでは以下の点から、CentOS 6 系(少なくとも 6.8、2016年06月09日現在)以下には反映されていないものと考える。
   * バグレポートで言及されているディストリビューションが !FedoraCore 17 である。
   * CentOS 6(RHEL6) は !FedoraCore 12/13 ベースである。
   * 更に CentOS 6 の nfs-utils のバージョンは 1.2.3 であるが、!FedoraCore 17 では 1.2.6 である。
   * !FedoraCore 17 ベースの CentOS 7 では問題無いと思われる(未検証)。
行 131: 行 170:
/export をどう共有するかによるが「/export/NFSv4クライアント」として、クライアント単位で共有設定する場合は、下記のようにパーティションを切る。
== 共有設定 ==
/export をどう共有するかによるが「/export/NFSv4クライアント」として、クライアント単位で共有設定する場合は、下記のようにパーティションを切る。
行 135: 行 176:
zfs create -o sharenfs="-maproot=0:0 NFSv4クライアント名" export/NFSv4クライアント

}}}

sharenfs 設定を行うと、/etc/zfs/exports ファイルに掃き出されるのと、合わせてmountd(8)に再読み込み(HUP シグナル)が実施される。

一つの領域を複数のNFSv4クライアント案とで共有するなら、/etc/exports に集約するのが良いと思われ(未実験)。
zfs create -o sharenfs="-maproot=root NFSクライアントIP" export/NFSクライアント名

}}}

sharenfs 設定を行うと、/etc/zfs/exports ファイルに掃き出されるのと、合わせて mountd(8) に再読み込み(HUP シグナル)が実施される。

一つの領域を複数のNFSクライアント間で共有するなら、/etc/exports に集約するのが良いと思われ(未実験)。

なおNFSクライアントからは、「/NFSクライアント名」でマウントすることになる(/export がトップディレクトリとなって見えなくなる)。

更にお好みに応じて、exec=off、setuid=off も追加しよう。これはNFSサーバーとしてはこれら属性を「解釈しない」という意味であって、NFSクライアントはNFSクライアントで、別途設定が必要となる。

== 設定確認 ==
mountd(8) の再読み込みによりNFSクライアントからマウントできるようになるわけだが、これが成功したのか失敗したのかはよくわからない。
そこで、「showmount -e」コマンドと「zfs get -t filesystem sharenfs」コマンドの実行結果を見比べて判断すること(設定した内容が反映されてないなど)。

{{{
# showmount -e
Exports list on localhost:
/export/NFSクライアント1 XXX.XXX.XXX.XXX
/export/NFSクライアント2 YYY.YYY.YYY.YYY
# zfs get -t filesystem sharenfs
NAME PROPERTY VALUE SOURCE
export sharenfs off default
export/NFSクライアント1 sharenfs -maproot=root XXX.XXX.XXX.XXX local
export/NFSクライアント2 sharenfs -maproot=root YYY.YYY.YYY.YYY local
}}}

※zfs get sharenfs やべぇ。スナップショットもリストアップして大変な量に…。 orz
行 147: 行 210:

 
 * [[https://bugzilla.redhat.com/show_bug.cgi?id=829362|Bug 829362 - wrong username/domain passed in nfs4 attribute requests]]

NFSv4サーバーの作り方

検証環境

  • FreeBSD/amd64 10.3-RELEASE をNFSv4【サーバー】とする。
  • CentOS をサーバーにするケースは今回は無しで。
  • 使用するプロトコルはNFSv4に絞る(重要なので2回ry)。
  • NFSv4 on ZFS 構成とし、/etc/exports ではなく sharenfs プロパティによりNFS共有設定を制御する。
  • また1つのディレクトリ(≒Zプール)以下に集約する(NFSv4の名前空間的要求による)。
  • もちろんバックエンドストレージをZFSにしようがUFSにしようが、違いは無い。UFSの場合、sharenfs でなく、/etc/exports で設定を行うくらいの違いで。
  • 今回ディレクトリ作成(mkdir)=ファイルシステム作成(zfs create)としているが、sharenfs プロパティの設定をそのまま /etc/exports に転載したものと思えばよい。
  • また、ZFSでもUFSでもそうだが、階層外にあるものをNFS共有したいなら、nullfs で引っ張れば良い。
  • バージョンの選択についてだが、過去との互換性?今時 v2 はおろか、v3 でもないでしょ、ということで、v4 ないしは v4.1(pNFS はまだ使えない orz)一択で。

セットアップ

ZFS領域確保(作業例)

sysctl vfs.zfs.min_auto_ashift=12
zpool create -O atime=off export /dev/da1
  • 今回、/export 上にNFS共有するファイルシステムを専用に用意するものとする(必須ではない)。
  • またマウント可否は sharenfs プロパティで制御するものとする(デフォルトは off)。
  • sharenfs プロパティを設定すると、/etc/zfs/exports に展開された上、mountd(8)にHUPシグナルを送られる。

/boot/loader.conf(環境依存)

vfs.zfs.trim.enabled="0"

※検証環境に使用した VMware ESXi 6.0U2 上(5.5/5.5U1/5.5U2/6.0/6.0U1 でも確認、いずれも LSI Logic SAS アダプタによる)では TRIM/UNMAP がエラーになってログがウザいので ZFS TRIM 機能をオフにする。

物理環境下なら今時のHDDであれば TRIM/UNMAP 試してエラーになることは無いと思われるので、CAMのエラーメッセージがうるさい時だけ設定する。

どういうエラーメッセージが表示されるかというと、下記のようなカーネルメッセージ(SCSI/SAS なので TRIM というよりは UNMAP が実行された)で3回リトライするので3セット出力される。

(da1:mpt1:0:0:0): UNMAP. CDB: 42 00 00 00 00 00 00 00 18 00
(da1:mpt1:0:0:0): CAM status: SCSI Status Error
(da1:mpt1:0:0:0): SCSI status: Check Condition
(da1:mpt1:0:0:0): SCSI sense: Vendor Specific asc:0,0 (No additional sense information)
(da1:mpt1:0:0:0): Error 5, Unretryable error

このあたり、dmesg(5) コマンドの結果や /var/log/messages ファイルの中を確認のこと。

/etc/rc.conf(NICチューニング)

ifconfig_インターフェース="inet XXX.XXX.XXX.XXX netmask XXX.XXX.XXX.XXX mtu 9000"

今時のファイル共有ならGbEや10GbE当たり前なので、MTU値を設定する。 MTU値はネットワーク依存で、通信に絡んでいる一番小さな値を指定することになる。必ずしも9000(バイト)とは限らないので、ちゃんと調べよう(&設定しよう)。

なお手動で設定できるが、その場合、MTU値を反映するために一度、下記のようにインターフェースをダウンさせる必要がある。

ifconfig インターフェース mtu 9000
ifconfig インターフェース down
ifconfig インターフェース up

/etc/sysctl.conf

NFSの最低利用バージョンの指定

vfs.nfsd.server_min_nfsvers=4

なお最大利用バージョンの指定は rc.conf 中の「nfsv4_server_enable="YES"」設定で行われている。

ZFSのチューニング

vfs.zfs.min_auto_ashift=12
vfs.zfs.vdev.async_write_max_active=31

特に async_write_max_active はドライブが対応しているNCQ・TCQの数(-1)を指定する(台数があれば台数分を乗算する)。

NFSのチューニング(未検証)

vfs.nfsd.issue_delegations=0
vfs.nfsd.enable_locallocks=0

vfs.nfsd.issue_delegations

  • NFSサーバーでデリゲーション機能を提供するとNFSクライアントにメリットがあるらしい。
  • しかし、調べた範囲だと、NFSクライアントでの使用が「明言されていない」というか確認できなかったので、とりあえずオフっておく。

vfs.nfsd.enable_locallocks

  • ロックについて、NFSサーバーとNFSクライアント間でのロック共有ができるようになる。
  • しかし、以下の組み合わせで、できたりできなかったりする。
    • NFSクライアント(CentOS 6.8)→NFSサーバー(FreeBSD 10.3-R)の順でロックすると問題無くロックできる。
    • NFSサーバー(FreeBSD 10.3-R)→NFSクライアント(CentOS 6.8)の順でロックするとNFSクライアント側でロックされずにエラーになる。
  • この問題について調査が足りてないので、とりあえずオフっておく。
  • もちろんこの設定があろうが、なかろうが、NFSv4の売り文句であるところの、NFSクライアント(内の複数のプロセス)でのロック取得について問題無し。
  • また、この話とは別に、NFSクライアント間のロック共有が可能かは未検証。

/etc/exports

V4: /export -network ネットワークアドレス -mask ネットマスク

とりあえず、/export がNFSv4共有できるようになる。ただし、/export 自体は sharenfs=off なので、どこからからもマウントできない(厳密にはできるけどアクセスできない)。

/etc/rc.conf

  • NFSv4サーバーとして運用するために必要なデーモンは以下の通り。

rpcbind_enable="YES"
nfsuserd_enable="YES"
mountd_enable="YES"
nfs_server_enable="YES"
nfsv4_server_enable="YES"
  • また、以下の設定によりある程度のアクセス制限を行う。

rpcbind_flags="-h 公開するNFSサーバーのIPアドレス"
nfsuserd_flags="-domain アカウント識別用ドメイン"
mountd_flags="-l -h 公開するNFSサーバーのIPアドレス"
nfs_server_flags="-t -h 公開するNFSサーバーのIPアドレス"

このうち、nfsuserd_flags で指定する「ドメイン」の指定が重要となる。 NFSv4では、NFSサーバーとNFSクライアント間のユーザー識別子を「ユーザー@ドメイン」で識別するため、合わせておく必要がある。

これはNFS共有するようなサーバー群では、同じドメインである場合、本設定を省略しても良い。

しかし、ホスティング環境でのバックアップサーバー提供のような、NFSクライアントのサーバーのドメインが統一できないような場合、サービス提供者側として、別途決め打ちする必要がある。

アカウント作成

  • 先にも述べたがNFSv4におけるNFSサーバーとNFSクライアント間のアカウント識別は「ユーザー@ドメイン」である。
  • これはNFSv3/v2までと違い、UID、GIDという数字では識別していないことを意味する(問題については後述)。
  • 「ドメイン」については先に決めたとおりとする。
  • よく使いそうな「ユーザー」については事前に作成しておくこと。
  • NFSサーバーとNFSクライアント間でアカウントミスマッチが起きると、以下の現象が発生する。
    • NFSクライアント(CentOS 6.8): nobody ユーザー・nobody グループにマップされる。
    • NFSサーバー(FreeBSD 10.3-R):32767 ユーザー・32767 グループにマップされる。

アカウント作成例

pw groupadd postgres -g 5432
pw useradd  postgres -u 5432 -g postgres -c "postgres" -s /usr/sbin/nologin
install -d -o postgres -g postgres -m 0755 /home/postgres

※FreeBSD の PostgreSQL 用アカウントとして pgsql (/usr/ports/UIDs ファイル参照のこと)があるが、CentOS の PostgreSQL 用アカウント(postgres)とはマッチしないので、別途作成する。

CentOS 6.x での相互運用問題

CentOS 6.8(おそらく CentOS 5.11 も) との相互運用では以下の点に注意する必要がある。

  • NFSサーバー・クライアント間でUID/GIDを合致させないといけないバグがある(NFSv4の仕様上、バグ認定)。
  • というのもNFSクライアント(CentOS 6.8)で postgres(26):postgres(26) のプロセスがアクセス(cd など)した時の、NFSサーバーへのユーザー問い合わせ結果を tcpdump(8)した結果、「postgres」ではなく「26」という文字列をNFSサーバーに問い合わせ(fattr_owner)ている現象を確認した。
  • なお、chown(8) や ls(1) した時には問題無い。
  • 本現象について調査したところ、下記のバグがレポートされていることを確認した。
  • バグレポートでは以下の点から、CentOS 6 系(少なくとも 6.8、2016年06月09日現在)以下には反映されていないものと考える。
    • バグレポートで言及されているディストリビューションが FedoraCore 17 である。

    • CentOS 6(RHEL6) は FedoraCore 12/13 ベースである。

    • 更に CentOS 6 の nfs-utils のバージョンは 1.2.3 であるが、FedoraCore 17 では 1.2.6 である。

    • FedoraCore 17 ベースの CentOS 7 では問題無いと思われる(未検証)。

領域の共有設定

共有設定

/export をどう共有するかによるが「/export/NFSv4クライアント名」として、クライアント単位で共有設定する場合は、下記のようにパーティションを切る。

zfs create -o sharenfs="-maproot=root NFSクライアントIP" export/NFSクライアント名

sharenfs 設定を行うと、/etc/zfs/exports ファイルに掃き出されるのと、合わせて mountd(8) に再読み込み(HUP シグナル)が実施される。

一つの領域を複数のNFSクライアント間で共有するなら、/etc/exports に集約するのが良いと思われ(未実験)。

なおNFSクライアントからは、「/NFSクライアント名」でマウントすることになる(/export がトップディレクトリとなって見えなくなる)。

更にお好みに応じて、exec=off、setuid=off も追加しよう。これはNFSサーバーとしてはこれら属性を「解釈しない」という意味であって、NFSクライアントはNFSクライアントで、別途設定が必要となる。

設定確認

mountd(8) の再読み込みによりNFSクライアントからマウントできるようになるわけだが、これが成功したのか失敗したのかはよくわからない。 そこで、「showmount -e」コマンドと「zfs get -t filesystem sharenfs」コマンドの実行結果を見比べて判断すること(設定した内容が反映されてないなど)。

# showmount -e
Exports list on localhost:
/export/NFSクライアント1       XXX.XXX.XXX.XXX
/export/NFSクライアント2       YYY.YYY.YYY.YYY
# zfs get -t filesystem sharenfs
NAME                                                  PROPERTY  VALUE                          SOURCE
export                                                sharenfs  off                            default
export/NFSクライアント1                           sharenfs  -maproot=root XXX.XXX.XXX.XXX  local
export/NFSクライアント2                           sharenfs  -maproot=root YYY.YYY.YYY.YYY  local

※zfs get sharenfs やべぇ。スナップショットもリストアップして大変な量に…。 orz

参考文献

NFSv4/サーバー (最終更新日時 2016-07-24 23:43:53 更新者 NorikatsuShigemura)