物理サーバーのログ容量を管理し、解放された領域を検証する

物理サーバーのログ容量を管理し、解放された領域を検証する

データベースへの書き込みが失敗しているのに、業務データのファイルは増えていない。そのような場合によくある原因が、同じエラーログの繰り返し出力によって、システムパーティションが先に埋まってしまうことです。ログ容量の管理では、定期的にディレクトリを削除するのではなく、書き込み・ローテーション・保存をそれぞれ制御し、実際に領域が解放されたことまで確認する必要があります。本記事では Debian 12 を例に、システムの journal と短時間で終了するタスクのファイルログを扱います。データベースのファイルや既存のストレージ構成は変更しません。

CloudSFP の物理サーバーには、それぞれ独立して直結された 1TB NVMe が標準で2台搭載されており、ハードウェア RAID はありません。2台分の容量を、そのままログを保存するファイルシステムの空き容量として扱うことはできません。ログの容量予算は、実際のマウントポイントを基準に決める必要があります。以下に示す容量はすべて操作例であり、サービスのデフォルト設定ではありません。

1. 使用量を特定し、ディスクブロックと inode を切り分ける

支払い後、コンソールで認証情報を確認し、SSH でログインします。サーバーに複数のアドレスがある場合は、最初のアドレスを使用します。まず、変更を加えない確認コマンドを実行します。

df -hT / /var/log
df -i / /var/log
findmnt -T /var/log
sudo du -xhd1 /var/log
sudo journalctl --disk-usage

df はファイルシステムの使用量を表示し、du はディレクトリ内で参照できるファイルを集計するため、両者の値が一致するとは限りません。-x を指定すると別のファイルシステムをまたがずに集計でき、個別にマウントされたボリュームが結果に混ざるリスクを抑えられます。/var/log が独立したパーティションでなければ、ログとシステムファイルは同じルートパーティションの領域を消費します。

空き領域が十分にあっても inode が枯渇しかけている場合は、最大のログだけでなく、大量の小さなファイルを調べる必要があります。ファイルシステム、空き容量、inode の使用量、増加が最も速いディレクトリを記録してから、対処する対象を決めます。診断結果の記録は、すでに満杯に近いパーティションへ書き込まないでください。

/var/log 全体を直接削除したり、保全していない障害ログを切り詰めたりしないでください。整理する前に、該当する時間帯の調査に必要な記録を保存し、対象がデータベースのデータ、トランザクションログ、バックアップファイルではないことを確認してください。

2. journald に個別の容量予算を設定する

永続化された journal は通常、/var/log/journal に保存されます。制限はメイン設定を直接上書きするよりも、ドロップイン設定で管理するほうが、監査や取り消しをしやすくなります。以下の例では、ログの容量予算と、ファイルシステムに確保しておく空き領域を設定します。

sudo install -d -m 0755 /etc/systemd/journald.conf.d
sudo tee /etc/systemd/journald.conf.d/60-capacity.conf >/dev/null <<'EOF'
[Journal]
Storage=persistent
SystemMaxUse=1G
SystemKeepFree=4G
MaxFileSec=1day
EOF

sudo systemd-tmpfiles --create --prefix /var/log/journal
sudo systemctl restart systemd-journald
sudo journalctl --flush
sudo journalctl --disk-usage
sudo systemctl status systemd-journald --no-pager

SystemMaxUse は journal が使用する容量予算を制御し、SystemKeepFree は同じファイルシステムに空き領域を残すよう指定します。実際の動作は、その時点の空き容量にも左右されます。これらの設定は、アプリケーションが独自に書き出すファイルには適用されません。MaxFileSec はアクティブなファイルに記録する時間幅の上限であり、ログを1日分だけ保存するという意味ではありません。

別のプログラムが同じメッセージをテキストログにも書き込んでいる場合、journal を制限しても、そのコピーはなくなりません。ログが出力される経路を確認し、それぞれを管理する必要があります。確認せずにシステムのログサービスを無効化しないでください。

削除する前にローテーションし、結果を確認する

sudo journalctl --rotate
sudo journalctl --vacuum-size=1G
sudo journalctl --disk-usage
df -h /var/log

vacuum はアーカイブ済みのファイルだけを削除し、アクティブなファイルを直接削除しません。そのため、最終的な使用量が指定値とちょうど一致するとは限りません。journald の再起動は設定変更を伴う操作です。実行前に現在のサービス状態を確認し、実行後には新たなエラーがないか、業務ログが引き続き journal に記録されているかを確認してください。

3. ファイルログのローテーションを誰が担うか明確にする

まず、どのプログラムがログを書き込むのか、ファイルを長時間開いたままにするのか、既存のルールがそのパスを対象にしているかを確認します。同じファイルをアプリケーション内蔵のローテーション機能と logrotate の両方で管理してはいけません。また、システムの既存ルールと重複する広範なマッチ条件を追加しないでください。

確認に使うツールをインストールします。

sudo apt-get update
sudo apt-get install logrotate lsof

短時間で終了するタスクが、起動のたびに /var/log/local-batch/run.log を開き直し、終了時に閉じると仮定します。その場合は、/etc/logrotate.d/local-batch に以下を記述できます。

/var/log/local-batch/run.log {
    daily
    maxsize 100M
    rotate 7
    compress
    delaycompress
    missingok
    notifempty
    create 0640
}

ディレクトリと元のログファイルは事前に作成し、所有権をタスクの実行アカウントに合わせておく必要があります。create 0640 で所有者を指定しない場合は、元のファイルの所有者とグループが引き継がれます。非特権アカウントがディレクトリに書き込める場合は、su ディレクティブとディレクトリの権限を別途検討する必要があり、このルールをそのまま流用することはできません。

sudo logrotate -d /etc/logrotate.conf
systemctl list-timers --all --no-pager

-d はシミュレーション結果を出力するだけで、ローテーションは実行しません。タイマーや cron が実際にどの頻度で実行されているかを確認してください。maxsize のチェックは logrotate が呼び出されたときだけ行われるため、リアルタイムに適用される厳密な上限ではありません。また、rotate 7 はアーカイブを7世代保存する指定であり、必ずしも7日分を意味しません。

常駐プロセスには、アプリケーションが対応しているログの再オープン機構が必要です。ファイル名を変更しても、プロセスが元のファイルへ書き込み続けることがあります。送るべきシグナルを推測したり、安易に copytruncate を使ったりしないでください。copytruncate には、コピーと切り詰めの間にログが失われる時間帯が生じます。

4. 隔離したディレクトリでローテーションと権限を試す

新しいルールのテストのために、全体設定へ強制ローテーションを実行してはいけません。以下の試験では、専用のディレクトリと状態ファイルを使用し、本番のログには触れません。

umask 077
test_dir=$(mktemp -d)
printf '%0200d\n' $(seq 1 20) >"$test_dir/run.log"

cat >"$test_dir/rules" <<EOF
"$test_dir/run.log" {
    size 1k
    rotate 2
    create 0640
}
EOF

logrotate -d -s "$test_dir/state" "$test_dir/rules"
logrotate -s "$test_dir/state" "$test_dir/rules"
ls -l "$test_dir"
printf 'after rotation\n' >>"$test_dir/run.log"
cat "$test_dir/run.log"

アーカイブファイル、新しく作成されたアクティブなファイル、想定どおりの権限が確認できるはずです。最後の書き込みで確認できるのは、パスを開き直して書き込めることだけであり、常駐アプリケーションが自動で新しいファイルに切り替わることまでは証明できません。本番での動作確認では、実際のタスクに識別できる記録を1件出力させ、新しいアクティブなファイルに記録されていることも確認する必要があります。

試験用ディレクトリは結果を確認するまで残し、確認後に削除します。本番のルールは引き続きシステム既存の状態ファイルで管理してください。手動実行と定期実行を同時に走らせたり、同じログを2つの状態ファイルで継続的に管理したりしてはいけません。

5. 領域の解放を検証し、繰り返されるエラーにも対処する

ファイルを削除しても空き領域が増えない場合は、まずプロセスが開いたまま保持しているファイルを調べます。

sudo lsof +L1
df -h /var/log
df -i /var/log
sudo du -xhd1 /var/log

lsof +L1 は、リンク数が1未満の開かれたファイルを表示します。パス、サイズ、プロセスを合わせて判断し、表示されたものすべてをログとして扱わないでください。対象を特定したら、アプリケーションのドキュメントに従ってログを開き直します。必要に応じて該当するサービスを再起動し、再度 df を確認してください。不明なプロセスを終了したり、そのファイル記述子に書き込んだりして、強引に領域を解放してはいけません。

動作確認では、少なくとも次の4点の結果を残します。新しい記録がアクティブなファイルに出力されること、アーカイブ数がルールどおりであること、実行アカウントが引き続き書き込めること、ファイルシステムの空き領域が継続的かつ異常に減っていないことです。エラーメッセージが依然として大量に繰り返される場合は、失敗時の再試行、無効なリクエスト、デバッグ出力など、発生源を修正する必要があります。ローテーションは障害対応の代わりにはなりません。

容量予算を設定しても、一定期間の履歴が必ず残るわけではありません。ピーク時にはログの増加が速くなり、同じ予算でも古い記録が早く削除されます。長期保存が必要な記録については、転送、アクセス制御、バックアップを別途設計し、実際に読み出せることを検証してください。ローカルのログローテーションが担うのは、そのサーバーでの使用量を制限することだけであり、バックアップの役割は担いません。

よくある質問

vacuum を実行すれば、すべての journal が指定サイズ以下になりますか?

なりません。vacuum が削除するのはアーカイブ済みの journal です。journalctl --rotate の後に journalctl --vacuum-size=1G を実行し、journalctl --disk-usage と df でそれぞれの使用量を確認します。

ログを削除しても df の空き容量が増えない原因は何ですか?

プロセスが削除済みファイルを開いたままの可能性があります。sudo lsof +L1 でサイズとプロセスを確認し、アプリが対応するログ再オープン処理か対象サービスの再起動で解放します。

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