データディスクのマウントを検証してからサービスを起動する

データディスクのマウントを検証してからサービスを起動する

データディスクのマウントを検証してからサービスを起動する

データディスクのマウントに失敗しても、アプリケーションがすぐにエラーを返すとは限りません。マウント先として用意した /srv/data は、システムディスク上の通常のディレクトリとして残るため、サービスがそのまま書き込みを続け、システムディスクの空き容量を使い切ることがあります。その後マウントを復旧すると、書き込まれたファイルはマウント先のファイルシステムに隠れ、見分けにくいデータが二重に存在する状態になります。本番稼働前の検証では、ディレクトリの有無だけでなく、そのパスを実際に支えているファイルシステムを確認する必要があります。

一、データディスクの識別情報と作業範囲を確認する

この記事では、Ubuntu Server 24.04 LTS 上で、すでに ext4 ファイルシステムがあるデータパーティションを扱います。パーティションの作成やフォーマットは行いません。コマンドは SSH で接続したサーバー上で実行します。CloudSFP の接続情報は支払い後に管理コンソールで確認できます。アドレスが複数ある場合は、最初のアドレスを使用してください。

標準構成の 1TB NVMe 2 台はそれぞれ直接接続されており、ハードウェア RAID はありません。デバイス番号だけでは、システムディスクとデータディスクを区別できません。また、番号から冗長化の有無を判断することもできません。すでにソフトウェア RAID や別のストレージ層がある場合は、その上位層のファイルシステムをマウントします。上位層を迂回して構成メンバーのディスクを直接マウントしてはいけません。

lsblk -o NAME,PATH,SIZE,TYPE,FSTYPE,UUID,MOUNTPOINTS
sudo blkid
findmnt -T /
findmnt -T /srv

容量、ファイルシステムの種類、現在のマウントポイント、インストール時の記録を照合して対象のパーティションを特定し、UUID を記録します。UUID はデバイスの列挙名より安定していますが、必ず一意であるとは限りません。ファイルシステムを複製すると UUID も複製されることがあります。重複が見つかった場合は、先に識別情報の競合を解消し、そのまま起動設定に書き込まないでください。

以下の変更は、データディスクを業務で使用する前に実施してください。すでに稼働中のサーバーでは、まず書き込みを停止し、バックアップと復元手順を確認する必要があります。テストのために、使用中のファイルシステムをそのままアンマウントしてはいけません。

二、試しにマウントしてから fstab に登録する

空のマウントポイントを作成し、その中にファイルがないか確認します。隠しファイルも確認対象です。ディレクトリが空でなければ、まずファイルの由来を調べ、削除や上書きは行わないでください。

sudo mkdir -p /srv/data
sudo find /srv/data -mindepth 1 -maxdepth 1 -print
read -r -p 'Filesystem UUID: ' DATA_UUID
sudo blkid -U "$DATA_UUID"
sudo mount -t ext4 -o ro "UUID=$DATA_UUID" /srv/data
findmnt -M /srv/data -o TARGET,SOURCE,FSTYPE,OPTIONS,UUID

blkid の出力がディスクの識別記録と一致した場合に限り、マウントに進みます。最初の読み取り専用マウントは内容を確認するためのものであり、破損したファイルシステムを修復する手段ではありません。ここで使う findmnt -M は、指定したマウントポイントそのものを確認します。一方、findmnt -T は指定パスを収容するファイルシステムを探すため、データディスクが未マウントの場合にはルートファイルシステムを返すことがあります。終了ステータスが成功だったというだけで、正しくマウントできていると判断してはいけません。

マウント元と内容を確認したら、読み取り専用のマウントを解除します。/etc/fstab をバックアップしてから編集し、同じマウントポイントを重複して追加しないでください。次の例の UUID は、先ほど照合した実際の値に置き換える必要があります。

UUID=<已核对的文件系统UUID> /srv/data ext4 defaults,nofail,x-systemd.device-timeout=15s 0 2

この設定では、ディスクが存在しなくてもシステムの起動を継続できます。デバイスの待機時間の上限は、この例で選んだ 15 秒です。提供までの時間や復旧時間を保証するものではありません。業務要件としてディスク不在時にシステムの起動を止める必要がある場合は、起動方針を別途設計し、nofail をそのまま採用しないでください。

sudo umount /srv/data
sudo cp -a /etc/fstab /etc/fstab.before-data-mount
sudoedit /etc/fstab
sudo findmnt --verify --verbose
sudo systemctl daemon-reload
sudo mount /srv/data
findmnt -M /srv/data -o TARGET,SOURCE,FSTYPE,OPTIONS,UUID

検証に失敗したら、先に設定を修正し、マウントには進まないでください。マウントするのは対象パスだけとし、すべてを一括でマウントすることで別の設定問題を見落とさないようにします。構文チェックに合格しても、デバイスが実際に利用できるとは限りません。実際のマウント結果も確認が必要です。

三、サービスの起動をマウントに依存させる

nofail が制御するのはシステムの起動動作であり、アプリケーションの安全性ではありません。データディレクトリを使用するサービスには、マウントへの依存関係を宣言する必要があります。以下の app.service は、実在する業務用ユニットの代わりに使っている名前です。実際のユニット名に置き換え、そのユニットが書き込みプロセスを起動することも確認してください。

sudo systemctl edit app.service を実行し、次を追加します。

[Unit]
RequiresMountsFor=/srv/data
AssertPathIsMountPoint=/srv/data

RequiresMountsFor は、このパスへのアクセスに必要なマウントを起動し、起動順序を設定します。アサーションは、「ディレクトリは存在するがマウントポイントではない」という状態での起動を拒否します。ただし、どちらも誤ったディスクを識別することはできず、アプリケーション側のデータ整合性チェックを代替するものでもありません。そのため、UUID とマウント元の照合は別の手順として必要です。

sudo systemctl daemon-reload
sudo systemctl cat app.service
sudo systemctl show app.service -p Requires -p After

追加したオーバーライド設定が反映されていることを確認し、アプリケーションが実際に使うデータディレクトリが /srv/data 配下にあることも確認します。起動スクリプトで別のパスへ切り替えている場合、依存関係が正しくても誤った場所に書き込む可能性があります。定期実行ジョブ、手動スクリプト、ほかのサービスにはこれらの制約が自動で引き継がれないため、それぞれ確認が必要です。

業務用のサブディレクトリは、マウントが成功してから作成し、実際のサービスアカウントに合わせて所有者と権限を設定します。データディスク全体をすべてのアカウントから書き込み可能にしたり、認証情報をマウント設定に書き込んだりしてはいけません。

四、本番の書き込み前にディスク不在と復旧をテストする

テストは、業務データがなく、書き込みも行われていない段階で実施します。まずアプリケーションを停止し、続いてデータディスクのマウントユニットを停止します。/srv/data に対応するユニット名は、systemd-escape --path --suffix=mount /srv/data で確認できます。複雑なパスのユニット名を手作業で推測してはいけません。

sudo systemctl stop app.service
sudo systemctl stop srv-data.mount
sudo systemctl mask --runtime srv-data.mount
sudo systemctl start app.service
sudo systemctl status app.service srv-data.mount --no-pager

マウントユニットを一時的にマスクするのは、マウントが利用できない状態を再現し、アプリケーションの起動時に自動で再マウントされるのを防ぐためです。期待する結果は、起動が失敗し、業務プロセスが動作していないことです。アンマウント時に使用中と表示された場合は、何が使用しているのかを調べます。強制アンマウントや遅延アンマウントで確認を回避してはいけません。

この状態で、マウントの下にある /srv/data ディレクトリに新しいファイルが作成されていないか確認します。テスト後は、まずマスクを解除してからマウントを復旧します。

sudo systemctl unmask --runtime srv-data.mount
sudo systemctl start srv-data.mount
findmnt -M /srv/data -o TARGET,SOURCE,FSTYPE,OPTIONS,UUID
sudo systemctl reset-failed app.service
sudo systemctl start app.service

マウント元が一致し、アプリケーションのヘルスチェックに合格して初めて、復旧完了と判断できます。検証を終える際は、一時的なマスクが解除されていることを必ず確認してください。起動依存関係が主に保護するのは起動時であり、稼働中のディスク障害を検知する仕組みではありません。その後の運用には、アプリケーションのエラー処理と監視も必要です。

五、再確認できる稼働開始記録を残す

記録には、ディスクの識別情報、UUID、マウントポイント、ファイルシステムの種類、fstab の変更内容、サービスのオーバーライド設定、ディスク不在テストの結果を含めます。再起動による検証は業務で使用する前に行い、マウントが完了してからサービスが起動することを確認します。一度の手動マウントが成功しただけでは、起動時の検証の代わりにはなりません。

マウント後にシステムディスクの空き容量に異常が見つかった場合は、まずマウントによって隠れている古いファイルがないか確認します。関連する書き込みを停止してから調査を行ってください。稼働中にアンマウントしてそのまま削除したり、マウントの下にあるディレクトリとデータディスク上のディレクトリを無条件に統合したりしてはいけません。

最終的な合格条件は、マウント元が正しいこと、対象パスが実際にマウントされていること、サービスの依存関係が有効であること、ディスク不在時に誤った書き込みが発生しないこと、復旧後のヘルスチェックに合格することです。マウント設定は、冗長化もバックアップも提供しません。この 2 点は、別途設計して検証する必要があります。

よくある質問

マウント元にデバイス名を直接指定しない理由は?

デバイスの認識順序は変わる可能性があります。確認済みの一意なファイルシステム UUID を使用します。複製により UUID が重複する場合もあるため、lsblk、blkid、findmnt で照合します。

fstab の nofail だけでシステムディスクへの誤書き込みを防げますか?

防げません。nofail はマウントに失敗してもシステムの起動を継続する設定です。サービスに RequiresMountsFor と AssertPathIsMountPoint を設定し、マウント元も確認する必要があります。

AMD EPYC 7543P 専用物理サーバー$441.4/月〜