X

News, tips, partners, and perspectives for the Oracle Solaris operating system

PxFS の紹介とグローバルマウントの考察

Guest Author

Sun Cluster ソフトウェアをお使いであれば、プロキシファイルシステム (Proxy File System、PxFS) の使用をお勧めします。PxFS はグローバルデバイスを可能にします。グローバルデバイスとは、クラスタのデバイス管理の中核をなすものです。ソースが公開されるようになったこともあり、PxFS の利点を説明できる環境は整っています。PxFS アーキテクチャーの概要について、ソースを参照しながら説明したいと思います。ほかのいくつかのブログエントリも参照したいと思います。このエントリでは、PxFS の紹介とグローバルマウントの説明をいたします。

PxFS は、POSIX に準拠し、高可用性を保ちながら、クラスタノード間にディスクベースのファイルシステムを配置するプロトコルレイヤーです。アプリケーションにファイルレベルのロックを要求しなくても、POSIX に準拠したうえで、複数のノードから同時にアクセスすることができます。グローバルマウントを行う際に管理者に求められる作業は、すべてのクラスタノード上にマウントポイントが存在していることの確認だけです。確認後、マウントコマンドに "-g" を付けると、マウントがグローバルになります。次のブログエントリで用語について解説しています

最初に、専用の物理デバイスを使用しなくても UFS ファイルシステムの作成とグローバルマウントを簡単に行えることを示したいと思います。では、lofi デバイスを作成し、そのデバイスを UFS でフォーマットし、グローバルマウントしてみましょう。

注意: この操作は Solaris 9 では行わないでください。このバージョンにはシステムパニックを発生させる可能性のある lofs バグが含まれているためです。


# mkfile 100m /var/tmp/100m
# LOFIDEV=`lofiadm -a /var/tmp/100m`
# yes | newfs ${LOFIDEV}

では、この lofi デバイスをクラスタ全体にマウントします (すべてのノード上にターゲットディレクトリが存在することを確認してください)。



# mount -g ${LOFIDEV} /mnt

完了です。これでクラスタのどのノードでも /mnt にアクセスでき、node1 上の lofi デバイスの UFS ファイルシステムに透過的にアクセスできます。

では、グローバルマウントについて詳しく見ていきましょう。ここでは、共有ストレージにファイルシステムをグローバルマウントする方法を例に話を進めます。3 つのノードで構成されるクラスタがあります。そして、node2 および node3 は共有ストレージに直接接続されていると想定します。"/dev/md/mydg/dsk/d42" という svm メタデバイスを、node1 のディレクトリ "/global/answer" にグローバルマウントすることにします。

コードについては、PxFS サービスの起動を参照してください。

マウントサブシステムは HA サービスです。クラスタ用語である HA サービスというのは、フェイルオーバー機能を持つことを意味します。HA サービスには、1 つのプライマリおよび 1 つまたは複数のセカンダリが備わっています。現在のプライマリがダウンすると、どのセカンダリでもプライマリになれます。セカンダリからプライマリへの昇格は、アプリケーションに対し透過的に行われます。

どのクラスタ セットアップにおいても、マウントサービスプライマリは常に 1 つのみです。ほかのすべてのノードにはマウントサービスセカンダリが含まれています。各クラスタノードには、グローバルマウントがノードで最初に有効化されたときに作成されたマウントクライアントもあります。

マウントプライマリおよびマウントセカンダリは、ノードのクラスタ参加時に作成される、二面のマウントレプリカオブジェクトです。このコードは、マウントレプリカサーバーを作成するものです。レプリカフレームワークにより、一度に 1 つのみのプライマリが存在し、必要に応じてセカンダリからプライマリへの昇格が確実に行われるようになっています。

では、グローバルマウントを行う際の一連の処理について説明します。下の図をご覧ください。グローバルマウントの各手順が、順番に示されています。番号にマウスをポイントすると、各手順のツールヒントが対応コードのリンクとともに表示されます。




Step 1href="javascript:void(0)"
onmouseover="Tip('The global mount command, mount -g, can be issued from any cluster node. It gets into the kernel and a generic mount redirects the call to PxFS. At this point, the directory to be mounted on is locked.
onnv-gate/usr/src/uts/common/syscall/mount.c#125
ohac/ohac/usr/src/common/cl/pxfs/client/pxvfs.cc#594', WIDTH, 400, TITLE, 'Step 1 for a global mount', SHADOW, true, FADEIN, 300, FADEOUT, 300, STICKY, 1, CLOSEBTN, true, CLICKCLOSE, true)"
onmouseout="UnTip()" />
Step 2href="javascript:void(0)"
onmouseover="Tip('The PxFS client tells the mount server about this global mount request via the mount client on that node. The mount client will have the server reference.
ohac/ohac/usr/src/common/cl/pxfs/client/pxvfs.cc#999', WIDTH, 400, TITLE, 'Step 2 for a global mount', SHADOW, true, FADEIN, 300, FADEOUT, 300, STICKY, 1, CLOSEBTN, true, CLICKCLOSE, true)"
onmouseout="UnTip()" />
Step 3href="javascript:void(0)"
onmouseover="Tip('The mount server in turn asks every client except the originating node, in this case node1, to lock the mount point.
ohac/ohac/usr/src/common/cl/pxfs/mount/mount_server_impl.cc#1204', WIDTH, 400, TITLE, 'Step 3 for a global mount', SHADOW, true, FADEIN, 300, FADEOUT, 300, STICKY, 1, CLOSEBTN, true, CLICKCLOSE, true)"
onmouseout="UnTip()" />
Step 3href="javascript:void(0)"
onmouseover="Tip('The mount server in turn asks every client except the originating node, in this case node1, to lock the mount point.
ohac/ohac/usr/src/common/cl/pxfs/mount/mount_server_impl.cc#1204', WIDTH, 400, TITLE, 'Step 3 for a global mount', SHADOW, true, FADEIN, 300, FADEOUT, 300, STICKY, 1, CLOSEBTN, true, CLICKCLOSE, true)"
onmouseout="UnTip()" />
Step 4href="javascript:void(0)"
onmouseover="Tip('

For shared devices, the mount server creates a PxFS primary and secondary. The node on which the device is primaried becomes the PxFS primary. For local devices, the mount is non-HA and an unreplicated PxFS server is created. The lofi device example, above, will result in an unreplicated PxFS server being created on node1.

The PxFS server does a hidden mount of the device. Details of the mount is contained in the PxFS server object.

ohac/ohac/usr/src/common/cl/pxfs/mount/mount_server_impl.cc#1237
ohac/ohac/usr/src/common/cl/pxfs/server/repl_pxfs_server.cc#125', WIDTH, 400, TITLE, 'Step 4 for a global mount', SHADOW, true, FADEIN, 300, FADEOUT, 300, STICKY, 1, CLOSEBTN, true, CLICKCLOSE, true)"
onmouseout="UnTip()" />
Step 4href="javascript:void(0)"
onmouseover="Tip('

For shared devices, the mount server creates a PxFS primary and secondary. The node on which the device is primaried becomes the PxFS primary. For local devices, the mount is non-HA and an unreplicated PxFS server is created. The lofi device example, above, will result in an unreplicated PxFS server being created on node1.

The PxFS server does a hidden mount of the device. Details of the mount is contained in the PxFS server object.

ohac/ohac/usr/src/common/cl/pxfs/mount/mount_server_impl.cc#1237
ohac/ohac/usr/src/common/cl/pxfs/server/repl_pxfs_server.cc#125', WIDTH, 400, TITLE, 'Step 4 for a global mount', SHADOW, true, FADEIN, 300, FADEOUT, 300, STICKY, 1, CLOSEBTN, true, CLICKCLOSE, true)"
onmouseout="UnTip()" />
Step 5href="javascript:void(0)"
onmouseover="Tip('The mount server passes a reference to the newly created server to all mount clients and asks the clients to do a user-visible PxFS mount.
ohac/ohac/usr/src/common/cl/pxfs/mount/mount_server_impl.cc#1438
ohac/ohac/usr/src/common/cl/pxfs/mount/mount_server_impl.cc#1684', WIDTH, 400, TITLE, 'Step 5 for a global mount', SHADOW, true, FADEIN, 300, FADEOUT, 300, STICKY, 1, CLOSEBTN, true, CLICKCLOSE, true)"
onmouseout="UnTip()" />
Step 5href="javascript:void(0)"
onmouseover="Tip('The mount server passes a reference to the newly created server to all mount clients and asks the clients to do a user-visible PxFS mount.
ohac/ohac/usr/src/common/cl/pxfs/mount/mount_server_impl.cc#1438
ohac/ohac/usr/src/common/cl/pxfs/mount/mount_server_impl.cc#1684', WIDTH, 400, TITLE, 'Step 5 for a global mount', SHADOW, true, FADEIN, 300, FADEOUT, 300, STICKY, 1, CLOSEBTN, true, CLICKCLOSE, true)"
onmouseout="UnTip()" />
Step 5href="javascript:void(0)"
onmouseover="Tip('The mount server passes a reference to the newly created server to all mount clients and asks the clients to do a user-visible PxFS mount.
ohac/ohac/usr/src/common/cl/pxfs/mount/mount_server_impl.cc#1438
ohac/ohac/usr/src/common/cl/pxfs/mount/mount_server_impl.cc#1684', WIDTH, 400, TITLE, 'Step 5 for a global mount', SHADOW, true, FADEIN, 300, FADEOUT, 300, STICKY, 1, CLOSEBTN, true, CLICKCLOSE, true)"
onmouseout="UnTip()" />
Step 6href="javascript:void(0)"
onmouseover="Tip('The mount client creates and adds a vfs_t entry of the same type as the underlying file system.
ohac/ohac/usr/src/common/cl/pxfs/mount/mount_client_impl.cc#1804
ohac/ohac/usr/src/common/cl/pxfs/mount/mount_client_impl.cc#1817', WIDTH, 400, TITLE, 'Step 6 for a global mount', SHADOW, true, FADEIN, 300, FADEOUT, 300, STICKY, 1, CLOSEBTN, true, CLICKCLOSE, true)"
onmouseout="UnTip()" />
Step 6href="javascript:void(0)"
onmouseover="Tip('The mount client creates and adds a vfs_t entry of the same type as the underlying file system.
ohac/ohac/usr/src/common/cl/pxfs/mount/mount_client_impl.cc#1804
ohac/ohac/usr/src/common/cl/pxfs/mount/mount_client_impl.cc#1817', WIDTH, 400, TITLE, 'Step 6 for a global mount', SHADOW, true, FADEIN, 300, FADEOUT, 300, STICKY, 1, CLOSEBTN, true, CLICKCLOSE, true)"
onmouseout="UnTip()" />
Step 6href="javascript:void(0)"
onmouseover="Tip('The mount client creates and adds a vfs_t entry of the same type as the underlying file system.
ohac/ohac/usr/src/common/cl/pxfs/mount/mount_client_impl.cc#1804
ohac/ohac/usr/src/common/cl/pxfs/mount/mount_client_impl.cc#1817', WIDTH, 400, TITLE, 'Step 6 for a global mount', SHADOW, true, FADEIN, 300, FADEOUT, 300, STICKY, 1, CLOSEBTN, true, CLICKCLOSE, true)"
onmouseout="UnTip()" />

ここからは、上の図の手順をわかりやすく説明していきます。


  1. グローバルマウントコマンド mount -g は、どのクラスタノードからでも発行できます。このコマンドがカーネルに入ると、汎用マウントがこの呼び出しを PxFS にリダイレクトします。この時点で、マウントされるディレクトリがロックされます。

    http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/uts/common/syscall/mount.c#125 http://src.opensolaris.org/source/xref/ohac/ohac/usr/src/common/cl/pxfs/client/pxvfs.cc#594

  2. PxFS クライアントは、マウントサーバーにこのグローバルマウント要求を自分のノード上のマウントクライアントを介して通知します。マウントクライアントはサーバー参照を持つようになります。

    http://src.opensolaris.org/source/xref/ohac/ohac/usr/src/common/cl/pxfs/client/pxvfs.cc#999

  3. マウントサーバーは元のノード (この例では node1) 以外の各クライアントに、マウントポイントをロックするように要求します。

    http://src.opensolaris.org/source/xref/ohac/ohac/usr/src/common/cl/pxfs/mount/mount_server_impl.cc#1204

  4. 共有デバイスでは、マウントサーバーは PxFS プライマリおよび PxFS セカンダリを作成します。プライマリデバイスが存在するノードが PxFS プライマリになります。ローカルデバイスでは、マウントは HA ではなく、レプリケートされていない PxFS サーバーが作成されます。上の例での lofi デバイスでは、node1 に作成される PxFS サーバーはレプリケートされていないものになります。

    PxFS サーバーはデバイスの非表示マウントを行います。マウントの詳細情報は PxFS サーバーオブジェクトに含まれています。

    http://src.opensolaris.org/source/xref/ohac/ohac/usr/src/common/cl/pxfs/mount/mount_server_impl.cc#1237 http://src.opensolaris.org/source/xref/ohac/ohac/usr/src/common/cl/pxfs/server/repl_pxfs_server.cc#125

  5. マウントサーバーは新たに作成されたサーバーへの参照をすべてのマウントクライアントに渡し、ユーザーに見えるかたちで PxFS マウントを行うようマウントクライアントに要求します。

    http://src.opensolaris.org/source/xref/ohac/ohac/usr/src/common/cl/pxfs/mount/mount_server_impl.cc#1438 http://src.opensolaris.org/source/xref/ohac/ohac/usr/src/common/cl/pxfs/mount/mount_server_impl.cc#1684

  6. マウントクライアントは、基盤のファイルシステムと同種類の vfs_t エントリを作成し、これを追加します。

    http://src.opensolaris.org/source/xref/ohac/ohac/usr/src/common/cl/pxfs/mount/mount_client_impl.cc#1804 http://src.opensolaris.org/source/xref/ohac/ohac/usr/src/common/cl/pxfs/mount/mount_client_impl.cc#1817

これですべてのクライアント上でマウントが表示されるようになりました。マウントサブシステムが提供する優れた機能はほかにもあります。たとえば、ノードがクラスタに参加するときに fs レプリカを起動したり、ストレージに接続されたノードがクラスタに参加するときに新たに PxFS セカンダリやプライマリを作成したりします。次回は PxFS での通常のファイルアクセスの動作についてお話しします。

Walter Zorn 氏の javascript ライブラリを利用させていただき、わかりやすいツールヒントを作成することができました。ここにお礼を申し上げます。


Binu Philip
Solaris Cluster エンジニアリング

Be the first to comment

Comments ( 0 )
Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.