はじめに
検証用にマシンに思ったよりパワーが必要だったので、短時間だからいっか、という軽い気持ちで m5.xlarge
にパワーアップさせた。
検証自体は無事に終わって、後日ログ採取を取るために起動したのだが、仕事の合間だったのでログ採取してあとに停止するのをすっかり忘れてしまい3日ほど起動しっぱなしに。。。。
さすが m5.xlarge
たかが3日とは言え請求が結構エグい。
とても悲しい気持ちになったので使っていないEC2を自動で停止するスクリプトを描くことにした。
TL;DR
だれ向け?
- 私と同じ悲しみにくれている方
- 個人のAWSアカウントでごにょごにょされること方
- 会社の検証環境のEC2料金が高くて悩んでいる方
スクリプト
5分毎にCPU、Inbound通信、SSH接続をチェック
10回連続でin-activeだった場合、つまり50分間in-activeな場合にサーバをシャットダウンする例
crontab
SHELL=/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/opt/aws/bin:/root/bin:/opt/aws/bin
MAILTO=""
*/5 * * * * cd ~; /bin/bash /root/monitor.sh; [ `tail -n 10 /root/monitor.log | grep -P "^active" | wc -l` -eq 0 ] && halt -h now || echo no shut >> /root/log.txt
サーバが利用状態かそうでないかをチェックするスクリプト
5秒間の平均CPU利用率2%
以上、10秒間のInbound通信が1024Byte
以上、SSH接続が有る
場合にActiveと判断する
monitor.sh
#!/bin/bash
cpu_usage=2
net_usage=1024
ssh_session=1
status=0
log='monitor.log'
# The first report of vmstat gives averages since the last reboot, drop it.
# Adopt average CPU usage rate for 5 seconds
cpu_usage_usr=$(vmstat 1 10 | tail -5 | awk '{sum+=$13} END {print sum/NR}')
# Adopt inbound traffic received in 10 seconds.
net_usage_usr=$(for i in `seq 1 2`; do cat /proc/net/dev; sleep 10; done | grep eth0 | awk 'NR==1{m=$10}NR==2{print $10-m}')
# Determine whether there is an SSH connection.
ssh_session_count=$(/usr/sbin/ss | grep '[s]sh' | wc -l)
if [ `echo "$cpu_usage_usr > $cpu_usage" | bc` == 1 -o `echo "$net_usage_usr > $net_usage" | bc` == 1 -o $ssh_session_count -ge $ssh_session ]; then
status=1
fi
[ $status -eq 0 ] && status_str='in-active' || status_str='active'
echo $status_str $cpu_usage_usr $net_usage_usr $ssh_session_count >> $log
exit 0
解説
元ネタ様はこちらです。
一定時間利用されていないEC2インスタンスを自動でstopする
何番煎じかわからないですが、EC2のみで実装できてサクッと仕込める方法は見つからなかったのでこちらに記録しておきます。
ほぼ元ネタ記事そのままなのですが、自分用に修正した点は以下
要件
- 個人もしくは極少数しか使わない環境なので間違って落ちちゃっても問題にはならない
- コピペレベルで簡単に設定できること(設定の手間が増えると後回しにされて結局はじめにの悲劇が起こるため)
- webアプリがメインのためInbound通信も監視対象にする
- SSHで作業中は停止されたくない
方針
- シェルスクリプト+Crontabのみで実装
- 5秒間の平均CPU使用率が2%を超えている場合はActive
- 10秒間のInbound通信が1024Byteを超えている場合はActive
- SSH接続があればActive
- In-Activeが50分連続して続いてたらサーバシャットダウン
課題
- 運悪く起動時にCronが走ると停止されちゃう。起動後10分は監視対象外のような条件付けの検討が必要
- 厳密にはSSHで作業しているときはActiveにしたいだけで、無操作の場合はIn-Activeにしたい。Oubgoing通信も監視するとか、auditlog残すようにしてログのタイムスタンプで判断するとかもう一捻りが必要
参考リンク
【AWS】CloudWatch入門/使っていないEC2を自動シャットダウンしよう
一定時間利用されていないEC2インスタンスを自動でstopする