web-dev-qa-db-ja.com

バインドマウントとは何ですか?

「バインドマウント」とは何ですか?どうやって作るの?何がいいの?

何かにバインドマウントを使用するように言われましたが、それが何であるか、またはどのように使用するのかわかりません。

バインドマウントとは何ですか?

bind mountは、ディレクトリツリーの代替ビューです。古典的には、マウントすると、ストレージツリーがディレクトリツリーとして表示されます。代わりに、バインドマウントは既存のディレクトリツリーを取得し、それを別のポイントに複製します。バインドマウントのディレクトリとファイルは、元のディレクトリと同じです。 2つのビューは同じデータを表示するため、片側の変更はすぐに反対側に反映されます。

たとえば、Linuxコマンドを発行した後

mount --bind /some/where /else/where

ディレクトリ/some/where/else/whereの内容は同じです。

ハードリンクやシンボリックリンクとは異なり、バインドマウントはファイルシステムに格納されているものに影響を与えません。これはライブシステムのプロパティです。

バインドマウントを作成するにはどうすればよいですか?

bindfs

bindfs ファイルシステムは、ディレクトリツリーのビューを作成する Fuse ファイルシステムです。たとえば、次のコマンド

bindfs /some/where /else/where

/else/whereを、/some/whereの内容が表示されるマウントポイントにします。

Bindfsは独立したファイルシステムであるため、ファイル/some/where/foo/else/where/fooは、アプリケーションでは異なるファイルとして表示されます(bindfsファイルシステムには独自のst_dev値があります)。一方の変更は「魔法のように」もう一方の側に反映されますが、ファイルが同じであるという事実は、bindfsの動作を知っている場合にのみ明らかになります。

Bindfsはマウントポイントを認識しないため、/some/whereの下にマウントポイントがある場合、/else/whereの下の単なる別のディレクトリとして表示されます。 /some/whereの下のファイルシステムをマウントまたはアンマウントすると、対応するディレクトリの変更として/else/whereの下に表示されます。

Bindfsは一部のファイルメタデータを変更する可能性があります。ファイルの偽のアクセス許可と所有権を表示できます。詳細については manual を、例については以下を参照してください。

Bindfsファイルシステムは非rootユーザーとしてマウントできます。Fuseファイルシステムをマウントするための特権のみが必要です。ディストリビューションによっては、これをFuseグループに含めるか、すべてのユーザーに許可する必要がある場合があります。 Fuseファイルシステムをマウント解除するには、umountの代わりにfusermount -uを使用します。

fusermount -u /else/where

nullfs

FreeBSDは、ファイルシステムの代替ビューを作成する nullfs ファイルシステムを提供します。次の2つのコマンドは同等です。

mount -t nullfs /some/where /else/where
mount_nullfs /some/where /else/where

いずれかのコマンドを発行した後、/else/whereは、/some/whereの内容が表示されるマウントポイントになります。

Nullfsは独立したファイルシステムであるため、ファイル/some/where/foo/else/where/fooは、アプリケーションに対して異なるファイルとして表示されます(nullfsファイルシステムには独自のst_dev値があります)。一方の変更は「魔法のように」反対側に反映されますが、ファイルが同じであるという事実は、nullfsの動作を知っている場合にのみ明らかになります。

ディレクトリツリーのレベルで機能するFuse bindfsとは異なり、FreeBSDのnullfsはカーネル内でより深く機能するため、/else/whereの下のマウントポイントは表示されません。/some/whereと同じマウントポイントの一部であるツリーのみが/else/whereに反映されます。

Nullfsファイルシステムは、他のBSDバリアント(OS X、OpenBSD、NetBSD)で使用できる場合がありますが、デフォルトシステムの一部としてコンパイルされていません。

Linuxバインドマウント

Linuxでは、バインドマウントはカーネル機能として使用できます。 mount コマンドを使用して、--bindコマンドラインオプションまたはbindマウントオプションを渡すことにより、1つを作成できます。次の2つのコマンドは同等です。

mount --bind /some/where /else/where
mount -o bind /some/where /else/where

ここで、「デバイス」/some/whereは、ディスク上のファイルシステムの場合のようなディスクパーティションではなく、既存のディレクトリです。マウントポイント/else/whereは、通常どおり既存のディレクトリでなければなりません。どちらの方法でもファイルシステムタイプが指定されていないことに注意してください。バインドマウントの作成にはファイルシステムドライバーは含まれず、元のマウントからカーネルデータ構造がコピーされます。

mount --bindは、非ディレクトリーへの非ディレクトリーのマウントもサポートします。/some/whereは通常のファイルにすることができます(この場合、/else/whereも通常のファイルである必要があります)。

Linuxバインドマウントは、元のマウントとほとんど区別がつきません。コマンドdf -T /else/whereは、df -T /some/whereと同じデバイスおよび同じファイルシステムタイプを示します。ファイル/some/where/foo/else/where/fooは、ハードリンクであるかのように区別できません。 /some/whereをマウント解除することができます。その場合、/else/whereはマウントされたままになります。

古いカーネルでは(いつかは正確にはわかりませんが、3.xまではそう思います)、バインドマウントは元のカーネルとまったく区別できませんでした。最近のカーネルはバインドマウントを追跡し、PID/mountinfoを介して情報を公開します。これにより、 findmntがバインドマウントを示すことができます

バインドマウントエントリを/etc/fstabに配置できます。オプションにbind(またはrbindなど)を、必要な他のオプションと一緒に含めるだけです。 「デバイス」は既存のツリーです。ファイルシステム列にはnoneまたはbindを含めることができます(無視されますが、ファイルシステム名を使用すると混乱を招きます)。例えば:

/some/where /readonly/view none bind,ro

/some/whereの下にマウントポイントがある場合、その内容は/else/whereの下には表示されません。 bindの代わりにrbindを使用できます。また、/some/whereの下のマウントポイントを複製できます。たとえば、/some/where/mntがマウントポイントの場合

mount --rbind /some/where /else/where

に相当

mount --bind /some/where /else/where
mount --bind /some/where/mnt /else/where/mnt

さらに、Linuxではマウントをsharedslaveprivateまたはnbindableとして宣言できます。これは、そのマウント操作が、マウントポイントを複製するバインドマウントに反映されるかどうかに影響します。詳細については、 カーネルのドキュメント を参照してください。

Linuxはマウントを移動する方法も提供します。ここで、--bindはコピーし、--moveはマウントポイントを移動します。

2つのバインドマウントディレクトリに異なるマウントオプションを設定することができます。ただし、奇妙な点があります。バインドマウントの作成とマウントオプションの設定は、アトミックに実行できないため、2つの連続した操作である必要があります。 (古いカーネルはこれを許可していませんでした。)たとえば、次のコマンドは読み取り専用ビューを作成しますが、/else/whereが読み取り/書き込みである短い時間枠があります。

mount --bind /some/where /else/where
mount -o remount,ro,bind /else/where

バインドマウントが機能しません。

システムがFuseをサポートしていない場合、同じ効果を得るための古典的なトリックは、NFSサーバーを実行し、公開するファイルをエクスポートして(localhostへのアクセスを許可)、同じファイルにマウントすることです。機械。これはメモリとパフォーマンスの点でかなりのオーバーヘッドがあるため、バインドマウントは利用可能な場合に明確な利点があります(これはFuseのおかげでほとんどのUnixバリアントにあります)。

ユースケース

読み取り専用ビュー

セキュリティ上の理由から、または誤って変更しないようにするための安全のレイヤーとして、ファイルシステムの読み取り専用のビューを作成すると便利です。

Bindfsの場合:

bindfs -r /some/where /mnt/readonly

Linuxでは、簡単な方法:

mount --bind /some/where /mnt/readonly
mount -o remount,ro,bind /mnt/readonly

これにより、/mnt/readonlyが読み書き可能な短い間隔が残ります。これがセキュリティ上の問題である場合は、最初にルートのみがアクセスできるディレクトリにバインドマウントを作成し、読み取り専用にしてから、パブリックマウントポイントに移動します。以下のスニペットでは、/root/private(マウントポイントの上のディレクトリ)がプライベートであることが重要です。 /root/private/mntの元の権限は、マウントポイントの背後に隠されているため、無関係です。

mkdir -p /root/private/mnt
chmod 700 /root/private
mount --bind /some/where /root/private/mnt
mount -o remount,ro,bind /root/private/mnt
mount --move /root/private/mnt /mnt/readonly

ユーザーとグループの再マッピング

ファイルシステムは、ユーザーとグループを数値IDで記録します。場合によっては、同じユーザーに異なるユーザーIDを割り当てる複数のシステムになることがあります。これはネットワークアクセスの問題ではありませんが、ディスク上のあるシステムから別のシステムにデータを運ぶときにユーザーIDを無意味にします。 AliceがユーザーID 1000を持ち、BobがユーザーID 1001を持っているシステムに、マルチユーザーファイルシステム(例:ext4、btrfs、zfs、UFSなど)で作成されたディスクがあり、そのディスクにアクセスできるようにするとします。 AliceのユーザーIDが1001で、BobのユーザーIDが1000のシステム。ディスクを直接マウントすると、AliceのファイルはBobが所有していると表示され(ユーザーIDが1001であるため)、BobのファイルはAliceが所有していると表示されます(ユーザーIDは1000です)。

Bindfsを使用してユーザーIDを再マップできます。まず、ディスクパーティションをプライベートディレクトリにマウントします。ここで、rootだけがアクセスできます。次に、AliceとBobのユーザーIDとグループIDを交換するユーザーIDとグループIDの再マッピングを使用して、パブリックエリアにbindfsビューを作成します。

mkdir -p /root/private/alice_disk /media/alice_disk
chmod 700 /root/private
mount /dev/sdb1 /root/private/alice_disk
bindfs --map=1000/1001:1001/1000:@1000/1001:@1001/1000 /root/private/alice_disk /media/alice_disk

を参照してください起動されていないシステムのユーザーのホームフォルダーにあるファイルにどのようにアクセスできますか? および mount-他のユーザーを自分自身としてバインド 別の例。

刑務所またはコンテナへの取り付け

chroot jail または container は、システムのディレクトリツリーのサブツリーでプロセスを実行します。これは、アクセスが制限されたプログラムを実行するのに役立ちます。自身のファイルとサーバーが提供するファイルのみにアクセスし、同じコンピューターに保存されている他のデータにはアクセスできないネットワークサーバーを実行します。 chrootの制限は、プログラムが1つのサブツリーに限定されていることです。独立したサブツリーにはアクセスできません。バインドマウントを使用すると、他のサブツリーをそのメインツリーに移植できます。これにより、Linuxでのコンテナーの最も実用的な使用法の基礎となります。

たとえば、マシンが/usr/sbin/somethingdの下のデータにのみアクセスできるサービス/var/lib/somethingを実行するとします。これらのファイルの両方を含む最小のディレクトリツリーがルートです。サービスをどのように制限できますか? 1つの可能性は、サービスが必要とするすべてのファイル(少なくとも/usr/sbin/somethingdおよびいくつかの共有ライブラリ)へのハードリンクを/var/lib/somethingの下に作成することです。しかし、これは扱いにくく(ファイルをアップグレードするたびにハードリンクを更新する必要があります)、/var/lib/something/usrが異なるファイルシステムにある場合は機能しません。より良い解決策は、アドホックルートを作成し、マウントを使用してそこにデータを追加することです。

mkdir /run/something
cd /run/something
mkdir -p etc/something lib usr/lib usr/sbin var/lib/something
mount --bind /etc/something etc/something
mount --bind /lib lib
mount --bind /usr/lib usr/lib
mount --bind /usr/sbin usr/sbin
mount --bind /var/lib/something var/lib/something
mount -o remount,ro,bind etc/something
mount -o remount,ro,bind lib
mount -o remount,ro,bind usr/lib
mount -o remount,ro,bind usr/sbin
chroot . /usr/sbin/somethingd &

Linuxの mount名前空間 はchrootを一般化します。バインドマウントは、名前空間を柔軟な方法で設定する方法です。例については、 プロセスに同じファイル名の別のファイルを読み取らせる を参照してください。

別のディストリビューションを実行する

Chrootsのもう1つの用途は、ディレクトリに別のディストリビューションをインストールして、そこからプログラムを実行することです。ベースシステム上に存在しない、またはコンテンツが異なるハードコーディングされたパスにファイルが必要な場合でもです。これは、たとえば、混合パッケージをサポートしていない64ビットシステムに32ビットのディストリビューションをインストールしたり、互換性をテストするために古いリリースのディストリビューションや他のディストリビューションをインストールしたり、新しいリリースをインストールしてテストしたりするのに役立ちます。 Debian/Ubuntuの例については、 64ビットのDebian/Ubuntuで32ビットプログラムを実行するにはどうすればよいですか? を参照してください。

/f/unstableディレクトリの下にディストリビューションの最新パッケージがインストールされていて、chroot /f/unstableでそのディレクトリに切り替えてプログラムを実行するとします。このインストールからホームディレクトリを利用できるようにするには、それらをchrootにバインドマウントします。

mount --bind /home /f/unstable/home

プログラム schroot はこれを自動的に行います。

マウントポイントの背後に隠されているファイルへのアクセス

ファイルシステムをディレクトリにマウントすると、ディレクトリの背後にあるものが隠されます。そのディレクトリ内のファイルは、ディレクトリがアンマウントされるまでアクセスできなくなります。 BSD nullfsおよびLinuxバインドマウントはマウントインフラストラクチャよりも低いレベルで動作するため、ファイルシステムのnullfsマウントまたはバインドマウントは、元のサブマウントの背後に隠されていたディレクトリを公開します。

たとえば、/tmpにtmpfsファイルシステムがマウントされているとします。 tmpfsファイルシステムが作成されたときに/tmpの下にファイルがあった場合、これらのファイルはそのまま残り、実質的にアクセスできなくなりますが、ディスク領域を占有します。走る

mount --bind / /mnt

(Linux)または

mount -t nullfs / /mnt

(FreeBSD)/mntにルートファイルシステムのビューを作成します。ディレクトリ/mnt/tmpは、ルートファイルシステムからのディレクトリです。

異なるパスでのNFSエクスポート

一部のNFSサーバー(NFSv4の前のLinuxカーネルNFSサーバーなど)は、ディレクトリをエクスポートするときに常に実際のディレクトリの場所を通知します。つまり、クライアントがserver:/requested/locationを要求すると、サーバーは/requested/locationの場所でツリーを提供します。クライアントが/request/locationをリ​​クエストできるようにすることが望ましい場合がありますが、実際には/actual/locationでファイルを提供します。 NFSサーバーが別の場所でのサービスをサポートしていない場合は、期待されるリクエストのバインドマウントを作成できます。

/requested/location *.localdomain(rw,async)

/etc/exports内、および/etc/fstab内の以下:

/actual/location /requested/location bind bind

シンボリックリンクの代替

シンボリックリンクを作成してファイルを/some/where/is/my/file/else/whereの下に表示したい場合がありますが、fileを使用するアプリケーションはシンボリックリンクを展開し、/some/where/is/my/fileを拒否します。バインドマウントはこれを回避できます:bind-mount /some/where/is/my to /else/where/is/myそして、 realpath は、/else/where/is/my/file/else/whereの下ではなく/some/whereの下にあると報告します。

バインドマウントの副作用

再帰的なディレクトリ走査

バインドマウントを使用する場合は、バックアップやインデックス作成など、ファイルシステムツリーを再帰的に走査するアプリケーションに注意する必要があります(たとえば、 locate データベースを構築するため)。

通常、バインドマウントは、再帰的なディレクトリトラバーサルから除外する必要があります。これにより、各ディレクトリツリーは、元の場所で一度だけトラバースされます。 bindfsとnullfsを使用して、可能であれば、これらのファイルシステムタイプを無視するように走査ツールを構成します。 Linuxバインドマウントはそのように認識できません。新しい場所は元の場所と同じです。 Linuxバインドマウント、またはファイルシステムタイプではなくパスのみを除外できるツールを使用する場合は、バインドマウントのマウントポイントを除外する必要があります。

ファイルシステムの境界(たとえば、find -xdevrsync -xdu -x、…)で停止するトラバーサルは、bindfsまたはnullfsマウントポイントが検出されると、そのマウントポイントが別のファイルシステムであるため、自動的に停止します。 Linuxバインドマウントを使用すると、状況は少し複雑になります。ファイルシステムの境界は、バインドマウントが別のファイルシステムを移植している場合のみであり、同じファイルシステムの別の部分を移植している場合ではありません。

バインドマウントを超えて

バインドマウントは、別の場所にあるディレクトリツリーのビューを提供します。それらは同じファイルを公開しますが、おそらくマウントオプションが異なり、(bindfsを使用して)所有権と権限が異なります。ディレクトリツリーのビューが変更されたファイルシステムは、overlay filesystemsまたはstackable filesystemsと呼ばれます。より高度な変換を実行する他の多くのオーバーレイファイルシステムがあります。ここにいくつかの一般的なものがあります。ここで目的のユースケースがカバーされていない場合は、Fuseファイルシステムの リポジトリをチェックしてください .

表示ファイルをフィルタリングする

  • clamfs —ファイルが読み取られたときにウイルススキャナーを介して実行する
  • filterfs —ファイルシステムの一部を隠す
  • rofs —読み取り専用ビュー。 bindfs -rと同様に、もう少し軽量です。
  • Union mounts —単一のディレクトリの下に複数のファイルシステム(branchesと呼ばれる)を表示します:tree1fooが含まれ、tree2barすると、それらのユニオンビューにはfoobarの両方が含まれます。新しいファイルは、特定のブランチ、またはより複雑なルールに従って選択されたブランチに書き込まれます。この概念には、次のようないくつかの実装があります。

ファイル名とメタデータを変更する

  • ciopfs —大文字と小文字を区別しないファイル名(Windowsファイルシステムのマウントに役立ちます)
  • convmvfs —文字セット間でファイル名を変換します( example
  • posixovl — VFAT( example )などのより制限されたファイルシステムにUnixファイル名とその他のメタデータ(権限、所有権など)を保存します

変更されたファイルの内容を表示する

  • avfs —各アーカイブファイルについて、アーカイブのコンテンツを含むディレクトリを表示します( exampleその他の例 )。特定のアーカイブをディレクトリとして公開する Fuseファイルシステムも多数あります
  • fuseflt —ファイルを読み取るときに、パイプラインを介してファイルを実行します。テキストファイルまたはメディアファイルを再コーディングするには( example
  • lzopfs —圧縮ファイルの透過的な解凍
  • mp3fs — FLACファイルが読み込まれたときにMP3にトランスコードします( example
  • scriptfs —スクリプトを実行してコンテンツを提供します(一種のローカルCGI)( example

コンテンツの保存方法を変更する

  • chironfs —複数の基礎となるストレージにファイルを複製します( ディレクトリツリーレベルでのRAID-1
  • copyfs —ファイルのすべてのバージョンのコピーを保持します
  • encfs —ファイルを暗号化する
  • pcachefs —遅いリモートファイルシステム用のオンディスクキャッシュレイヤー
  • simplecowfs —提供されたビューを介して変更をメモリに保存し、元のファイルはそのまま残します
  • wayback —ファイルのすべてのバージョンのコピーを保持します