
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(@)"
