特定の時間帯にCPU使用率が高騰した時のみEC2インスタンスを自動で再起動させる方法

EC2インスタンス内部でcronを使用し、aws cliで特定の時間にCloudWatchアラームの作成と削除するようにスケジュールを設定しました。
2022.12.06

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

困っていた内容

特定の時間帯にCPU使用率が高騰した時のみEC2インスタンスを自動で再起動させたいです。

どうすればいいの?

他にも方法はあると思いますが、今回はEC2内部でcronを使用し、特定の時間にCloudWatchアラームの作成と削除するようにスケジュールを設定しました。

設定方法

EC2インスタンス用のIAMロールを作成する

CloudWatchにアクセス可能なIAMポリシーを設定します。 今回は、IAM ポリシー「CloudWatchFullAccess」をアタッチしました。必要な権限を付与してください。

EC2 を起動する

EC2を起動します。 今回は Amazon Linux 2 を使用しています。

$ cat /etc/os-release
NAME="Amazon Linux"
VERSION="2"
ID="amzn"
ID_LIKE="centos rhel fedora"
VERSION_ID="2"
PRETTY_NAME="Amazon Linux 2"
ANSI_COLOR="0;33"
CPE_NAME="cpe:2.3:o:amazon:amazon_linux:2"
HOME_URL="https://amazonlinux.com/"

EC2にSSH接続し、Cronを設定する

EC2にSSH接続します。

$ ssh -i "***.pem" ec2-user@ec2-3-96-168-65.ca-central-1.compute.amazonaws.com

CloudWatchアラームを作成するCLI用のJSONファイルを作成します。

$ vi /home/ec2-user/create-cw-alarm-ec2-reboot.json

create-cw-alarm-ec2-reboot.json は以下の内容で設定します。

{
    "Namespace": "AWS/EC2",
    "MetricName": "CPUUtilization",
    "Dimensions": [
        {
            "Name": "InstanceId",
            "Value": "i-0cef0c5afe9414797"
        }
    ],
        "AlarmActions": [
            "arn:aws:automate:ca-central-1:ec2:reboot"
        ],
        "ComparisonOperator": "GreaterThanThreshold",
        "DatapointsToAlarm": 1,
        "EvaluationPeriods": 1,
        "Period": 300,
        "Statistic": "Maximum",
        "Threshold": 80,
        "AlarmDescription": "CPU Utilization with 80% as threshold",
        "AlarmName": "CPU80-ec2-reboot"
}

crontabに下記のように設定します。今回は試しに、5:30pm(UTC) に put-metric-alarm を実行、6:30pm(UTC) delete-alarms を実行するように設定しています。

$ sudo crontab -e
30 17 * * * aws cloudwatch put-metric-alarm --region ca-central-1 --cli-input-json file:///home/ec2-user/create-cw-alarm-ec2-reboot.json
30 18 * * * aws cloudwatch delete-alarms --region ca-central-1 --alarm-names CPU80-ec2-reboot

試してみた

設定した時間に put-metric-alarm が実行されたことを確認しました。

$ sudo tail -f /var/log/cron
〜・〜・〜・〜・
Dec  2 17:30:01 ip-172-31-13-2 CROND[3621]: (root) CMD (aws cloudwatch put-metric-alarm --region ca-central-1 --cli-input-json file:///home/ec2-user/create-cw-alarm-ec2-reboot.json)

CloudWatchコンソールでCloudWatchアラームが作成されていることを確認しました。

一時的にCPUに負荷をかけるため、EC2にStressツールをインストールします。

$ sudo amazon-linux-extras install epel -y
$ sudo yum install stress -y
$ stress --version
stress 1.0.4

StressツールでCPUに負荷をかけます。

$ stress -c 1
stress: info: [3308] dispatching hogs: 1 cpu, 0 io, 0 vm, 0 hdd

topコマンドでCPU使用率を確認するため、別ターミナルで同じインスタンスにログインします。 Stressコマンドで100%近くCPUが使用されていることを確認しました。

top - 17:43:18 up 45 min,  3 users,  load average: 1.79, 0.70, 0.26
Tasks: 109 total,   3 running,  64 sleeping,   0 stopped,   0 zombie
%Cpu(s):100.0 us,  0.0 sy,  0.0 ni,  0.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem :   988916 total,   384800 free,    88380 used,   515736 buff/cache
KiB Swap:        0 total,        0 free,        0 used.   761120 avail Mem 

  PID USER      PR  NI    VIRT    RES    SHR S %CPU %MEM     TIME+ COMMAND                                          
 3649 ec2-user  20   0    7584    100      0 R 98.0  0.0   2:36.78 stress   
〜・〜・〜・〜・

CloudWatchアラームの状態がアラーム状態となり、設定したアクションにてEC2の再起動が始まったのでターミナルがクローズされました。

Connection to ec2-3-96-168-65.ca-central-1.compute.amazonaws.com closed by remote host.
Connection to ec2-3-96-168-65.ca-central-1.compute.amazonaws.com closed.

CloudWatchアラームのコンソールを確認します。CloudWatchメトリクス 「CPUUtilization」が80%を超え、「アラーム状態」となりました。

CloudWatchアラームのアクションが実行されたことを確認しました。

EC2に再度ログインし、OSが再起動されたことを確認しました。

$ last reboot
reboot   system boot  5.10.147-133.644 Fri Dec  2 17:47 - 17:50  (00:02)    
reboot   system boot  5.10.147-133.644 Fri Dec  2 16:57 - 17:50  (00:53)

再度、CloudWatchアラームのコンソールを確認します。インスタンスが再起動され、CPU使用率が下がったことでアラームの状態が[OK]に変化しました。

設定した時間に delete-alarms が実行されたことを確認しました。

$ sudo tail -f /var/log/cron
〜・〜・〜・〜・
Dec  2 17:30:01 ip-172-31-13-2 CROND[3621]: (root) CMD (aws cloudwatch put-metric-alarm --region ca-central-1 --cli-input-json file:///home/ec2-user/create-cw-alarm-ec2-reboot.json)
〜・〜・〜・〜・
Dec  2 18:30:01 ip-172-31-13-2 CROND[3427]: (root) CMD (aws cloudwatch delete-alarms --region ca-central-1 --alarm-names CPU80-ec2-reboot)

参照情報

EC2にStressコマンドをインストールする方法
crontabの書き方