この EC2 インスタンスを最後に使ったのいつ?EC2 インスタンスの最終起動時刻と停止時刻を一括で取得する

User initiated shutdown であれば「状態遷移の理由」に停止時刻が含まれるので、それに相当する StateTransitionReason を取得することでいい感じに一覧表示できます。

このインスタンスいつから動いてる/止まってるんだろう

コンバンハ、千葉(幸)です。

皆さん、EC2 インスタンスは適切に管理されていますか?具体的には、以下の情報がパッと出るでしょうか。

  • 起動しているインスタンスの場合
    • いつから起動しているのか?
  • 停止しているインスタンスの場合
    • いつ停止されたのか?
    • 最後に起動したのはいつか?

台数が限定的であればそれらの利用状況を把握するのはそこまで難しくありません。しかし、台数が多い・関係者が多数である といった事情ですぐに答えられないこともあるでしょう。もしくは、はじめましての環境を調査する際に関係者へのヒアリング前にパパッと手元で調べたいこともあるかと思います。(わたしはありました。)

少し条件付きとなりますが、AWS CLI を使用して上記の情報を取得できます。その内容と関連情報をまとめておきます。

EC2 インスタンスの起動時刻と停止時刻を一括で取得するコマンド

使用するのは以下の AWS CLI コマンドです。

コマンドの実行例は以下です。

% aws ec2 describe-instances\
 --query 'Reservations[].Instances[].{
     InstanceId:InstanceId,
     Name:Tags[?Key==`Name`]|[0].Value,
     State:State.Name,
     LaunchTime:LaunchTime,
     StateTransitionReason:StateTransitionReason
     }'\
 --output table
----------------------------------------------------------------------------------------------------------------------
|                                                  DescribeInstances                                                 |
+---------------------+----------------------------+--------+----------+---------------------------------------------+
|     InstanceId      |        LaunchTime          | Name   |  State   |            StateTransitionReason            |
+---------------------+----------------------------+--------+----------+---------------------------------------------+
|  i-047875da17caa9xxx|  2022-07-05T15:55:14+00:00 |  TestA |  stopped |  User initiated                             |
|  i-04bdd5595e5ac5xxx|  2022-03-06T05:26:05+00:00 |  TestB |  stopped |  User initiated (2022-03-06 12:24:00 GMT)   |
|  i-0b22e15a7b41ddxxx|  2022-06-02T05:58:04+00:00 |  TestC |  stopped |  User initiated (2022-06-02 06:05:59 GMT)   |
|  i-0cd8f6111725f0xxx|  2022-07-06T13:46:36+00:00 |  TestD |  running |                                             |
+---------------------+----------------------------+--------+----------+---------------------------------------------+

ここで取得できるのは以下の情報です。

  • InstanceId:インスタンス ID
  • LaunchTime:最後に起動した時刻
  • Name:インスタンスのNameタグの値
  • State:インスタンスの状態
  • StateTransitionReason:状態が変化した理由
    • Staterunningの場合、ブランク
    • Statestoppedの場合、以下のいずれか *1
      • User initiated + 停止時刻(AWS API で停止した場合)
      • User initiated(OS から停止した場合)★

注意していただきたいのは★の部分です。

インスタンスを停止する手法は大きく分けて以下2種があります。

  • AWS API で停止(マネジメントコンソールや AWS CLI による停止など)
  • OS から停止(OS 上でのshutdownコマンドの実行など)

後者の「OS から停止」によって停止状態にあるインスタンスは、StateTransitionReasonに停止時刻が記録されません。例ではTestAインスタンスが該当します。

今回の手法ではそのようなインスタンスがいつ停止されたかの情報は取得できませんのでご注意ください。

インスタンスのライフサイクル

おさらいとして、インスタンスのライフサイクルを押さえておきます。

インスタンスのライフサイクル - Amazon Elastic Compute Cloud より

Launchという言葉は「AMI からインスタンスを起動(新規作成)すること」を指す場合が多い印象ですが、冒頭で見たLaunchTimestoppedからrunningに遷移した時間も表します。

また、running中に行った再起動はLaunchTimeに影響を与えません。ここでの再起動は AWS API によるものと OS から行ったものの両方を指します。

User initiated shutdown と Instance initiated shutdown

冒頭の繰り返しになりますが、インスタンスを停止する手法は大きく分けて以下2種があります。

  • AWS API で停止(マネジメントコンソールや AWS CLI による停止など)
  • OS から停止(OS 上でのshutdownコマンドの実行など)

マネジメントコンソールでは以下を参照することで、上記のいずれであるかを判別できます。

EC2_stopped

表示パターンと、ついでに CloudTrail ・AWS Config での記録有無をまとめたものが以下です。

AWS API で停止の場合 OSから停止の場合
状態遷移の理由 User initiated (+状態遷移の時刻) User initiated(時刻の記載無し)
状態遷移の理由メッセージ Client.UserInitiatedShutdown: User initiated shutdown Client.InstanceInitiatedShutdown: Instance initiated shutdown
Trail での記録 される されない
Config での記録 される される

そして切り口を少し変えてマネジメントコンソールにおける「状態遷移の理由」「状態遷移メッセージ」が、 AWS API のレスポンスや AWS CLI のアウトプットのどれに該当するのか?をまとめたものが以下です。

状態遷移の理由 状態遷移の理由メッセージ
AWS API reason stateReason.message
AWS CLI StateTransitionReason StateReason.Message

AWS API のレスポンスを基準に見ていきます。

reason

reasonは以下から確認できます。具体的にどういった値が入るのか?の詳細は記載されていませんでした。

reason

The reason for the most recent state transition. This might be an empty string.

今回の AWS CLI コマンドではこのreasonに相当するStateTransitionReasonを取得しています。

stateReason.message

stateReason.messageは以下で確認できます。

ユーザー(クライアント)の操作による停止の場合、以下のふたつが該当します。

  • Client.UserInitiatedShutdown: The instance was shut down using the Amazon EC2 API.
  • Client.InstanceInitiatedShutdown: The instance was shut down using the shutdown -h command from the instance.

参考までに AWS (サーバー)側の事情による停止の場合、以下が該当しそうです。

  • Server.ScheduledStop: The instance was stopped due to a scheduled retirement.
  • Server.SpotInstanceShutdown: The instance was stopped because the number of Spot requests with a maximum price equal to or higher than the Spot price exceeded available capacity or because of an increase in the Spot price.

User initiated shutdown でも Instance initiated shutdown でも、「状態遷移の理由」がUser initiatedと表されるのがややこしいポイントですね。 *2

対象のインスタンスをフィルタリングして出力する

冒頭で載せたコマンドでは環境内のインスタンスがすべて出力されるため、対象のインスタンスを絞って表示したい、ということもあるでしょう。

その場合は--filtersオプションを使用するか、--queryオプションの中で条件を指定します。

それぞれで「停止中のインスタンスのみ」でフィルタリングするイメージは以下です。

filtersを使用する場合

aws ec2 describe-instances\
 --filters Name=instance-state-name,Values=stopped\
 --query 'Reservations[].Instances[].{
     InstanceId:InstanceId,
     Name:Tags[?Key==`Name`]|[0].Value,
     State:State.Name,
     LaunchTime:LaunchTime,
     StateTransitionReason:StateTransitionReason
     }'\
 --output table

queryを使用する場合

aws ec2 describe-instances\
 --query 'Reservations[].Instances[?State.Name==`stopped`]|[].{
     InstanceId:InstanceId,
     Name:Tags[?Key==`Name`]|[0].Value,
     State:State.Name,
     LaunchTime:LaunchTime,
     StateTransitionReason:StateTransitionReason
     }'\
 --output table

どちらでも大差ないと思いますが、個人的には前者の方が好きです。--queryの中身を変更しなくて済むためです。

--filtersを基本としつつ、それで賄えない条件を指定したい場合は--queryを使用する、という使い分けがおすすめです。 *3

マネジメントコンソールで停止時刻を一覧で見れない?

ここまで見てきたような AWS CLI コマンドを使わず、マネジメントコンソールで停止時刻も含めて「一覧で」見たい、ということもあるかと思います。

残念ながら一覧では「状態遷移の理由」を表示できないため、実現できません。

インスタンス一覧画面の設定をカスタマイズする際、属性列で「状態遷移の理由」を選択できません。「状態遷移理由コード」というものに置き換わっています。

Instances_customize

念の為これを選択して確認してみますが、停止時刻は含まれていません。

EC2_Instance_satereason

マネジメントコンソールから停止時刻を確認したい場合はインスタンスの詳細からひとつずつ見ていくほかなさそうです。数が少ない場合は頑張れるかもしれませんが、なるべく AWS CLI での一覧取得をおすすめします。

終わりに

このインスタンスっていつから動いてるの?(あるいはいつから止まってるの?)を一括で確認したい、という話でした。

環境調査、棚卸しの際などにご活用ください。

他のパラメータも一緒に取得したい、出力形式を変えたい、という場合は以下のエントリもご参考ください。

何かの参考になれば幸いです。

以上、 チバユキ (@batchicchi) がお送りしました。

参考

脚注

  1. running、stopped以外の状態のパターンは精査できていませんが、特に有効な値は入らない(遷移前の状態時の値から変わらない)ような挙動に見えました。
  2. 「Client initiated」だったらしっくりきます。
  3. 具体的にどんな条件?と問われるときちんと精査しきれていません。--filters の Values に「null」は指定できなかったと記憶しているので、そういったケースを想定しています。