CentOS 6にSSHトンネリングしてNFSv4で共有
AWSでCentOS 6を立てて、NFSv4サーバを設置、別のCentOS 6からSSHでトンネリングしてNFSv4でマウントするというシナリオです。
想定される状況としては、「すでに稼働中のWebサーバを、物理的につながっていない別のサーバに移転しなくてはならないのだけれども、DNSの切替がスムーズにいかないことが予想されるので、先にコンテンツだけ移転先のサーバにNFSサーバを立ててあらかじめコピーしておき、その後Webサーバのファイルシステムを移転先のNFSサーバに切り替える」というものです。
- 移転先のNFSサーバへは2049/TCPでアクセスしない(新旧サーバ間の通信はインターネット経由なので平文が流れるNFSは通したくない)
- Webサーバから22/TCPのSSHトンネリングにて、セキュアな通信路を確保したうえで、2049/TCP(NFS)を通します。
IPで見た方が分かりやすいので、以降リアルIPそのままです。これ書いた後サーバは停止していますので今はつながらないです、あしからず。出てくるIPは、AmazonのAWSから付与されたIPと、spmodeから付与されたIPです。
移転先サーバ(NFSv4サーバ)のインストール・設定・起動
nfs-utilsをインストールします。依存関係に現れている、rpcbindは、CentOS 5ではportmapとなっていたパッケージですので、注意してください。
[root@ip-10-128-3-242 ~]# yum install nfs-utils Loaded plugins: fastestmirror Loading mirror speeds from cached hostfile * atomic: www4.atomicorp.com * base: www.ftp.ne.jp * elrepo: ftp.osuosl.org * epel: mirror01.th.ifl.net * extras: www.ftp.ne.jp * updates: www.ftp.ne.jp Setting up Install Process Resolving Dependencies --> Running transaction check ---> Package nfs-utils.x86_64 1:1.2.3-26.el6 will be installed --> Processing Dependency: nfs-utils-lib >= 1.1.0-3 for package: 1:nfs-utils-1.2.3-26.el6.x86_64 --> Processing Dependency: keyutils >= 1.4-4 for package: 1:nfs-utils-1.2.3-26.el6.x86_64 --> Processing Dependency: rpcbind for package: 1:nfs-utils-1.2.3-26.el6.x86_64 --> Processing Dependency: libtirpc for package: 1:nfs-utils-1.2.3-26.el6.x86_64 --> Processing Dependency: libgssglue.so.1(libgssapi_CITI_2)(64bit) for package: 1:nfs-utils-1.2.3-26.el6.x86_64 --> Processing Dependency: libgssglue for package: 1:nfs-utils-1.2.3-26.el6.x86_64 --> Processing Dependency: libevent for package: 1:nfs-utils-1.2.3-26.el6.x86_64 --> Processing Dependency: libtirpc.so.1()(64bit) for package: 1:nfs-utils-1.2.3-26.el6.x86_64 --> Processing Dependency: libnfsidmap.so.0()(64bit) for package: 1:nfs-utils-1.2.3-26.el6.x86_64 --> Processing Dependency: libgssglue.so.1()(64bit) for package: 1:nfs-utils-1.2.3-26.el6.x86_64 --> Processing Dependency: libevent-1.4.so.2()(64bit) for package: 1:nfs-utils-1.2.3-26.el6.x86_64 --> Running transaction check ---> Package keyutils.x86_64 0:1.4-4.el6 will be installed ---> Package libevent.x86_64 0:1.4.13-4.el6 will be installed ---> Package libgssglue.x86_64 0:0.1-11.el6 will be installed ---> Package libtirpc.x86_64 0:0.2.1-5.el6 will be installed ---> Package nfs-utils-lib.x86_64 0:1.1.5-4.el6 will be installed ---> Package rpcbind.x86_64 0:0.2.0-9.el6 will be installed --> Finished Dependency Resolution Dependencies Resolved ================================================================ Package Arch Version Repository Size ================================================================ Installing: nfs-utils x86_64 1:1.2.3-26.el6 base 316 k Installing for dependencies: keyutils x86_64 1.4-4.el6 base 39 k libevent x86_64 1.4.13-4.el6 base 66 k libgssglue x86_64 0.1-11.el6 base 23 k libtirpc x86_64 0.2.1-5.el6 base 78 k nfs-utils-lib x86_64 1.1.5-4.el6 base 67 k rpcbind x86_64 0.2.0-9.el6 base 51 k Transaction Summary =============================================================== Install 7 Package(s) Total download size: 640 k Installed size: 1.7 M Is this ok [y/N]: y Downloading Packages: ... Installed: nfs-utils.x86_64 1:1.2.3-26.el6 Dependency Installed: keyutils.x86_64 0:1.4-4.el6 libevent.x86_64 0:1.4.13-4.el6 libgssglue.x86_64 0:0.1-11.el6 libtirpc.x86_64 0:0.2.1-5.el6 nfs-utils-lib.x86_64 0:1.1.5-4.el6 rpcbind.x86_64 0:0.2.0-9.el6 Complete!
設定します
[root@ip-10-128-3-242 ~]# vi /etc/idmapd.conf [General] #Verbosity = 0 # The following should be set to the local NFSv4 domain name # The default is the host's DNS domain name. #Domain = local.domain.edu Domain = dtpwiki.jp ...
[root@ip-10-128-3-242 ~]# vi /etc/sysconfig/nfs # # Define which protocol versions mountd # will advertise. The values are "no" or "yes" # with yes being the default #MOUNTD_NFS_V2="no" #MOUNTD_NFS_V3="no" MOUNTD_NFS_V2="no" MOUNTD_NFS_V3="no" # # # Path to remote quota server. See rquotad(8) #RQUOTAD="/usr/sbin/rpc.rquotad" RQUOTAD=no # Port rquotad should listen on. #RQUOTAD_PORT=875 # Optinal options passed to rquotad #RPCRQUOTADOPTS="" # # # Optional arguments passed to in-kernel lockd #LOCKDARG= # TCP port rpc.lockd should listen on. #LOCKD_TCPPORT=32803 LOCKD_TCPPORT=32803 # UDP port rpc.lockd should listen on. #LOCKD_UDPPORT=32769 LOCKD_UDPPORT=32769 # # # Optional arguments passed to rpc.nfsd. See rpc.nfsd(8) # Turn off v2 and v3 protocol support #RPCNFSDARGS="-N 2 -N 3" RPCNFSDARGS="-N 2 -N 3 -U" # Turn off v4 protocol support #RPCNFSDARGS="-N 4" # Number of nfs server processes to be started. # The default is 8. #RPCNFSDCOUNT=8 # Stop the nfsd module from being pre-loaded #NFSD_MODULE="noload" # Set V4 grace period in seconds #NFSD_V4_GRACE=90 # # # # Optional arguments passed to rpc.mountd. See rpc.mountd(8) #RPCMOUNTDOPTS="" # Port rpc.mountd should listen on. #MOUNTD_PORT=892 # # # Optional arguments passed to rpc.statd. See rpc.statd(8) #STATDARG="" # Port rpc.statd should listen on. #STATD_PORT=662 # Outgoing port statd should used. The default is port # is random #STATD_OUTGOING_PORT=2020 # Specify callout program #STATD_HA_CALLOUT="/usr/local/bin/foo" # # # Optional arguments passed to rpc.idmapd. See rpc.idmapd(8) #RPCIDMAPDARGS="" # # Set to turn on Secure NFS mounts. #SECURE_NFS="yes" # Optional arguments passed to rpc.gssd. See rpc.gssd(8) #RPCGSSDARGS="" # Optional arguments passed to rpc.svcgssd. See rpc.svcgssd(8) #RPCSVCGSSDARGS="" # # To enable RDMA support on the server by setting this to # the port the server should listen on #RDMA_PORT=20049
NFSで共有したいディレクトリを設定します。通常、共有先のホストのIP範囲を指定するところが、自ホストのIPになっている点、SSHトンネリングによる通常とはちがうportからの接続に対応するためにinsecureを指定している点に注意してください。理由は後述③のnetstat -naの出力でわかります。
[root@ip-10-128-3-242 ~]# vi /etc/exports / 10.128.3.242/32(rw,sync,no_root_squash,insecure,fsid=0) [root@ip-10-128-3-242 ~]# /usr/sbin/exportfs -ra [root@ip-10-128-3-242 ~]# /usr/sbin/exportfs -v / 10.128.3.242/32(ro,wdelay,root_squash,no_subtree_check,fsid=0)
サービスを起動します。
[root@ip-10-128-3-242 ~]# /sbin/service rpcbind start rpcbind を起動中: [ OK ] [root@ip-10-128-3-242 ~]# /sbin/service rpcidmapd start RPC idmapd を起動中: [ OK ] [root@ip-10-128-3-242 ~]# /sbin/service nfs start NFS サービスを起動中: [ OK ] NFS mountd を起動中: [ OK ] RPC idmapd を停止中: [ OK ] RPC idmapd を起動中: [ OK ] NFS デーモンを起動中:
①サーバ側のnetstat -naです。IPv6の表示は省略。今回は、SSHでトンネルを掘って接続しますので、22/TCPだけファイアウォールを空けておいてください。太字は、rpcbindを起動すると現れる、不用なポートです。どうにかして消せないものか。
[root@ip-10-128-3-242 ~]# netstat -na Active Internet connections (servers and established) Proto Recv-Q Send-Q Local Address Foreign Address State tcp 0 0 0.0.0.0:111 0.0.0.0:* LISTEN tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN tcp 0 0 0.0.0.0:2049 0.0.0.0:* LISTEN tcp 0 0 0.0.0.0:32803 0.0.0.0:* LISTEN tcp 0 52 10.128.3.242:22 1.72.4.106:58643 ESTABLISHED udp 0 0 0.0.0.0:111 0.0.0.0:* udp 0 0 0.0.0.0:32769 0.0.0.0:* udp 0 0 0.0.0.0:951 0.0.0.0:* Active UNIX domain sockets (servers and established) ...
Webサーバ(NFSクライアント側)からマウント
クライアント側からマウントするにあたり、SSHで先にサーバまでトンネルを掘って(SSHトンネリング)、そこにNFSを通して接続します。
まず、トンネルを掘ります。
※このトンネルの掘り方には議論の余地があります。この用途に特化した、autosshていうのがありますので、そっちを使うべきでしょう。
[root@ip-10-146-70-17 ~]# ssh -f -N -i ~/.ssh/key.pem -L 2049:10.128.3.242:2049 root@10.128.3.242
②このときのサーバ側のnetstatは以下の通り。太字は、SSHトンネリングで掘ったトンネルです。
[root@ip-10-128-3-242 ~]# netstat -na Active Internet connections (servers and established) Proto Recv-Q Send-Q Local Address Foreign Address State tcp 0 0 0.0.0.0:111 0.0.0.0:* LISTEN tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN tcp 0 0 0.0.0.0:2049 0.0.0.0:* LISTEN tcp 0 0 0.0.0.0:32803 0.0.0.0:* LISTEN tcp 0 0 10.128.3.242:22 10.146.70.17:55764 ESTABLISHED tcp 0 52 10.128.3.242:22 1.72.4.106:58643 ESTABLISHED udp 0 0 0.0.0.0:111 0.0.0.0:* udp 0 0 0.0.0.0:32769 0.0.0.0:* udp 0 0 0.0.0.0:951 0.0.0.0:* Active UNIX domain sockets (servers and established) ...
マウントします。普通共有元のサーバを指定するところが、localhostになっている点に注意してください。
[root@ip-10-146-70-17 ~]# mount -t nfs4 -o hard,intr localhost:/ /mnt [root@ip-10-146-70-17 ~]# ls /mnt/ bin boot dev etc home lib lib64 lost+found media mnt opt proc root sbin selinux srv sys tmp usr var [root@ip-10-146-70-17 ~]#
共有できました。
③最終的なnetstatです。太字のところは、サーバ内でトンネルの出口からNFSへの接続が確立されているという様子です。
[root@ip-10-128-3-242 ~]# netstat -na Active Internet connections (servers and established) Proto Recv-Q Send-Q Local Address Foreign Address State tcp 0 0 0.0.0.0:111 0.0.0.0:* LISTEN tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN tcp 0 0 0.0.0.0:2049 0.0.0.0:* LISTEN tcp 0 0 0.0.0.0:32803 0.0.0.0:* LISTEN tcp 0 0 10.128.3.242:50115 10.128.3.242:2049 ESTABLISHED tcp 0 0 10.128.3.242:2049 10.128.3.242:50115 ESTABLISHED tcp 0 0 10.128.3.242:22 10.146.70.17:55764 ESTABLISHED tcp 0 52 10.128.3.242:22 1.72.4.106:58643 ESTABLISHED udp 0 0 0.0.0.0:111 0.0.0.0:* udp 0 0 0.0.0.0:32769 0.0.0.0:* udp 0 0 0.0.0.0:951 0.0.0.0:* Active UNIX domain sockets (servers and established) ... [root@ip-10-128-3-242 ~]#
でき上ったシステムに対する評価
現在稼働しているWebサーバのファイルシステムを、新しいサーバのNFSに置き換える用途であるとして、このシステムで実現するとなると、以下のような問題点が考えられます。
- SSHトンネリングということであるが、SSHは通信路の切断に弱い。定常的に利用するのは難しいのではないか。
- NFSでファイルシステムを置き換える場合、キャッシュが効かず、毎回NFSにファイルをリクエストすることになるから、速度や、通信量の面で問題はないか。
1.については、当然品質の高いインターネット回線を確保することも必要ですが、さらにautosshによるSSHセッションの自動貼り直しツールを使うのも有効でしょう。
2.については、つまり一度読みこんだコンテンツをキャッシュするような仕組みの導入を考えればよいわけですが、昔からあるmod_cacheなどのApache内での解決を試みるのもありでしょうが、せっかくなのでNFSにキャッシュを組み込めるcachefilesdを使うことも検討して見られたらいかがでしょうか。