【logrotate講座 付録】ディスク容量不足の緊急救命室!LVM拡張・olddir活用・別ディスク退避の完全対策

「No space left on device」…絶望のカウントダウンを止めろ。

こんにちは!「LINUX工房」管理人の「リナックス先生」です。
全8回のlogrotate講座、お疲れ様でした。これでログ管理は完璧…と言いたいところですが、運用現場にはもう一つ、巨大な敵がいます。

それは「物理的なディスク容量不足」です。
いくらログを圧縮しても、サービスの成長とともにログは肥大化し、データベースの容量も増え続け、いつか必ず / (ルート) パーティションが100%になる日が来ます。
ディスクが満杯になると、ログが書けないだけでなく、データベースが停止し、最悪の場合はOS自体がクラッシュして起動しなくなります。

コウ君

先生、緊急事態です!
logrotateの設定はしたんですが、そもそもサーバーのディスクが20GBしかなくて、もう残り100MBしかありません!
ログを消そうにも「監査のために1年は残せ」って言われてて…。
サーバーを作り直してデータ移行するしかないんでしょうか? そんな時間ありません!

リナックス先生

落ち着いて、コウ君。Linuxはそんなにヤワじゃないわ。
現代のLinuxサーバー(AlmaLinuxなど)は、「LVM(論理ボリュームマネージャ)」という仕組みで動いていることがほとんど。
これを使えば、サーバーを止めずに、後からディスクを継ぎ足して容量を増やすことができるのよ。
さらに、logrotateには「olddir」という整理整頓機能もあるし、スクリプトを使えば別ディスクへの自動退避も可能なの。

本記事では、ディスク容量が逼迫した際やログが散乱した際の「3つのアプローチ」を徹底解説します。

  1. インフラ側からの解決策「LVMによるディスク拡張」
  2. ディレクトリを整理する基本機能「olddirの活用」
  3. 物理的に別の場所に逃がす「別ディスクへのログ自動退避」

アプローチ1:LVMによるディスク容量の拡張

最も根本的な解決策は、「ディスクの容量そのものを増やす」ことです。
VPSやクラウド環境(AWS EBSなど)、あるいは仮想環境(VMware/VirtualBox)であれば、物理的なディスクサイズを増やしたり、新しいディスクを追加したりすることは容易です。

しかし、単にディスクを追加しただけでは、/ (ルート) の容量は増えません。
ここで登場するのが LVM (Logical Volume Manager) です。

1. LVMの仕組みを理解する(3層構造)

LVMは、物理的なハードディスクと、OSが見ているファイルシステムの間に「抽象化レイヤー」を挟む技術です。
以下の3つの概念を理解してください。

  1. PV (Physical Volume / 物理ボリューム):
    物理的なハードディスクやパーティションそのものです。(例:/dev/sdb1
    「粘土の塊」だと思ってください。
  2. VG (Volume Group / ボリュームグループ):
    複数のPVを束ねた、巨大な一つのプールです。(例:almalinux
    複数の粘土をまとめて一つの大きな「粘土の山」にします。
  3. LV (Logical Volume / 論理ボリューム):
    VGから必要な分だけ切り出して作られる仮想的なパーティションです。(例:/dev/almalinux/root
    OSはこれを「ディスク」として認識し、ここにファイルシステム(XFSなど)を作ります。

つまり、「新しいディスク(PV)を追加」→「プール(VG)を大きくする」→「論理ボリューム(LV)を拡張する」という手順を踏むことで、既存のデータを消すことなく容量を増やせるのです。

2. 【実践】ディスク追加から拡張までの完全手順

それでは、AlmaLinux 9 環境で、新しいディスク(10GB)を追加して、ルートパーティションを拡張する手順をシミュレーションします。
※操作は全て root ユーザーで行います。非常に危険な操作を含むため、必ずバックアップを取ってから行ってください。

Step 1: 新しいディスクの確認

サーバーに新しいディスクを接続した後、OSが認識しているか確認します。

lsblk

出力例:

NAME        MAJ:MIN RM  SIZE RO TYPE MOUNTPOINTS
sda           8:0    0   20G  0 disk
├─sda1        8:1    0    1G  0 part /boot
└─sda2        8:2    0   19G  0 part
  ├─almalinux-root 253:0    0   17G  0 lvm  /       <-- これを増やしたい
  └─almalinux-swap 253:1    0    2G  0 lvm  [SWAP]
sdb           8:16   0   10G  0 disk                <-- 新しく追加したディスク

sdb として10GBのディスクが見えています。

Step 2: PV(物理ボリューム)の作成

新しいディスク /dev/sdb をLVMで使えるように初期化します。

pvcreate /dev/sdb

Physical volume "/dev/sdb" successfully created. と出ればOKです。

Step 3: VG(ボリュームグループ)の拡張

既存のVG(ここでは almalinux)に、新しいPVを追加してプールを大きくします。
まずVG名を確認します。

vgs

出力例: VG #PV #LV #SN Attr VSize VFree almalinux 1 2 0 wz--n- 19.00g 0
VG名は almalinux です。

拡張を実行します。

vgextend almalinux /dev/sdb

Volume group "almalinux" successfully extended と表示されます。
もう一度 vgs を叩くと、VFree(空き容量)が10GB増えているはずです。

Step 4: LV(論理ボリューム)の拡張

増えたプールの容量を使って、ルートパーティション(LV)を拡張します。
LVのパスは df -hlsblk で確認できます(例: /dev/mapper/almalinux-root)。

# 空き容量の100%を割り当てるコマンド
lvextend -l +100%FREE /dev/mapper/almalinux-root

Logical volume almalinux/root successfully resized. と表示されます。

Step 5: ファイルシステムの拡張(これが最後!)

LVの器は大きくなりましたが、その中にある「ファイルシステム(XFS)」はまだ元のサイズのままです。
最後にファイルシステムを広げます。

AlmaLinux 9 (XFS) の場合:

xfs_growfs /

Ubuntu (ext4) の場合:

resize2fs /dev/mapper/ubuntu--vg-ubuntu--lv

最後に df -h を実行し、/ のサイズが増えていることを確認しましょう。
これで、サーバーを止めることなくディスク容量不足を解消できました!


アプローチ2:olddir でログファイルを整理整頓する

次に紹介するのは、logrotate標準機能である olddir です。
これは、「ローテーションした古いログを、指定したディレクトリに移動して保存する」機能です。

1. olddir の基本と設定

/var/log/httpd/ の中に、access.log.1, access.log.2.gz ... と大量のファイルが散らばっていて見づらい!という場合に有効です。
サブディレクトリ(例:archives)を作ってそこに放り込むことで、メインのディレクトリをスッキリ保てます。

設定例:

/var/log/httpd/*.log {
    daily
    rotate 30
    compress
    # 古いログの移動先を指定(ディレクトリは事前に作成しておくこと)
    olddir /var/log/httpd/archives
    # 移動したファイルに権限を与える(必要に応じて)
    create 644 root root
}

2. 重要な制約(別デバイス不可)

非常に便利な olddir ですが、致命的な制約が一つあります。
それは、「ログファイルと同じ物理デバイス(ファイルシステム)上にないと動かない」ということです。

例えば、/var/log// パーティションにあり、/mnt/backup/ が別のHDDだとします。
この場合、olddir /mnt/backup/ と設定すると、logrotateはエラーを出して停止します。

⚠️ エラー内容
error: /var/log/httpd/access.log is on different filesystem than /mnt/backup/

これは、logrotateが内部で単純な「リネーム(mv)」操作を行っており、パーティションを跨ぐ移動(コピー&削除)には対応していないためです。
したがって、「ディスク容量不足の解消」のために別ディスクへ olddir する、ということはできません。
それを実現するのが、次のアプローチ3です。


アプローチ3:別ディスクへのログ退避と階層化管理

では、「ルートパーティションをこれ以上拡張できない(あるいは高価なSSDを節約したい)」場合に、安価なHDDなどの別ディスクへログを逃がすにはどうすればいいでしょうか?
ここで、logrotateのスクリプト機能が火を噴きます。

1. 要件定義と戦略

今回は以下の高度な階層化管理(ティアリング)を実現します。

  1. アプリケーションのログ(/var/log/myapp/*.log)を管理する。
  2. 直近30日分は、標準の場所(/var/log/myapp/)に残す。
  3. 31日以上経過したログは、別ディスク(/mnt/archive/)に移動する。
  4. 移動したログは、合計365日経過したら完全に削除する。

2. 別ディスクのマウント準備

まず、新しいディスク(/dev/sdb とします)をフォーマットし、アーカイブ用ディレクトリとしてマウントします。

# パーティション作成(全領域を使用)
echo -e "n\np\n1\n\n\nw" | fdisk /dev/sdb

# XFSでフォーマット
mkfs.xfs /dev/sdb1

# マウントポイント作成
mkdir -p /mnt/archive

# マウント
mount /dev/sdb1 /mnt/archive

# 自動マウント設定 (/etc/fstab)
echo "/dev/sdb1 /mnt/archive xfs defaults 0 0" >> /etc/fstab

# ログ保存用ディレクトリ作成
mkdir -p /mnt/archive/myapp
# 権限調整(必要に応じて)
chmod 755 /mnt/archive/myapp

3. 【実践】logrotateによる階層化移動の実装

logrotateの設定ファイルを作成します。
ポイントは、lastaction ブロックの中で find コマンドを駆使して「移動」と「削除」を行うことです。

設定ファイル (/etc/logrotate.d/myapp):

/var/log/myapp/*.log {
    daily
    missingok
    rotate 30
    notifempty
    compress
    delaycompress
    dateext
    dateformat -%Y%m%d
    
    # 権限設定(アプリのユーザーに合わせる)
    create 644 myappuser myappgroup
    
    sharedscripts
    postrotate
        # アプリケーションのリロード(createモードの場合)
        /bin/systemctl reload myapp.service > /dev/null 2>/dev/null || true
    endscript
    
    lastaction
        # 【処理1】30日を超えたログを別ディスクへ移動
        # /var/log/myapp/ 内にある、30日以上前に更新された圧縮ログ(.gz)を探して移動
        /usr/bin/find /var/log/myapp/ -name "*.gz" -mtime +30 -exec mv {} /mnt/archive/myapp/ \;
        
        # 【処理2】アーカイブ先で365日を超えたログを削除
        # /mnt/archive/myapp/ 内にある、365日以上前のファイルを削除
        /usr/bin/find /mnt/archive/myapp/ -name "*.gz" -mtime +365 -delete
    endscript
}

スクリプトの解説:

  • rotate 30:
    logrotateとしての管理は「30世代」です。31回目を回そうとした時、logrotateは一番古いログを「削除」しようとします。
    しかし、その前に lastaction が走ります。
  • find ... -mtime +30 -exec mv ...:
    -mtime +30 は「更新日時が30日(24時間×30)より前のファイル」を探します。
    logrotateが削除する直前(あるいは削除対象にならなくても古くなったもの)を、mv コマンドで強制的に別ディスクへ退避させます。
  • find ... -mtime +365 -delete:
    移動先のディスク(/mnt/archive)は logrotate の管理外です。
    放っておくと無限に溜まってしまうため、ここで一緒に「365日経過したファイルの削除」も行います。

⚠️ 注意点:rotate設定との兼ね合い
lastaction でファイルを移動(mv)してしまえば、元の場所からは消えるため、logrotate本体の rotate 処理(削除)と競合することはありません。
ただし、タイミングによっては「移動しようとしたら既にlogrotateに消されていた」あるいは「logrotateが消そうとしたら既に移動されていた」となる可能性があります。
安全策として、logrotate側の設定を rotate 32 程度(スクリプトの条件より少し長め)にしておくと、logrotateによる削除よりも先に確実に mv を実行できます。

4. 動作確認とトラブルシューティング

この複雑な設定が正しく動くか、必ずテストしましょう。

findコマンド単体でのテスト:
いきなり logrotate を回す前に、find コマンドが意図したファイルを拾うか確認します。

# 移動対象の確認(mvはしない)
find /var/log/myapp/ -name "*.gz" -mtime +30 -print

# 削除対象の確認(deleteはしない)
find /mnt/archive/myapp/ -name "*.gz" -mtime +365 -print

テスト用に touch -d "2023-01-01" test.log.gz などで古い日時のファイルを作って実験すると良いでしょう。

SELinuxの壁:
別ディスク(/mnt/archive)へのアクセスは、デフォルトのSELinuxポリシーではブロックされる可能性が高いです。
ログローテート実行時(cron)に拒否されるのを防ぐため、ラベルを貼ります。

# アーカイブディレクトリにログ用ラベルを付与
semanage fcontext -a -t var_log_t "/mnt/archive/myapp(/.*)?"
restorecon -Rv /mnt/archive/myapp

まとめ:容量不足は「技術」で解決できる

今回は、ディスク容量不足という危機的状況を脱するための、2つの強力な手法を学びました。

今回の重要ポイント:

  • LVMを使えば、システムを止めずにディスク容量を増やせる(PV→VG→LV→ファイルシステムの順)。
  • xfs_growfs コマンドで、増えた容量をOSに認識させるのを忘れずに。
  • olddir は整理には便利だが、別ディスク(別パーティション)へは使えない。
  • lastactionfind コマンドを組み合わせれば、高度な階層化ストレージ管理が自動化できる。

「ディスクがいっぱいになったら消す」という受動的な対応から、「容量が増やせる構成にしておく」「自動的に安いディスクへ逃がす」という能動的な設計へ。
これが、初心者エンジニアとプロフェッショナルを分ける壁です。

この付録記事の技術を使えば、あなたはもう「No space left on device」の文字に怯えることはありません。
自信を持って、大規模なサーバー運用に挑んでください!

▼ 実践的なインフラ技術を身につける ▼

LVM操作を試す
「VPS」で自分専用環境

おすすめVPSを見る

ストレージ知識を年収に
「ITエンジニア転職」

転職エージェントを見る

コメント