なぜLinuxのデフォルト設定は高性能ストレージに不十分なのか
インストール直後の状態でも、Linuxは「十分に高速」です。しかし、Ubuntu 22.04とDebian 12が混在する14台の本番環境VPSノードを管理してきた経験から、高負荷条件下では「十分に高速」では足りないことに気づきました。デフォルト設定は、数千種類ものハードウェアとの互換性を優先しており、あなたの手元にあるSamsung 990 ProやWD Black SN850Xに最適化されているわけではありません。現代のカーネルは、10年前よりもフラッシュストレージをうまく認識しますが、安全策を優先するあまり、依然としてかなりのパフォーマンスを無駄にしています。
PostgreSQLデータベースを運用していたり、秒間5,000リクエストを処理する忙しいウェブサーバーを動かしている場合、ストレージのボトルネックはいずれCPUの足を引っ張ることになります。OSが物理シリコンと通信する方法を最適化する必要があります。私のセットアップでは、メタデータのスラッシングを減らし、ドライブのNANDセルが早期に摩耗するのを防いでいます。このガイドでは、ハードウェアへの投資を保護しつつ、インフラのレスポンスを維持するために私が採用している、実戦で実証済みの調整方法を紹介します。
アプローチの比較:デフォルト設定 vs 外科手術的なチューニング
多くの管理者は、インストーラーを信頼する派と、カーネルパラメータを掘り下げる派の2つに分かれます。
「設定して忘れる」アプローチ
これはUbuntuやAlmaLinuxের標準的な運用です。OSは非回転ドライブを認識し、週次のTRIMクローンジョブを有効にします。通常、スケジューラはデフォルトの mq-deadline に設定されます。一般的なデスクトップ用途であればこれで十分ですが、マイクロ秒単位が重要になる高並列I/OパターンのDevOps環境では、この設定はあまりに大雑把です。
「外科手術的なチューニング」アプローチ
私は、ソフトウェアのロジックをシリコンの物理特性に合わせることを好みます。手動でドライブがSATAかNVMeかを確認し、不要な書き込みサイクルを削減するために /etc/fstab を調整します。また、I/Oスケジューラをハードウェアの内部コントローラと一致させます。NVMeドライブは自前で巨大な内部キューイングを処理するため、Linuxレイヤーでスケジューラを追加することは、フェラーリにスピードリミッターをかけるようなものであり、無駄なCPUオーバーヘッドを増やすだけです。
手動最適化のメリットとデメリット
システムレベルのパラメータ調整にはトレードオフが伴います。メンテナンスコストとスピードの向上を天秤にかける必要があります。
- メリット:
- 寿命の向上: 賢いマウントオプションによって「書き込み増幅(write amplification)」を抑えることで、ドライブのTBW(総書き込みバイト数)定格を直接的に延ばすことができます。
- 低レイテンシ: 私のテストでは、負荷のかかったNVMeで
noneスケジューラを使用することで、平均I/Oレイテンシが0.5msから0.32msに低下しました。 - 一貫したスループット: プロアクティブなTRIM管理により、ドライブの容量が80%に達したときに発生する、あの恐ろしいパフォーマンスの急低下を防ぐことができます。
- リスク:
- 構成の乖離: AnsibleやTerraformのスクリプトで管理すべきカスタムのudevルールやfstabフラグが増えることになります。
- エッジケースでのデータ損失:
data=writebackのような極端なオプションは、突然の停電時にデータを失う可能性があります。私は通常、これらを避け、noatimeのような安全で効果の高いフラグを優先します。
パフォーマンスのための推奨ベースライン
これは、私が管理するサーバーの90%に適用している構成です。生の速度とデータ整合性の間で、プロフェッショナルなバランスを実現しています。
- TRIM戦略:
fstrim.timerを使い続けます。discardマウントフラグは避けてください。継続的なTRIMは、削除のたびにOSがブロック解放の確認を待つため、わずかですが不快なカクつき(スタッター)の原因になることがあります。 - マウントフラグ:
noatimeとlazytimeを使用します。デフォルトでは、Linuxはファイルを確認(リード)するたびにアクセス時間を更新するためにディスクへの書き込みを行います。SSDにとってこれは狂気の沙汰です。noatimeはこの挙動を停止させ、メタデータの書き込みを即座に10〜15%削減します。 - I/Oスケジューラ: NVMeには
none、SATA SSDにはkyber(Facebookが開発)またはmq-deadlineを使用します。 - Swappiness:
vm.swappinessを10に下げます。これにより、LinuxはRAMをより効率的に使用するようになり、SSD上のスワップパーティションへの過度なアクセスを防ぎます。
実装ガイド:システムのチューニング
以下のコマンドはrootとして実行してください。可能な限り、システムの再起動なしで変更を適用していきます。
ステップ 1: ハードウェアの特定
推測は禁物です。誤って古いHDDバックアップドライブにSSD用の調整を適用しないよう、どのドライブがフラッシュベースかを確認します。
# 0 = SSD/NVMe, 1 = HDD (0ならSSD/NVMe、1ならHDD)
lsblk -d -o NAME,ROTA,MODEL,SIZE
ステップ 2: プロアクティブなTRIMの有効化
定期的なTRIMは黄金律です。これにより、ドライブはアイドル時間中にガベージコレクションを管理できます。
# タイマーがアクティブであることを確認
systemctl status fstrim.timer
# 停止している場合は、有効化して即座に起動
sudo systemctl enable --now fstrim.timer
一度手動で sudo fstrim -av を実行してください。数ヶ月間TRIMされていなかったサーバーでは、50GiB以上の「失われた」スペースが回収されても驚かないでください。
ステップ 3: 寿命向上のために /etc/fstab を編集
/etc/fstab を開き、マウントポイントを見つけます。汎用的な relatime を、より積極的な最適化設定に入れ替えます。
# 変更前:
UUID=abc-123 / ext4 defaults,relatime 0 1
# 変更後:
UUID=abc-123 / ext4 defaults,noatime,lazytime 0 1
lazytime フラグは「隠し味」です。アクセス時間をRAM上に保持し、ファイルのデータが実際に変更されたときやシステム同期の際のみディスクに書き込みます。
ステップ 4: 適切なスケジューラの設定
NVMeにとって最適なスケジューラは「スケジューラなし」です。カーネルが余計なことをしないようにします。再起動後もこの設定を維持するために udev ルールを使用します。
# ルールファイルを作成
sudo nano /etc/udev/rules.d/60-scheduler.rules
中に以下のロジックブロックを貼り付けます:
# カーネルのオーバーヘッドを避けるため、NVMeには 'none' を使用
ACTION=="add|change", KERNEL=="nvme*", ATTR{queue/scheduler}="none"
# SATA SSD(非回転体)には 'mq-deadline' を使用
ACTION=="add|change", KERNEL=="sd[a-z]", ATTR{queue/rotational}=="0", ATTR{queue/scheduler}="mq-deadline"
変更を即座に適用します: sudo udevadm trigger
ステップ 5: スワップの抑制
Linuxはしばしばスワップを過度に使用しようとします。SSDでは、不要なセルの摩耗を防ぐためにこれを最小限に抑えたいところです。
# RAMの利用効率を高めるために10に設定
sudo sysctl vm.swappiness=10
# 再起動後も設定を維持
echo "vm.swappiness=10" | sudo tee -a /etc/sysctl.d/99-swappiness.conf
結論:石橋を叩いて渡る
パフォーマンスチューニングの本質は、ベンチマークで自己満足の数値を追い求めることではありません。午前3時にトラフィックが急増した際にも、システムが揺るぎない安定性を維持できるようにすることです。14台のVPSインスタンスを運用して学んだのは、小さく慎重な構成変更が、後の大きなトラブルを防ぐということです。
これらの設定を適用したら、fio のようなツールを使ってレイテンシが実際に低下したか確認してください。ただし、/etc/fstab を触る前には必ずバックアップを取ることを忘れないでください。たった一つのタイポが、楽しい最適化の時間を、リカバリコンソールと向き合う長い夜に変えてしまうかもしれないからです。

