概要
トラブルシューティング
普段サーバーにつないで開発や運用をしているとサーバーにつながらないといったトラブルを経験することがあるかもしれません。エンジニアは不具合が生じた場合にいかにトラブルシューティング力が試される職種でもあります。
今回はサーバーのディスク残容量がなくSSH接続ができなくなってしまった事例をもとに解決する流れを説明していきます。本記事では現象の調査から解決(暫定対応と恒久対応)までの思考過程をなるべく言語化してみたので参考にしてみてください。
思考の流れ
発生時の状況
VS CodeでAWSのEC2(Amazon linux 2023、t2.micro)にSSH接続して開発を行っていました。するとあるタイミングからSSH接続が切れてつながらなくなってしまいました。
再現性の確認
まず初めに再現性を確認します。起こっている現象が一時的なものか、継続的なものかで対応策が変わるためです。システムトラブルではよく再起動をすることがあります。今回、サーバーではバッチなどの常駐プログラムがないことがわかっていますのでVS CodeやEC2を再起動してみることにしました。しかしSSH接続ができない状況は変わらなかったため、何かが原因で現象が継続していることがわかります。
ログの確認
次にすべきことはログを確認することです。トラブルが発生するとその現象の根拠がログに出力されることが多いです。そのためログが確認できる状況ではログを確認します。
今回であればクライアントはVS Codeを、サーバーはEC2を利用しているのでこの2つでログが出力されていないかを確認しました。するとVS CodeターミナルのOUTPUTタブで下記のログが出力されていました。注意深く読むと7行目にNo space left on device
の文字があります。これはLinuxを使っているとよく目にする文言で容量不足を指摘するキーワードです。どうやらEC2のディスク容量の空きがなくっていることが原因のようです。
...
[18:56:14.563] >
> /home/ec2-user/.vscode-server/.cli.e8653663e8840adaf45af01eab5c627a5af81807.log:
> No such file or directory
> main: line 389: /home/ec2-user/.vscode-server/.cli.e8653663e8840adaf45af01eab5c6
> 27a5af81807.log: No space left on device
...
対応策の整理
ここまででの情報でEC2のディスク容量が増えれば問題が解決しそうです。解決の糸口が見えてから実際に対策を行うのがよいでしょう。今、クライアントからSSH接続できないのでAWSのマネジメントコンソールからEC2への接続を試みます。ここでSSH接続をした後でディスク容量の空きを増やすようにします。
実施手順
暫定対応
AWSからEC2に接続
AWSからEC2に接続するにはいくつか方法がありますが、今回は手軽なEC2 Instance Connectを利用します。元々SSH接続ができていたのであればこの方法を利用することでAWSのマネジメントコンソールから接続することが可能です。今回はディスク容量の空きを増やすことがメインのテーマですので、利用方法はこちらをご参考ください。
ディスクの空き容量確認
AWSからEC2に接続できたらdf -h
で空き容量を確認します。6行目から分かるように空き容量がほとんどないことがわかります。
[ec2-user@ip-172-31-38-158 ~]$ df -h
Filesystem Size Used Avail Use% Mounted on
devtmpfs 4.0M 0 4.0M 0% /dev
tmpfs 475M 0 475M 0% /dev/shm
tmpfs 190M 432K 190M 1% /run
/dev/xvda1 8.0G 7.9G 0.1G 99% /
tmpfs 475M 0 475M 0% /tmp
/dev/xvda128 10M 1.3M 8.7M 13% /boot/efi
tmpfs 95M 0 95M 0% /run/user/1000
容量が大きいディレクトリの特定
容量が大きいディレクトリやファイルを特定してきます。まずはsudo du -sh /* 2>/dev/null
でディレクトリ容量を確認します。linuxの場合、tmp
やvar
に大容量ファイルが保存されることがありますが、今回はvar
の容量が大きいようです。
# 容量が大きいディレクトリを特定
[ec2-user@ip-***-***-***-*** ~]$ sudo du -sh /* 2>/dev/null
0 /bin
40M /boot
0 /dev
22M /etc
1.3G /home
0 /lib
0 /lib64
0 /local
0 /media
0 /mnt
116K /opt
0 /proc
3.1M /root
416K /run
0 /sbin
0 /srv
0 /sys
0 /tmp
2.0G /usr
4.3G /var
さらに調査を進めます。sudo du -ah /var | sort -rh | head -n 20
を実行することでvar
の中で容量が大きいファイルを特定することができます。コマンド実行の結果、どうやらvar/lib/docker/overlay2
直下のファイルの容量が大きいことがわかりました。おそらくdockerコンテナのごみが残ってしまっている可能性が高いと思われます。
# 画面の都合上文字列を...にしてあります。
[ec2-user@ip-***-***-***-*** ~]$ sudo du -ah /var | sort -rh | head -n 20
4.3G /var
4.2G /var/lib
4.1G /var/lib/docker/overlay2
4.1G /var/lib/docker
588M /var/lib/docker/overlay2/5c...34b/diff
588M /var/lib/docker/overlay2/5c...34b
579M /var/lib/docker/overlay2/5c...34b/diff/usr
470M /var/lib/docker/overlay2/t58g1u0mt89p0squwq0okisvn/diff
470M /var/lib/docker/overlay2/t58g1u0mt89p0squwq0okisvn
470M /var/lib/docker/overlay2/kvxb9atcwuk4fq1vku47fike9/diff
470M /var/lib/docker/overlay2/kvxb9atcwuk4fq1vku47fike9
390M /var/lib/docker/overlay2/5c...34b/diff/usr/lib
316M /var/lib/docker/overlay2/qohqnd6kae0vphlgk2exto9ps/diff
316M /var/lib/docker/overlay2/qohqnd6kae0vphlgk2exto9ps
310M /var/lib/docker/overlay2/qohqnd6kae0vphlgk2exto9ps/diff/usr
310M /var/lib/docker/overlay2/gyad3r7t256ne6uiihwugz9bc/diff
310M /var/lib/docker/overlay2/gyad3r7t256ne6uiihwugz9bc
305M /var/lib/docker/overlay2/gyad3r7t256ne6uiihwugz9bc/diff/usr
260M /var/lib/docker/overlay2/5c...34b/diff/usr/lib/x86_64-linux-gnu
224M /var/lib/docker/overlay2/t58...svn/diff/Python-3.9.6
削除するしないの判断
ここで慌ててファイルを削除しないようにしましょう。なぜならばファイルを削除することで最悪サーバーや特定のアプリケーションが動作しなくなってしまうことがあるからです。そのため削除する前はバックアップを取ることが望ましいです。
今回は調査の結果、dockerコンテナのごみ削除には専用のコマンドであるdocker system prune
が適していることがわかりました。まずはこちらを実行してみてから手動削除を検討します。実行の結果、13行目で1.372GBの容量を確保することに成功しました。
[ec2-user@ip-***-***-***-*** ~]$ docker system prune
WARNING! This will remove:
- all stopped containers
- all networks not used by at least one container
- all dangling images
- unused build cache
Are you sure you want to continue? [y/N] y
Deleted Containers:
...
Total reclaimed space: 1.372GB
参考:ログやキャッシュの削除
下記のコマンドを実行することでログやキャッシュを削除することが可能です。これらも削除前に本当に削除してよいかを確認してください。
# ログファイルの削除
sudo rm -f /var/log/amazon/ssm/*.log
sudo rm -f /var/log/sa/*
# ジャーナルログの削除
sudo journalctl --vacuum-size=50M
sudo journalctl --vacuum-time=3d
# Amazon Linux でのパッケージキャッシュ削除
sudo du -sh /var/cache
sudo yum clean all
# tmpディレクトリの確認と削除
sudo du -ah /tmp | sort -rh | head -n 20
sudo rm -rf /tmp/*
対応結果
最後に容量が変化したかを確認します。sudo du -sh /* 2>/dev/null
を実行すると21行目のvar
の容量が4.3GBから2.5GBに減っていることがわかります。
[ec2-user@ip-172-31-38-158 ~]$ sudo du -sh /* 2>/dev/null
0 /bin
40M /boot
0 /dev
22M /etc
1.3G /home
0 /lib
0 /lib64
0 /local
0 /media
0 /mnt
116K /opt
0 /proc
3.1M /root
432K /run
0 /sbin
0 /srv
0 /sys
0 /tmp
2.0G /usr
2.5G /var
続いてdf -h
を実行すると99%から75%に減っていることがわかります。
[ec2-user@ip-172-31-38-158 ~]$ df -h
Filesystem Size Used Avail Use% Mounted on
devtmpfs 4.0M 0 4.0M 0% /dev
tmpfs 475M 0 475M 0% /dev/shm
tmpfs 190M 432K 190M 1% /run
/dev/xvda1 8.0G 5.9G 2.1G 75% /
tmpfs 475M 0 475M 0% /tmp
/dev/xvda128 10M 1.3M 8.7M 13% /boot/efi
tmpfs 95M 0 95M 0% /run/user/1000
ここまで対応をして再度VS CodeからSSH接続すると、見事にSSHが成功しました。
恒久対応
以上が暫定対応でしたが、これだとまたいつの日か容量不足に陥った時に同じような現象に遭遇する可能性があります。そこで容量不足にならないように恒久対応を解説します。
ジャーナルログの制限
下記のコマンドを実行することでジャーナログの容量を制限することができます。ジャーナルログとは、システム資源やデータに対する変更を記録したもので、システムの問題解決やデータの回復に役立ちます
sudo journalctl --vacuum-size=100M
sudo journalctl --vacuum-time=2d
EBSのボリューム拡張
そもそものディスク容量が十分でない場合は容量の拡張を検討します。EC2のディスクであるEBSの容量拡張は下記の記事を参考に実施してみてください。
残容量の監視
AWSのEC2のハードディスクの使用率を監視するにはCloudWatchのカスタムメトリクスを定義する必要があります。本記事では紹介に留めますが、必要に応じて実施してみるのもいいでしょう。
まとめ
本記事では技術の解説というより不具合の調査の流れを言語化しました。問題の原因を見つけることができれば問題の80%は解決したと思えるくらい、最初の原因調査が重要です。現場で不具合が生じたときも落ち着いて原因を調査してみましょう!