Systems Managerインベントリを使ってEC2のインベントリ情報帳票を作成する


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

はじめに

AWS Systems Manager(SSM) インベントリ はマネージドインスタンスからメタデータを収集して、情報表示する機能です。 OSやアプリケーション、ネットワーク設定などの情報を収集してくれます。

今回はインベントリを使った「定期的にEC2のインベントリ情報帳票を作成する」 の方法を紹介します。

1.前提

SSMを使うためには、当該リソースを「マネージドインスタンス」(SSMで管理されたインスタンスのこと)にする必要があります。マネージドインスタンスにするためには、以下の 3 点が必要です。

  1. インスタンスに SSM Agent が導入されていること
    SSM Agent の導入については今回は手順については触れません。
    詳しくはドキュメント↓を参照してください。
     SSM エージェント の使用

  2. インスタンスから SSM API へのネットワーク経路が確保されていること
     以下2パターンのどちらかで、SSM Agentからのアウトバウンド経路を確保する:
      ・インターネット経由
      ・VPCエンドポイント経由

  3. インスタンスに適切な IAM Role が付与されていること
     IAM Roleにアタッチが必要なIAM Policy:AmazonSSMManagerInstanceCore

※設定完了すれば、対象インスタンスがマネージドノードとして表示されていることを確認できる。
file

2.構成

今回作成する構成は以下の通りです。
(マルチアカウント構成の場合は、全てのアカウントのインベントリデータを特定アカウントのS3バケットへ集約することで一元管理をすることも可能です。)
file

  1. EC2のインベントリ情報はSystems Managerを経由してS3に収集される。
  2. 収集されたインベントリ情報データを抽出し、検索しやすい形にデータ変換を行う。
  3. 定期的にインベントリ情報帳票を作成するLambda関数を実行し、生成したインベントリ情報帳票をS3に保管する

ちなみに「はじめに」の説明では"メタデータの取得”とありましたが、実際にどのようなデータがメタデータとして取得できるのでしょうか。
主な取得可能情報は以下の通り:
以下以外にも、個別に取得設定(カスタムインベントリ)することが可能。

file

(詳細はAWSサイトを参照)


3.インベントリセットアップ

ここからは実際に設定を行っていきます。
まず、インベントリセットアップを行います。

  1. サービスの検索で、SSMと入力して、「System Manager」を選択します。左のメニューから「インベントリ」を選択します。ページが開いたら、「セットアップインベントリ」をクリックします。
    file

  2. 入力画面が出てきます。 以下の通り入力してみてください。
    名前:
    任意の名前を指定できます。
    file
    ターゲット:
    「インスタンスの手動選択」を選択します。
    file
    スケジュール:
    30分に指定します。
    file
    パラメータ:
    デフォルトのままにします。
    file
    file
    詳細設定:
    今回はS3に書き込まないので、チェックは外しておきます。
    さいごに
    右下のセットアップインベントリボタンをクリックします。
    file

  3. 画面が遷移して作成されていることが確認できました。

4.リソースデータ同期

次はインベントリ情報をS3へ格納するために同期設定を行います。
SSM リソースデータ同期を利用して、Inventoryの情報をS3に適宜出力します。

4.1.バケットポリシーの変更

まずはインベントリ情報を書き込めるようバケットポリシーを設定します。

  1. 対象バケットをクリックし、バケットの詳細画面を開きます。その後、上部の「アクセス許可」ボタンを押し、バケットポリシー「編集」ボタンを押します。
    file
    file

  2. 「ポリシー」に表示されている文字列(JSONドキュメントといいます)をすべて選択して削除し、以下の内容をコピーして貼り付けます。(まだ保存しません)

    {
       "Version": "2012-10-17",
       "Statement": [
         {
           "Sid": "SSMBucketPermissionsCheck",
           "Effect": "Allow",
           "Principal": {
             "Service": "ssm.amazonaws.com"
           },
           "Action": "s3:GetBucketAcl",
           "Resource": "arn:aws:s3:::YOUR_BUCKET_NAME"
         },
         {
           "Sid": " SSMBucketDelivery",
          "Effect": "Allow",
          "Principal": {
            "Service": "ssm.amazonaws.com"
           },
           "Action": "s3:PutObject",
           "Resource": "arn:aws:s3:::YOUR_BUCKET_NAME/*/accountid=YOUR_ACCOUNT_ID/*",
           "Condition": {
             "StringEquals": {
              "s3:x-amz-acl": "bucket-owner-full-control"
             }
           }
         }
       ]
     }

    こちらのページのバケットポリシー例をJSONをエディタ内に記述していきます。
    上記のjson内の
    "Resource":"arn:aws:s3:::YOUR_BUCKET_NAME"

    "arn:aws:s3:::YOUR_BUCKET_NAME//accountid=YOUR_ACCOUNT_ID/"
    backet-nameアカウントIDを変更する必要があります。

  3. Jsonの内容を修正できたら、右上の保存ボタンを選択します。

以上でバケットポリシーの変更は完了です。

4.2.SSMのリソースデータの同期設定

次はインベントリ情報をS3へ格納するために同期設定を行います。

  1. インベントリの画面が開いて、右上の「リソースデータの同期」ボタンをおします。
    file

  2. リソースデータの同期の一覧画面が開いたら、右上の「リソースデータの同期の作成」をクリックします。
    file

  3. 入力画面が出てきます。以下の通り入力してみてください。
    同期名:
    好きな名前をつける事ができます。
    バケット名:
    S3のバケット名を設定します。
    バケットプレフィックス:
    S3のバケットのプレフィックスを設定します。
    (入力しなくてもいい)
    バケットのリージョン:
    バケットのリージョンを選択します。
    file
    file
    さいごに
    右下の作成ボタンをクリックします。

  4. リソースデータの同期一覧が表示され、最後にいつ同期が完了したのかが表示されます。
    file

    4.3.同期情報の確認

    早速ですが、S3バケットに移動して、インベントリ情報が出力されているかを確認しましょう。
    file
    問題なく確認がとれました!

5.データベースとテーブルの作成

それでは、Glue クローラを使って、S3をクロールして情報を集めましょう。

5.1.データベースを作成

  1. サービスの検索で、Glueと入力して、Glueを選択します。左のメニューから「データベース」を選択します。ページが開いたら、「データベースの追加」をクリックします。
    file

  2. データベース名を入力し、作成ボタンをクリックします。
    file

  3. データベースの作成が完了です。
    file

    5.2.クローラを作成

  4. Glue左のメニューからテーブルを選択します。ページが開いたら、「クローラを使用してテーブルを追加」をクリックします。
    file

  5. 以下の手順通りに設定してみてください。

    • クローラに関する情報の追加
       クローラの名前を入力します。
      file
    • Crawler source type
       デフォルトのままで次に行きます。
      file
    • データストア
       インクルードパスを対象バケットを選択する。
       ほかの設定箇所はデフォルトで「次へ」ボタンクリックします。
      (glueはリージョンサービスのため、S3バケットとglueは同じリージョンであることが前提)
      file
      file
    • 別のデータストアの追加
       デフォルトのままで次に行きます。
      file
    • IAMロールの選択
       既存の IAM ロールを選択します。
      file
      既存の IAM ロールがなければ、作成することも可能です。
      file
    • このクローラのスケジュールを設定する
       デフォルトのままで次に行きます。
      file
    • クローラの出力を設定する
       5.1で作成したのデータベース名を入力し、次に行きます。
      file
    • 最後すべてのステップを確認して完了ボタンをクリックします。
       画面が遷移して作成されていることが確認できました。
      file

※テーブルを作成する前、一つの事前作業があります。
クローラを実行する時にエラーが発生しないよう不要なjsonファイルを削除:
・対象のバケットオブジェクト名をクリックして、各インベントリ情報のフォルダが表示されることを確認します。
file
・前項で表示されたバケット画面の「AWS:InstanceInformation」をクリックします。
アカウントIDが記載された以下のオブジェクト(フォルダ)が表示されます。accountid=xxxxxxxx
file
・対象オブジェクト直下の「test.json」ファイルを選択して削除します。
file
・「概要」項目にて正常に削除されたことを確認します。
file


5.3.テーブルを作成

  1. 作成したのクローラを選択して、「クローラの実行」をおします。
    file
  2. 実行中になりました。少し待ちましょう。
    file
  3. テーブルの作成が完了です。
    file

6.クエリを実行してみる

lambdaを作成する前に、まずはAhtenaにてクエリを実行してみましょう。

  1. Athenaコンソール画面を開いて、データベースを選択します。
    file

  2. 最初のクエリを実行する前に、Amazon S3 でクエリ結果の場所を設定する必要がありますので、
    「設定」⇒「管理」をクリックします。
    file

  3. クエリ結果の出力パスを指定して、保存します。
    file
    4.クエリを実行してみましょう。
     テストとして
    SELECT * FROM "ro-db-inventory"."aws_instanceinformation" limit 10;
    を入力して、「実行」ボタンをクリックします。
    file
    5.失敗です!なぜだろうか。。。(他のテーブルが問題なくクエリ実行できたことを確認済み、aws_instanceinformationテーブルのみエラーが発生している状況)
    エラーメッセージ: Table descriptor contains duplicate columns
    カラムが重複している?
    file
    テーブル「aws_instanceinformation」を確認すると、確か「resourcetype」のカラムが重複しています⇒パーティションキー列と非パーティションキー列
    file
    これはAWS仕様上の問題だと思われますので、サポートにも問合せたのですが、現時点で回避対策しか提供できません。
    回避対策をここで共有します:

  1. マネジメントコンソールの Glue データカタログの画面より Glue クローラにより作成された 対象のテーブルを選択し、詳細画面を開く。
  2. "スキーマの編集"を選択する。
  3. 列名の"resourcetype"(非パーティションキー列)を"resource_type"などの別名に変更するか、削除する。
  4. "保存"を選択する。
  5. マネジメントコンソールの Glue クローラの画面より作成したクローラを選択する。
  6. "編集"を選択する。
  7. 画面左の"出力"を選択する。
  8. "設定オプション(任意)"を開き、"クローラがデータストアのスキーマ変更を検出した場合に、AWS Glue はデータカタログでテーブルの更新をどのように取り扱いますか?"の項目で"変更を無視して、データカタログのテーブルを変更しません。"を選択する。
  9. "次へ"を選択したあと"完了"を選択し、クローラを更新する。
    また、以上の手順の 5-9 を実施してからクローラを実行すると、新しいパーティションについてもテーブルに追加できることを確認しました。
  1. 回避対策を実施しましたら、エラーが解消しました。クエリ実行できました!
    file

これで SSM から S3 に対してリソースデータの同期が行われ、さらに AWS Glue カタログに登録された状態になりました。

7.Lambda作成

定期的にインベントリ情報帳票を作成するLambda関数を作りましょう。

  1. Lambda 用の AWS Identity and Access Management (IAM) サービスロールを作成します。次に、Athena、Amazon Simple Storage Service (Amazon S3)、および Amazon CloudWatch Logs へのアクセスを許可するポリシーをアタッチします。例えば、AmazonAthenaFullAccess と CloudWatchLogsFullAccess をロールに追加できます。 AmazonAthenaFullAccess は Athena へのフルアクセスを許可し、Amazon S3 の基本的なアクセス許可を含みます。CloudWatchLogsFullAccess は CloudWatch Logs へのフルアクセスを許可します。
    (IAM Roleの設定詳細はここでは割愛)

  2. Lambda コンソールを開いて、[関数の作成] を選択します。
    file

  3. [一から作成] が選択されていることを確認し、次のオプションを設定します。
    [名前] に関数の名前を入力します。
    [ランタイム] で、Python オプションのいずれかを選択します。
    [ロール] で、[既存のロールを使用する] を選択し、ステップ 1 で作成した IAM ロールを選択します。
    file
    file

  4. [(関数を作成)] を選択します。

  5. [関数コード] セクションにコードを貼り付けます。次の例では Python 3.7 を使用します。例にある次の値を置き換えます。
    default: Athena データベース名
    *SELECTFROM default.tb: クエリ
    s3://AWSDOC-EXAMPLE-BUCKET/**: クエリ出力のための S3 バケット

import time
import boto3

query = 'SELECT * FROM default.tb'
DATABASE = 'default'
output='s3://AWSDOC-EXAMPLE-BUCKET/'

def lambda_handler(event, context):
    query = "SELECT * FROM default.tb"
    client = boto3.client('athena')
    # Execution
    response = client.start_query_execution(
        QueryString=query,
        QueryExecutionContext={
            'Database': DATABASE
        },
        ResultConfiguration={
            'OutputLocation': output,
        }
    )
    return response
    return
  1. [Deploy] を選択します。
    file

これでlambdaの設定が終わりました。

8.イベントルールを作成

Amazon EventBridge ルールを作成して、Lambda 関数をスケジュールします。

8.1.イベントルールの作成

  1. Amazon EventBridge コンソールを開きます。
    ナビゲーションペインで [ルール]を選択し、続いて [ルールを作成] を選択します。
    file

  2. ルールの名前と説明を入力します。
    [パターンを定義]で、[スケジュール]を選択します。
    file

  3. cron 式を入力します。
    file

  4. 「ターゲットタイプ」が「AWSのサービス」を選択して、[ターゲット] で、ドロップダウンリストから 「Lambda 関数」 を選択します。「関数」で、ドロップダウンリストから Lambda 関数の名前を選択します。
    file

  5. 「次へ」をクリックし、最後に「ルールの作成」を押します。画面が遷移して作成されていることが確認できました。
    file

8.2.テスト

テストとして実際にイベントルールからLambdaを呼び出します。

  1. 先作成したのイベントルールを選択して、ルールの詳細画面が表示されます。「編集」ボタンをクリックします。
    file

  2. イベントルールのCron式設定をテスト実施予定の時間に変更します。(注意点:UTC時間変換)
    file

  3. 時間になりましたら、テスト結果を確認します。帳票の出力先S3に移動します。
    帳票が出力されたことを確認できました!
    file

※テスト終了後イベントルールのスケジュール設定を戻すことを忘れないようご注意ください。

おわりに

インベントリはEC2インスタンスへ直接入ることなく、各種メタデータを収集してくれる便利機能です。ぜひ活用してみてください。
以上、SSMインベントリの活用例でした。 少しでも参考になれば幸いです。

Last modified: 2022-10-02

Author