AWS CLIを踏み台EC2上で実行して接続先サーバを選べるようにScriptを組んでみた
こんにちは。manebi開発クラ部の中の人、よく見かけるマネージャのJでござる。
以前、Session Managerを使って接続したEC2サーバから別のEC2サーバへ接続するためのScriptを公開してみた。
ただ、しかし!事前にサーバリストをconfigファイルとして用意しても、EC2サーバの台数は日々変わるもので、それをメンテナンスするのが難儀になってきた。
そりゃそうだろう!って声が聞こえてくる。早く気付けばよかった。
そんで、踏み台EC2からの接続先であるEC2インスタンスを自動で取得できないか。という思いになったのだった。
EC2でのAWS CLI実行
恥ずかしいことに、EC2でAWSのCLIを実行できることがわかっていなかった。Google先生に聞いたら教えてくれた。と言うか、先人の人たちが記事を残してくれていたのだった。
簡単に言うと、EC2にAWS CLIをインストールして、aws configureで環境設定をすればいいだけの話だった。が、もし、問題が出てきた場合は、以下の公式サイトを参照していただきたい。
EC2でAWS CLIを用いてインスタンスリストを出力
いつもの「describe-instances」を使えば良いのだけど、見やすく、使いやすいように必要な項目を吐き出すには「query」を使うらしい。
aws ec2 describe-instances --filter "Name=instance-state-name,Values=running" --output=table --query 'sort_by(Reservations[].Instances[].{InstanceId: InstanceId, GlobalIP: join(`, `, NetworkInterfaces[].Association.PublicIp), State: State.Name,Name: Tags[?Key==`Name`].Value|[0]}, &Name)'
こちらが筆者がたどり着いた一つの解である。ネット上でも様々な情報があるので、検索して頂きたいが、今回重点をおいて直したのはこちら。
表形式で吐き出す
--output=table稼動中のインスタンスだけを対象とする
--filter "Name=instance-state-name,Values=running"名前で並び替えする
sort_by(~~~~, &Name)
テキストだと、のちに、サーバリストを表示して、メンバに接続先サーバを選んでもらう際、不都合が生じやすそうなので、わかりやすいテーブル構造にし、稼動していないインスタンスを省いて、名前で並び替える。
このあたりがポイントだと思う。
----------------------------------------------------------------------------------
| DescribeInstances |
+----------------+-----------------------+----------------------------+----------+
| GlobalIP | InstanceId | Name | State |
+----------------+-----------------------+----------------------------+----------+
| xxx.xx.xxx.xxx| i-xxxxyy1yyzzz | ec2.instance.01 | running |
| xxx.xx.xxx.xxx| i-xxxxy5yyyzzz | ec2.instance.02 | running |
| xxx.xx.xxx.xxx| i-x2xxxyyyyzzz | ec2.instance.03 | running |
~~~~ 中略 ~~~~
| xxx.xx.xxx.xxx| i-xxxxyyy3yzzz | ec2.instance.50 | running |
| xxx.xx.xxx.xxx| i-xxx4xyyyyzzz | ec2.instance.51 | running |
+----------------+-----------------------+----------------------------+----------+
上記が実行結果で、接続先となるGlobalIPとインスタンスID、インスタンス名、ステータスがわかる。
そして、想定通り、インスタンス名でソートされているので、まだわかりやすいのだ。
AWS CLIの実行結果からIPアドレスだけを抽出
上記の結果は人にはわかりやすいので助かるのだけど、いざShellの中で扱おうとすると、区切り位置がいまいちで使いにくい。
そこで、awkコマンドの登場だ。
まずはユーザが選んだサーバの行だけを抽出する。
echo -n "Please select a SERVER NAME. ( Copy and paste ) :::: "
read SERVER_NAME
grep ${SERVER_NAME} ${SERVER_LIST}
ユーザが入力したサーバ名をSERVER_NAMEに入れ、それでgrepをかけるだけだ。これを実行すると行まではなんとかなる。
| xxx.xx.xxx.xxx| i-xxxxyyy3yzzz | ec2.instance.50 | running |
それから、区切り文字を選択して、区切っていく。
grep ${SERVER_NAME} ${SERVER_LIST} | awk -F "|" '{print $2}'
これを実行すると以下のようにIPアドレスだけを取得できる。
xxx.xx.xxx.xxx
↑↑ 空白が残っている!
これで、すっきりはしたものの、テーブル形式で出していた名残として、先頭に空白が残っていしまっている。
これも取り除いていく。
grep ${SERVER_NAME} ${SERVER_LIST} | awk -F "|" '{print $2}' | awk '{sub(/^[ \t]+/, "")}1'`
パイプにパイプを重ねるので気持ち悪さもあるが、これによって以下のように先頭の空白がなくなって、sshコマンドで使えるような文字列になった。
xxx.xx.xxx.xxx
↑↑ 空白がない!
これでやっとsshで使いやすくなった。簡単な話だけど、文字列の扱いは案外面倒くさいのでメモ程度に共有しておく。
これでEC2インスタンスの増減を気にすることなく、都度、AWS CLIを用いた最新のインスタンスリストを使ったsshができるようになった。
同じような面倒くささに悩まれているどなたかの役に立つことを願う。