Steampipe で EC2 の情報を一覧化してみた

Steampipe で select * from cloud; した。
2022.07.22

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

はじめに

本記事のテーマは AWS ブログで紹介されていた Steampipe です。

Steampipe is an open source tool for querying cloud APIs in a universal way and reasoning about the data in SQL.

(機械翻訳) Steampipeは、クラウドAPIを普遍的な方法でクエリし、SQLのデータについて推論するためのオープンソースツールです。

Explore, connect and join data.
Painlessly join live cloud configuration data with internal or external data sets to create new insights.

(機械翻訳) データを探索、接続、結合します。ライブクラウド構成データを内部または外部のデータセットと痛みを伴わずに結合して、新しい洞察を作成します。

対象読者

  • ふだんよく AWS CLI を使って describe してるよって方
  • ちょうど取引先や上司から AWS の設定をリストでちょうだいって無茶ぶりされた方
  • SQL したい方

実行例

例えば、自分が使っている EC2 について「AZ 別」「インスタンスタイプ別」に数を出したいとします。

AWS CLI の場合だと、aws ec2 describe-instances の結果から jq で抽出し、OSコマンドやシートで集計する方法になるかと思います。

Steampipe の場合だと、以下の SQL で同様の結果を得られます。

> select
  placement_availability_zone as az,
  instance_type,
  count(*)
from
  aws_ec2_instance
group by
  placement_availability_zone,
  instance_type;
  
+-----------------+---------------+-------+
| az              | instance_type | count |
+-----------------+---------------+-------+
| ap-northeast-1a | t2.micro      | 2     |
| ap-northeast-1c | t2.micro      | 1     |
+-----------------+---------------+-------+

複数リージョン・複数アカウントの情報が欲しい場合も、その部分の設定は外出しになっているため、SQL は1回で済みます。認証情報の設定方法は以下のページにあります。AWS CLI で環境変数やプロファイルの概念に馴染みのある方には、違和感ない仕組みになっているかと思います。

セットアップ

AWS の IAM ユーザーの準備

プログラムアクセス可、ReadOnlyAccess 権限ありの IAM ユーザーを作成し、クレデンシャルをダウンロードしておきます。

インストール

前述の AWS ブログ の最後にステップ紹介とリンクがあります。とても簡単です。

インストール例(Linux)

$ sudo /bin/sh -c "$(curl -fsSL https://raw.githubusercontent.com/turbot/steampipe/main/install.sh)"
$ steampipe plugin install steampipe
$ steampipe plugin install aws

クレデンシャル設定例

~/.steampipe/config/aws.spc

regions = ["ap-northeast-1","us-east-1"]

環境変数

$ export AWS_ACCESS_KEY_ID=XXXXX
$ export AWS_SECRET_ACCESS_KEY=XXXXX

あとはクエリを実行するだけです。参照可能なテーブルの種類はこちらです。

クエリ実行例

$ steampipe query
Welcome to Steampipe v0.15.0
For more information, type .help
> select count(*) from aws_iam_user
+-------+
| count |
+-------+
| 1     |
+-------+
>

Ctrl + D でプロンプト終了します。

1:nの情報を一覧化するには?

セキュリティグループや EBS ボリュームなど、1つのインスタンスに複数アタッチされているリソースを一覧化する場合は cross join を駆使するといけます。

セキュリティグループの例

> select
  instance_id,
  sg ->> 'GroupName' as security_group
from
  aws_ec2_instance
  cross join jsonb_array_elements(security_groups) as sg;

+--------------+-------------------+
| instance_id  | security_group    |
+--------------+-------------------+
| i-xxxxx      | launch-wizard-1   |
| i-xxxxx      | launch-wizard-2   |
+--------------+-------------------+

EBS ボリュームの例

> select
  instance_id,
  device ->> 'DeviceName' as DeviceName,
  device -> 'Ebs' ->> 'VolumeId' as VolumeId,
  device -> 'Ebs' ->> 'AttachTime' as AttachTime,
  device -> 'Ebs' ->> 'DeleteOnTermination' as DeleteOnTermination
from
  aws_ec2_instance
  cross join jsonb_array_elements(block_device_mappings) as device;

+--------------+------------+------------+----------------------+---------------------+
| instance_id  | devicename | volumeid   | attachtime           | deleteontermination |
+--------------+------------+------------+----------------------+---------------------+
| i-xxxxx      | /dev/xvda  | vol-xxxxx  | 2022-07-13T13:02:33Z | true                |
| i-xxxxx      | /dev/sdf   | vol-xxxxx  | 2022-07-14T02:51:44Z | false               |
+--------------+------------+------------+----------------------+---------------------+

ENI の例

本当は IP アドレスなども一覧に並べたかったのですが、力及ばず。親切な方教えてください。

> select
  instance_id,
  ni ->> 'NetworkInterfaceId' as eni,
  jsonb_pretty(cast(ni ->> 'Groups' as jsonb)) as security_group,
  jsonb_pretty(cast(ni ->> 'PrivateIpAddresses' as jsonb)) as private_ip
from
  aws_ec2_instance
  cross join jsonb_array_elements(network_interfaces) as ni;

+-------------+------------+-------------------------------------------+-------------------------------------------------------------------------------+
| instance_id | eni        | security_group                            | private_ip                                                                    |
+-------------+------------+-------------------------------------------+-------------------------------------------------------------------------------+
| i-xxxxx     | eni-11111  | [                                         | [                                                                             |
|             |            |     {                                     |     {                                                                         |
|             |            |         "GroupId": "sg-xxxxx",            |         "Primary": true,                                                      |
|             |            |         "GroupName": "launch-wizard-1"    |         "Association": null,                                                  |
|             |            |     },                                    |         "PrivateDnsName": "ip-172-31-39-164.ap-northeast-1.compute.internal", |
|             |            |     {                                     |         "PrivateIpAddress": "172.31.39.164"                                   |
|             |            |         "GroupId": "sg-yyyyy",            |     }                                                                         |
|             |            |         "GroupName": "launch-wizard-2"    | ]                                                                             |
|             |            |     }                                     |                                                                               |
|             |            | ]                                         |                                                                               |
| i-xxxxx     | eni-22222  | [                                         | [                                                                             |
|             |            |     {                                     |     {                                                                         |
|             |            |         "GroupId": "sg-zzzzz",            |         "Primary": true,                                                      |
|             |            |         "GroupName": "launch-wizard-3"    |         "Association": null,                                                  |
|             |            |     }                                     |         "PrivateDnsName": "ip-172-31-40-113.ap-northeast-1.compute.internal", |
|             |            | ]                                         |         "PrivateIpAddress": "172.31.40.113"                                   |
|             |            |                                           |     }                                                                         |
|             |            |                                           | ]                                                                             |
+-------------+------------+-------------------------------------------+-------------------------------------------------------------------------------+

おわりに

最初、ゲームの何かと間違えて飛びついてアテが外れたのですが、調べていくとデザインがクールで実に私好みでした。クラウド全体をデータベースと捉えて探索するという発想も天才的ですが、ツールの発展や応用を見据えた細やかな工夫が随所に感じられ、構成がよく練られたツールだと思いました。

ユーザー体験も良質で、試して結果を得るまでものの数分といったところです。
ドキュメントとサンプルもわかりやすいので、変につまずくところもなくストレスなしです。

ただ Steampipe は言ってしまえば情報の参照を楽にしてくれるところまでであり、何か問題を直接解決するといったものではないため、どう活用するかは自分のアイディア次第かと思います。AWS 以外にも Google Cloud Platform などさまざまなプラグインがあるので、組み合わせて何ができるか考えるのも面白そうです。

今後もテーブルやプラグインは随時追加されていくと思いますが、そこに欲しいものがまだない場合は、自分自身でテーブルのカスタマイズやプラグイン開発することもできるようです。

また、対話式ではなくコマンドラインでの実行や、 Docker での実行、サービス起動させて PostgreSQL クライアントから接続、などの応用も可能となっています。

AWS CLI 使ってこねこねする機会がある方は、ご興味あればぜひ1度 Steampipe を試してみてはいかがでしょうか。