【AWS】【CloudWatch】異常で止まったインスタンスを自動で再起動させる

最近サーバーの復旧作業を行う機会がありました。

原因は恐らくメモリ不足です。
過去のアクセス数がわかる情報が無かったため最小の構成で構築しましたが、実際に稼働させて見ると耐えられないほどのユーザーが訪れたようです。
冗長化は重要ですね。


さて、
絶対に落ちないサービスが無いという前提のもと、重要なのはサービスのダウンタイムを減らす事です。

一般的には、サーバーを複数台用意しロードバランサーでユーザーを捌いたり、1つのサーバーが落ちても直ぐに予備のサーバーに切り替えるようにします。
しかし、予算の都合でリソースが割けなかったり、稼働後で構成が変えられなかったりと冗長化の対策が難しい場合があります。

AWSでは、CloudWatchというサーバーの監視を目的としたサービスがあります。
docs.aws.amazon.com

CloudeWatchは、サーバの情報を監視し、問題が発生したら管理者にメール等で通知する事ができます。
他にも、「インスタンスの再起動」 等のEC2の状態を変更させる事も出来ます。

今回は、CloudeWatchを使って、異常終了したインスタンスを自動的に再起動する仕組みを作ります。

参考ページ

構築内容や設定値については、公式ドキュメントを参考に行います。
docs.aws.amazon.com

事前準備

必要なポリシー

今回の要件を実現するには、対象のIAMに次のポリシーを付与する必要があります。

  • AWSServiceRoleForCloudWatchEventsロールに含まれるポリシー
  • IAMを操作するためのポリシー

私が、監視のために作成したポリシーは次のようになります。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "ec2:RebootInstances",
                "ec2:DescribeInstances",
                "ec2:DescribeVolumeStatus",
                "ec2:TerminateInstances",
                "ec2:DescribeVolumes",
                "ec2:CreateSnapshot",
                "cloudwatch:DescribeAlarms",
                "iam:ListRoles",
                "ec2:DescribeSnapshots",
                "ec2:StopInstances",
                "ec2:DescribeInstanceStatus"
            ],
            "Resource": "*"
        },
        {
            "Sid": "VisualEditor1",
            "Effect": "Allow",
            "Action": [
                "iam:GetRole",
                "iam:GetPolicyVersion",
                "iam:GetPolicy",
                "iam:ListAttachedRolePolicies",
                "iam:CreateRole",
                "iam:AttachRolePolicy"
            ],
            "Resource": [
                "arn:aws:iam::*:policy/*",
                "arn:aws:iam::*:role/*"
            ]
        }
    ]
}

CloudWatchを使用する上で関連するポリシーについて

CloudWatchでインスタンスを再起動するために必要なポリシーを設定しました、他の機能を使う場合、別途ポリシーの設定が必要です。
必要なポリシーは次のページより確認できます。

docs.aws.amazon.com

アラームの設定

まず、先ほど設定したIAMのアカウントでAWSにログインします。

Cloudwatchのトップページに移動し、左カラムから「アラーム」を選択します。
アラームの一覧画面に遷移しますので、「アラーム作成」ボタンを押下して設定画面に移動します。

f:id:nakahashi_h:20190110022416p:plain

メトリクス設定

まず、計測の対象を設定します。

「メトリックスの選択」を押下します。
f:id:nakahashi_h:20190110022527p:plain

「すべてのメトリクス」タブを選択し、「EC2」->「インスタンス別メトリクス」でインスタンス毎の一覧を表示します。
「メトリクス名」から、StatusCheckFailed_Instanceという項目を探し、左のチェックボックスを有効にします。
f:id:nakahashi_h:20190110021650p:plain

計測の間隔を設定

デフォルトだと計測の間隔は5分毎です。
しかし、サービスが止まっている事をより早く検知するためには、5分は長いです。

そのため、計測の間隔を1分毎に変えます。
「グラフ化したメトリクス」タブを開き、対象レコードの値を次のように変えます。

設定項目 内容
統計 最小
期間 1分

f:id:nakahashi_h:20190110022110p:plain

変更後、右下の「メトリクスの変更」を押下します。

アラーム詳細の設定

今回は、下記のように設定します。

設定項目 内容
名前 Reboot EC2 instance
説明 Reboot EC2 instance when health checks fail
次の時 StatusCheckFailed_Instance (StatusCheckFailed_Instance)※1
> 0
期間 5 / 5 データポイント

※1 メトリックス選択で選択した内容が入りますので特に操作は不要です。

f:id:nakahashi_h:20190110022858p:plain

アクション設定

次に、再起動の設定を行います。

通知

まず、再起動を実行した時に送信される通知の設定です。
通知の項目は次のように設定します。

設定項目 内容
アラームが次の時 状態:警告
通知の送信先 適当なリストを追加してください。
初めて使う場合はリストがないので、右の「新しいリスト」から追加できます。

EC2アクション

インスタンスを再起動するアクションを追加します。

右下のEC2アクションを押下し、新しくEC2アクションのウィンドウを追加します。
追加すると、入力エリアが追加されます。

EC2アクションの項目は次のように設定します。

設定項目 内容
アラームが次の時 状態:警告
次のアクションを実行 このインスタンスの再起動

この後、「アラームの作成」を押下して設定完了です。

検証方法

検証するためには、インスタンスが不正に止まった事を再現する必要があります。
今回は、ネットワークを意図的に切断します。
SSHにでサーバに接続して次のコマンドを実行します。  

$ curl http://169.254.169.254/latest/meta-data/instance-id ; echo
(インスタンスIDに誤りがない事を確認)
$ sudo ifdown eth0
(以降、サーバー停止)

実行すると次の順で処理が進みます。

  1. インスタンスが停止。(止まるまでに数分のラグがあります。)
  2. インスタンスを再起動
  3. 再起動をした事を通知

参考URL

dev.classmethod.jp

Tips

アラームの期間の読み方

CloudWatchのバージョンによって表記が揺れますが、 現在のアラーム詳細の初期値は次のようになっているかと思います。

期間:1 / 1 データポイント

上記の内容を文章にすると、次のようになります。

1回計測し、しきい値(設定値)を超えたらアラート対象

記事内で設定した期間について

記事内では次のように設定しました。

f:id:nakahashi_h:20190110022858p:plain

期間を「5/5データポイント」設定しています。
この期間は文章で言い換えると次の通りです。

期間:5 / 5 データポイント
= 5回(1分を5セット)計測して、5回ともしきい値を超えたらアラート対象

参考URL

docs.aws.amazon.com

サーバーが落ちた場合の原因の探り方

サーバーが落ちてしまった場合、速やかに復旧する事も重要です。
同時になぜ落ちてしまったかの原因究明も必要です。

サーバーが落ちる原因を調べてみると、下記のようなケースがありえます。

  • マシンに高負荷がかかったため、自動的にマシン停止。
    • スペック的な面
    • 外部より不正に負荷をかけられる
  • 意図的にマシン停止
    • sshでサーバー侵入して停止させる
    • AWSのコンソールからインスタンスを停止
  • AWSが何らか理由でマシン停止
    • メンテナンス
    • 利用料金の未払い等の契約不備
    • 事故

もちろん、他にもたくさん理由があると思います。
原因を探るときの参考にしていただけると幸いです。

 AWSのコンソールから確認できるインスタンス状態遷移のログ

EC2インスタンスの管理画面の説明タブには「状態遷移の理由メッセージ」、「状態遷移の理由」という項目があります。
今回は復旧後に知ったため確認はしていないのですが、この項目からも情報を得られるかもしれません。

f:id:nakahashi_h:20190110014932p:plain

©︎2017-2018 WebSandBag