fstabの六フィールドを正確に
一言でいうと
fstabの1行は、デバイス / マウントポイント / タイプ / オプション / dump / passの6つのフィールドです。最後の2つの数字を適当に書いて、起動が止まる事故が実際にあります。
なぜ必要なのか
fstabは、システムで最も危険なファイルの1つです。間違って書くと起動の途中で止まり、コンソールがなければ打つ手がありません。ところが形式が単純なので、人は適当にコピーして貼り付けてしまいます。
どう動くのか
UUID=1a2b... /srv/data ext4 defaults,noatime,nofail 0 2
[----1----] [---2---] [-3-] [--------4---------] 5 6
1. デバイスの識別子。UUID=、LABEL=、PARTUUID=、またはデバイスのパスです。ネットワークファイルシステムなら、server:/exportの形式です。デバイスのパスは不安定なので、UUIDを使います。
2. マウントポイント。絶対パスです。空白が入る場合は、\040でエスケープします。
3. ファイルシステムのタイプ。ext4、xfs、tmpfs、nfs4、none(バインドマウント)、autoです。
4. オプション。カンマで区切ります。よく使うものは次のとおりです。
| オプション | 意味 | いつ使うか |
|---|---|---|
defaults |
rw,suid,dev,exec,auto,nouser,async | 既定 |
noatime |
読み取り時にアクセス時刻を更新しない | ほとんどのサーバーで推奨 |
nofail |
マウントに失敗しても起動を続ける | データディスクでは必須 |
_netdev |
ネットワークの準備ができてからマウント | NFS/iSCSIでは必須 |
noexec,nosuid,nodev |
実行/setuid/デバイスファイルの禁止 | /tmp、ユーザーのアップロードパス |
ro |
読み取り専用 | 監査対象のデータ |
bind |
バインドマウント | 下記参照 |
nofailがないと、データディスクが1つ壊れたときにサーバー全体が起動しません。ルートでないすべてのエントリには、事実上必須です。
5. dump。昔のdumpバックアップツール用のフラグです。最近は、ほとんどいつも0です。
6. pass: fsckの検査順序。これが本当の落とし穴です。
| 値 | 意味 |
|---|---|
0 |
検査しない(tmpfs、NFS、バインドマウント) |
1 |
ルートファイルシステムだけ。最初に、単独で検査 |
2 |
それ以外のローカルファイルシステム。1が終わったあと、並列で検査 |
ルートではないのに1を指定すると、起動時に複数のファイルシステムを同時に単独で検査しようとして、順序がこじれます。ネットワークファイルシステムに1や2を指定すると、ネットワークがない起動初期の段階で検査しようとして止まります。
バインドマウント
同じファイルシステムの1つのディレクトリを、別のパスにも見えるようにします。
/srv/data /var/www/data none bind 0 0
シンボリックリンクとは何が違うのでしょうか。シンボリックリンクはパスの文字列で、バインドマウントは本物のマウントです。そのため、chrootの中やコンテナの中のように、パスの解決範囲が制限された場所では、シンボリックリンクは壊れますが、バインドマウントは動作します。また、バインドマウントにはroのような別のオプションを指定できます。元は書き込み可能にして、このパスでだけ読み取り専用に見せることができます。
検証
fstabを直したあとは、再起動の前に必ず確認します。再起動して確認するのは、確認ではなく賭けです。
findmnt --verify --verbose
mount -a # 실제로 붙여 본다 (특권 필요)
現場での姿
NFSのエントリに_netdevを入れ忘れます。起動中にネットワークの準備ができる前にマウントを試み、タイムアウトまで待ちます。サーバーの起動が5分延びます。
容量を拡張したあと、fstabを直し忘れます。LVMを拡張してresize2fsまでしたのに、再起動すると古いサイズに戻ってしまう場合があります。実は、fstabが別のボリュームを指していたのです。
systemdがfstabを読む
最近のLinuxでは、fstabはそれ自体が実行されるのではなく、起動時にsystemdが読み込んでマウントユニットに変換します。この事実を知ると、2つのことが説明できます。
1つ目は、systemctl statusでマウントの状態を見られることです。/srv/dataはsrv-data.mountというユニットになります(パスのスラッシュがハイフンに変わります)。マウントが失敗したとき、journalctl -u srv-data.mountで原因を見ると、fstabだけをのぞいたときよりずっと具体的なメッセージが出ます。
2つ目は、fstabのオプションの一部は、実はsystemdへの指示だということです。nofailは、そのマウントが失敗しても、ほかのユニットを止めないという意味で、_netdevは、ネットワークの準備ができたあとに順序を遅らせるという意味です。x-systemd.で始まるオプションは、そもそもsystemd専用です。そのうち、実務で価値が大きい2つだけを取り上げます。
x-systemd.automount: 起動時にマウントせず、そのパスに実際にアクセスしたときにマウントします。遅い、あるいはときどき存在しないネットワークストレージに、特に向いています。起動がそのせいで遅れません。x-systemd.device-timeout=10s: デバイスを待つ時間を短くします。既定値は90秒なので、存在しないデバイス1つが、起動をかなり長く引き止めます。
fstabを直したあと、systemdに再読み込みを知らせる必要があることも、忘れやすいです。systemctl daemon-reloadをしないと、systemdは古いユニットをそのまま持っているため、mount -aではマウントできるのに、再起動すると違う動作になる、混乱した状態になります。先ほど言及したfindmnt --verifyとmount -aにこれを加えた3行で確認する習慣をつけると、fstabが原因で起動が止まる事故は、ほとんどなくなります。
次のラボですること
壊れたfstabのフィクスチャをルールに従って監査して問題の行を見つけ、直したあと、自分で検証スクリプトを作成します。採点ツールが、そのスクリプトを正常な入力と不良の入力の両方で実行して、きちんと判別できているかを見ます。