LoginSignup
9
10

More than 5 years have passed since last update.

一定時間利用されていないEC2インスタンスを自動でstopする

Last updated at Posted at 2018-09-26

プライベートのOSS開発向けに、一定時間利用されていないAWSのEC2インスタンスを自動でstopする仕組みを作った。プライベート用なのでちょっと雑かも。

最初は【AWS】CloudWatch入門/使っていないEC2を自動シャットダウンしよう のように CloudWatch で CPU 使用率を監視すれば良いかと思ったが、やってみると vim を開いて編集しているだけの時間が案外長く、利用中なのにstopされてしまうことが多かったのでもう少し工夫した。

要件

  • 一定時間利用されていないAWSのGPUインスタンスを自動でstopしたい
  • ただし、vim を開いて編集しているだけのような CPU を喰わない時間帯も利用中なので stop したくない
  • ただし、GPUを使って deep learning の学習を走らせているような時間帯も利用中なので stop したくない
  • tmux や screen を使うので、余計なプロセスは生き続けている可能性があることも注意

設計

  1. ssh セッションが生きて入れば ssh して作業中なので「active」と定義する
  2. CPU 使用率が 2% より大きければなにか処理中なので「active」と定義する
  3. cron に仕込んで AWS CloudWatch に CustomMetrics として active か否かの情報を投げる
  4. AWS CloudWatch で一定時間 Non Active なら EC2 インスタンスを stop するようにアラームを作る

ポイント

  • CloudWatch を使わずに cron で毎分 1 or 2 の判定をして Non Active だったら即座に shutdown -h now するような仕組みでも、大体は機能すると思うが、EC2インスタンス起動直後に shutdown される可能性があるため避けた。後はちょっとコーヒーブレークで離席して ssh セッション切れたらすぐ stop されそうなので避けた。
  • EC2上でログを吐いて、自前でログを舐めて一定時間(20分とか) Non Active なら shutdown するような仕組みにしても良いが、ログの rotate などを考えると面倒なので、AWS CloudWatch にデータを蓄積するようにした。
  • AWS CloudWatch は 2018/09 現在、複合メトリクス(AND, OR)を条件にしたアラームを作れないので、スクリプト側で 1 or 2 の判定を複合して「active か否か」の情報を投げるようにした。
  • GPU だけ使って CPU 全く使わないアプリケーションは存在しないので、CPU使用率だけ見れば良いことにした。GPU使用率も見た方が良いのは確かで、これはただの手抜き。

実装

is-active.sh
#!/bin/bash

# The first report of vmstat gives averages since the last reboot, drop it.
cpu_usage_usr=$(vmstat 1 2 | tail -1 | awk '{print $13}')
ssh_session_count=$(ss | grep '[s]sh' | wc -l)
if [ $cpu_usage_usr -gt 1 -o $ssh_session_count -gt 0 ]; then
  echo 1
  exit 0
fi
echo 0
exit 1
aws-put-mon-is-active.sh
#!/bin/bash
REGION=${1:-us-west-2}

SCRIPT_DIR=$(dirname "$0")
instance_id=$(curl --silent http://169.254.169.254/latest/meta-data/instance-id/)

value=$("$SCRIPT_DIR"/is-active.sh)
aws cloudwatch put-metric-data --namespace 'EC2/Custom' --metric-name 'IsActive' \
  --value "$value" --dimensions InstanceId="$instance_id" --region "$REGION"
/etc/cron.d/aws-put-mon-is-active
SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin
MAILTO=root
HOME=/home/sonots

* * * * * root /home/sonots/scripts/aws-put-mon-is-active.sh

あとは 【AWS】CloudWatch入門/使っていないEC2を自動シャットダウンしよう を参考に CPU 使用率の代わりに、今回作った EC2/Custom IsActive メトリクスを見るようなアラームを作って、一定時間(20分とか) Non Active なら stop するように設定。

なお、AWS CloudWatch アラームの EC2 アクションを選べるようにするには、カスタムメトリクスに InstanceId ディメンジョンを設定しなければならない(ので、してある)。

9
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
10