🚴‍♂️

本番サーバの disk full に対処した話

2021/12/18に公開

前任者が構築したWebシステムで業務画面にログインできなくなっている!との連絡。
取り敢えずサーバのsyslogを覗いてみると No space left on device のメッセージが。。。

syslog
Dec 17 04:50:44 ip-172-31-49-201 kernel: [514637.192805] systemd-journald[407]: Failed to create new system journal: No space left on device
Dec 17 04:50:44 ip-172-31-49-201 kernel: [514637.227973] systemd-journald[407]: File /var/log/journal/b0c6ed86cd0d415eacd8a94126
Dec 17 07:15:02 ip-172-31-49-201 rsyslogd: file '7' write error: No space left on device [v8.32.0 try http://www.rsyslog.com/e/2027 ]
Dec 17 07:15:02 ip-172-31-49-201 rsyslogd: action 'action 3' (module 'builtin:omfile') message lost, could not be processed. Check for additional error messages before this one. [v8.32.0 try http://www.rsyslog.com/e/2027 ]

dfでディスク使用率を確認すると、inode不足では無く、本当に満杯のようです。

bashでTABキーを押すと〝ヒアドキュメント用一時ファイルを作成できません: デバイスに空き領域がありません〟になりインテリセンス機能も働かない状況です。

対処

暫定対処

まずはジャーナルの使用量を確認し、落ち着いて対処しましょうか。

ジャーナル使用容量確認
# journalctl --disk-usage
Journal file /var/log/journal/b0b5ed86cd0d415eacd7a9472676e39d/user-1000.journal is truncated, ignoring file.
Archived and active journals take up 886.0M in the file system.

過去3日分だけ残し、削除してみます。

ジャーナル削除
# journalctl --vacuum-time=3d

この時点で業務画面の復旧を確認。サービスの再開を通達しました。

本格対処

まだ、ルートパーティションの使用率が100%から97%に下がっただけなので、続いて根本原因を探っていきます。

ざっくりと何処で容量を食っているのか見てみます。
--max-depth は、集計するディレクトリの深さを指定するオプションです。

# du --max-depth=1 / | sort -rn
54497374  /
38707068  /data
7291716   /usr
5758016   /var
1240026   /snap
975968    /home
358572    /lib
120204    /boot
15252     /bin
15236     /sbin
9392      /etc
5056      /root
780       /run
48        /tmp
16        /lost+found
4         /srv
4         /opt
4         /mnt
  :

/data は専用のデータパーティションにあるので除外し、/var を深掘りします。

# du /var | sort -rn | more
3628680 /var/appl/data
2129336 /var
2029800 /var/www
2029796 /var/www/html
1113088 /var/lib
285532  /var/log
262264  /var/log/journal
197824  /var/cache
  :

アプリケーションが出力している /var/appl/data が圧倒していました。
どうやら開発ベンダーが、ファイルのクリーンアップ処理を入れ忘れていたようです。

このデータは保存期間が2年であることを確認できたため、更新日付が2年以上前のファイルを削除します。

まず、削除対象ファイルを確認します。

find /var/appl/data -type f -mtime +730 -name "*.jpg" | xargs ls -l
実行結果
-rw-rw-r-- 1 appl appl 186275 10月 17  2016 /var/appl/data/d7ca337c-b7d3-441b-822b-f943f7b17fd2/1222/15.jpg
-rw-rw-r-- 1 appl appl 218768 10月 18  2016 /var/appl/data/d7ca337c-b7d3-441b-822b-f943f7b17fd2/1222/16.jpg
-rw-rw-r-- 1 appl appl 212066 10月 17  2016 /var/appl/data/d7ca337c-b7d3-441b-822b-f943f7b17fd2/0117/15.jpg
-rw-rw-r-- 1 appl appl 198906 10月 18  2016 /var/appl/data/d7ca337c-b7d3-441b-822b-f943f7b17fd2/0117/16.jpg
  :

ファイルの更新日付からみて問題なさそうです。削除しちゃいましょう。

そのまま削除しても良いですが、念の為、データパーティションに圧縮&保存しておきます。

find /var/appl/data -type f -mtime +730 -name "*.jpg" | xargs tar zcvf /data/tmp/archive.tar.gz

作成したtarファイルのエントリーを確認します。

tar ztvf /data/tmp/archive.tar.gz

削除を実行します。
ちなみに-execrmに渡すより、パイプでxargs rmに渡す方がプロセス面で効率が良いです。

find /var/appl/data -type f -mtime +730 -name "*.jpg" | xargs rm

使用率が大幅に減ったことをdfで確認します。

$ df
Filesystem     1K-blocks     Used Available Use% Mounted on
/dev/xvda1      15180980 11428788   3735808  76% /
/dev/xvdb       15416264  9397284   5216164  65% /data
udev             4060904        0   4060904   0% /dev
tmpfs             815080      780    814300   1% /run

恒久対処

この手のクリーンアップ処理はcronに仕込んで定期的に実行させるのがセオリーです。
設定しましょう。

毎月15日の午前6時に実行する例です。

00 6 15 * * find /var/appl/data -type f -mtime +730 -name "*.jpg" | xargs rm

ディスク容量の拡張

その後、専用パーティションの/dataが満杯になり、データ保持ポリシー(データ保全期間)の見直しもあったので、/dataを拡張しました。

拡張前のサイズを確認します。

$ df
Filesystem     1K-blocks     Used Available Use% Mounted on
/dev/xvda1      15180980 12940288   2224308  86% /
/dev/xvdb       15416264 14613448         0 100% /data

Amazon EBS では、ボリュームサイズの増大が、ボリュームをデタッチすることなく動的かつ簡単に行えるので、変更のリクエストをします。

ext4ファイルシステムのサイズを変更します。

resize2fs /dev/xvdb

ブロックデバイスの一覧を表示します。

$ lsblk
NAME    MAJ:MIN RM   SIZE RO TYPE MOUNTPOINT
xvda      202:0    0    15G  0 disk 
└─xvda1 202:1    0    15G  0 part /
xvdb    202:16   0    30G  0 disk /data

サービスを停止することなく、サイズが拡張されました。

$ df
Filesystem     1K-blocks     Used Available Use% Mounted on
/dev/xvda1      15170820 12916420   2238016  86% /
/dev/xvdb       30853116 16032956  13377728  55% /data

ちなみに、/dev/xvda1のように、パーティションに対して指定するとエラーになります。

# resize2fs /dev/xvda1
resize2fs 1.44.1 (24-Mar-2018)
The filesystem is already 3931899 (4k) blocks long.  Nothing to do!

この場合、先立ってgrowpartでパーティションを拡張しておきます。

# growpart /dev/xvda 1
CHANGED: partition=1 start=2048 old: size=31455199 end=31457247 new: size=62912479,end=62914527

Discussion