ENECHANGE Developer Blog

ENECHANGE開発者ブログ

AWS Chatbotの現行仕様に耐えつつ、EC2インスタンスの状態をSlackで一覧表示する

VPoTの岩本 (iwamot) です。プレイングマネージャーとして、ENECHANGEの各種システムで使っているAWSの運用も担当しています。

先日、アプリチームの同僚から「複数のEC2インスタンスの状態をSlackで確認したい」と相談を受けました。くわしくは後で述べますが、停止中の開発サーバをぱっと探せるようにしたいとの要望です。

AWS Chatbotを使えば簡単だろうと軽く引き受けたものの、現状のAWS Chatbotにはいくつかの制約があり、ちょっと手こずりました。

今回の記事では、AWS Chatbotに現状どのような制約があり、どう対処したのか書いてみます。

相談の背景

まず、相談の背景を説明します。

  • 開発用インスタンスが9台ある
  • 作業が必要になったら、停止済みのインスタンスを探して起動している(実行中のインスタンスは別のエンジニアが作業している)
  • インスタンスはSlackワークフローで起動している(AWS Chatbotを利用)
  • どのインスタンスが停止済みなのか探しづらい(ワークフローの出力がSlackチャンネルで流れてしまうため)

AWS CLIでの初期実装

適切なクエリを考えるため、まずはAWS CLIで実装してみました。

$ aws ec2 describe-instances \
  --region ap-northeast-1 \
  --filters Name=tag:Name,Values=dev-enechange,dev2-enechange,dev3-enechange,dev4-enechange,dev5-enechange,dev6-enechange,dev7-enechange,dev8-enechange,dev9-enechange \
  --query "Reservations[*].Instances[].{Name: Tags[?Key=='Name'].Value | [0], State: State.Name} | sort_by(@, &Name)" \
  --output table
-------------------------------
|      DescribeInstances      |
+-----------------+-----------+
|      Name       |   State   |
+-----------------+-----------+
|  dev-enechange  |  stopped  |
|  dev2-enechange |  running  |
|  dev3-enechange |  running  |
|  dev4-enechange |  stopped  |
|  dev5-enechange |  running  |
|  dev6-enechange |  stopped  |
|  dev7-enechange |  stopped  |
|  dev8-enechange |  running  |
|  dev9-enechange |  running  |
+-----------------+-----------+

いい感じです。どのインスタンスが停止済みなのか、ぱっと分かります。

ちなみに sort_by でソートしないと、意図通りの並び順になりません。

$ aws ec2 describe-instances \
  --region ap-northeast-1 \
  --filters Name=tag:Name,Values=dev-enechange,dev2-enechange,dev3-enechange,dev4-enechange,dev5-enechange,dev6-enechange,dev7-enechange,dev8-enechange,dev9-enechange \
  --query "Reservations[*].Instances[].{Name: Tags[?Key=='Name'].Value | [0], State: State.Name}" \
  --output table
-------------------------------
|      DescribeInstances      |
+-----------------+-----------+
|      Name       |   State   |
+-----------------+-----------+
|  dev3-enechange |  running  |
|  dev2-enechange |  running  |
|  dev4-enechange |  stopped  |
|  dev5-enechange |  running  |
|  dev-enechange  |  stopped  |
|  dev6-enechange |  stopped  |
|  dev7-enechange |  stopped  |
|  dev8-enechange |  running  |
|  dev9-enechange |  running  |
+-----------------+-----------+

AWS Chatbotの制約1:sort_byに未対応

準備ができたので、sort_by ありのクエリをAWS Chatbotで実行してみました。

@aws ec2 describe-instances
  --region ap-northeast-1
  --filters Name=tag:Name,Values=dev-enechange,dev2-enechange,dev3-enechange,dev4-enechange,dev5-enechange,dev6-enechange,dev7-enechange,dev8-enechange,dev9-enechange
  --query "Reservations[*].Instances[].{Name: Tags[?Key=='Name'].Value | [0], State: State.Name} | sort_by(@, &Name)"
  --output table

が、--query パラメータがパースできないと言われてしまいます。

AWSサポートに問い合わせたところ、AWS Chatbotは sort_by に未対応なのだそうです。

並び順はいったん保留にして、sort_by を抜くことにします。

AWS Chatbotの制約2:--outputに未対応

@aws ec2 describe-instances
  --region ap-northeast-1
  --filters Name=tag:Name,Values=dev-enechange,dev2-enechange,dev3-enechange,dev4-enechange,dev5-enechange,dev6-enechange,dev7-enechange,dev8-enechange,dev9-enechange
  --query "Reservations[*].Instances[].{Name: Tags[?Key=='Name'].Value | [0], State: State.Name}"
  --output table

sort_by を抜いて実行すると、今度は --output には未対応であると警告されました。

--output table を指定しても、現状では無視され、表形式にはなりません。これは我慢するしかないでしょう。

AWS Chatbotの制約3:デフォルト5件まで

また、結果に5件のインスタンスしか表示されていない点も気になります。

この点については、--max-results 9 を指定することで、9件すべてのインスタンスが一覧表示できました。

@aws ec2 describe-instances
  --region ap-northeast-1
  --filters Name=tag:Name,Values=dev-enechange,dev2-enechange,dev3-enechange,dev4-enechange,dev5-enechange,dev6-enechange,dev7-enechange,dev8-enechange,dev9-enechange
  --max-results 9
  --query "Reservations[*].Instances[].{Name: Tags[?Key=='Name'].Value | [0], State: State.Name}"

並び順は「インスタンス名と状態を結合してsort」で我慢

最後に、棚上げしていた並び順について検討しました。

現状、AWS Chatは sort_by には未対応であるものの、sort には対応しているため、文字列または数値のリストであればソートできます。

今回はインスタンス名と状態を結合してソートすることにしました。

@aws ec2 describe-instances
  --region ap-northeast-1
  --filters Name=tag:Name,Values=dev-enechange,dev2-enechange,dev3-enechange,dev4-enechange,dev5-enechange,dev6-enechange,dev7-enechange,dev8-enechange,dev9-enechange
  --max-results 9
  --query "Reservations[*].Instances[].[join(': ', [Tags[?Key=='Name'].Value | [0], State.Name])][] | sort(@)"

見た目はともかく、これで「停止中の開発サーバをぱっと探せるようにしたい」との要望に応えられそうです。

まとめ

以上、ぼくが気づいたAWS Chatbotの現時点の制約と対処についてご紹介しました。

簡単にまとめると、下記の通りです。

制約 対処
sort_by に未対応 値を結合して sort を使う
--output に未対応 指定せずに我慢する
デフォルト5件まで --max-result N を指定する

sort--output については、AWSサポートによれば、AWS Chatbot担当部署に改善要望として伝えていただけたとのことです。今後の改善に期待しましょう。

また、大前提として、空きインスタンスを探す運用がベストだとは思えません。使いたいときに一時的な開発環境をすぐに立てられるよう、整えていきたいと考えています。

追記 (2024-04-12)

同僚の提案で絵文字を使ったら、さらに見やすくなりました。いろいろできますね。

@aws ec2 describe-instances
  --region ap-northeast-1
  --filters Name=tag:Name,Values=dev-enechange,dev2-enechange,dev3-enechange,dev4-enechange,dev5-enechange,dev6-enechange,dev7-enechange,dev8-enechange,dev9-enechange
  --max-results 9
  --query "[Reservations[*].Instances[?State.Name=='running'][].Tags[?Key=='Name'][].[join('', [Value, ': running :large_green_circle:'])][], Reservations[*].Instances[?State.Name=='stopped'][].Tags[?Key=='Name'][].[join('', [Value, ': stopped :white_circle:'])][]][] | sort(@)"