この記事について
AWS CLI や GCP の gcloud コマンド、Terraform などを使っていると、
毎回オプションを調べて、長いコマンドを打つのが大変になりがちです。
この問題に対して、Jupyter Notebookと、subprocessなどのライブラリを使って、
CLI(Command Line Interface)をPythonから実行できるようにし、「試す」「学ぶ」「記録する」を効率化する方法を試してみました。
CLIの活用が大変な理由
ls
やcd
のような普通のUnix/Linuxのコマンドと違って、AWSやGCPのCLIは何かと長いです。
たとえばGCPで、Google Compute Engineで、起動中インスタンスを一覧を出す場合、
gcloud compute instances list --filter='status=RUNNING'
といった具合に、すぐに長くなっていってしまいます。ちょっとした調べ物程度でも、すぐにこの程度の複雑さになっていきます(場合によってはもっと)。しかも、これがテキパキ使いこなせるかどうかで、開発効率が大きく変わってきます。
ただ単に慣れてないだけなのに、「仕事が遅い」みたいな評価を受けかねないのは、悩ましいところです。ともあれ、CLIのコマンド体系はAWSとGCPでは全然ちがうので、別のクラウドインフラの活用スキルが高くても、慣れていないと苦労します。
そこでJupyter × subprocessを使ってみる
Pythonの subprocess モジュールを使うことで、Jupyter Notebook上からCLIコマンドを実行できるようになります。
これにより、
- CLIコマンドをPythonコードとして残せる
- 実行結果やエラー出力もNotebookに明示的に記録される
- Markdownと組み合わせて、調査メモ+実験ログが一体化できる
つまり、CLIを試しながら実行 → コードと実行結果の記録 → 記録の振り返りと学習 といったプロセスが噛み合い、試行錯誤のプロセスをそのまま「学び」として蓄積させやすくなります。
AWS CLIやgcloud CLIなどのコマンドをリスト形式で指定
たとえば、あらかじめこんな関数を用意しておきます。
import subprocess
def command(cmd):
result = subprocess.run(
cmd,
cwd=".", # 実行するディレクトリを指定
stdout=subprocess.PIPE, # 標準出力をキャプチャ
stderr=subprocess.PIPE, # 標準エラー出力もキャプチャ
text=True) # 出力を文字列として取得
cmd_str = " ".join(cmd) # 半角スペース区切りで、コピペ用コマンド作成
print(cmd_str)
if result.stderr:
print("※STD_ERROR:")
print(f"```\n{result.stderr}\n```") #異常終了時の出力
print(f"```\n{result.stdout}\n```") #正常終了時の出力
この関数を使って、Jupyter Notebook経由でコマンドを実行する場合は、こんな感じ。
# GCP上のプロジェクトの一覧を出力する場合
command(["gcloud","projects","list"]) #gcloud projects list
それぞれセルを分けておくと、実行コマンドと、その結果がすべて一枚のノートブックに収まります。
オプションを少しずつ変えて、比較しながら実験することもできます。これなら、記録を残すことも、他人に共有することも楽になります。
筆者のマシンで、Jupyter Notebookで試してみた際の作業イメージはこんな感じ。
- 気がついたこと、備忘録を、マークダウンの記載欄に書き留める
- 繰り返し使いそうなコマンド・スクリプトは、セルを分けて並べて、残す
- 実行結果を羅列していくことで、「どのコマンドで、どんな結果が返ってきたのか」を時系列で記録していく
といった使い方も、これなら自然にできそうです。
いろいろなツールで試してみる(AWS/GCP/Terraform)
AWSもTerraformも同様にコマンド実行できます。
AWSの場合
# EC2インスタンスの一覧表示
command(["aws","ec2","describe-instances"])
Terraformの場合
# Terraformの変更点を表示
command(["terraform","plan"])
一個のセルにまとめて2つ以上のコマンドをまとめて記述・実行することもできます。
その場合は、実行結果も複数まとめて表示されます。
画像は、AWSとTerraformのコマンドを併記してみたところ。ただまとめて羅列しただけではあるものの、複数クラウドを跨いだ手順の整理がしやすくなりそうです。Terraform/AWS/GCPをはじめとするクラウドインフラの内包む、インフラをコード化する(いわゆるIaC) との親和性も高いのではないでしょうか。
注意点:本格的なシステム化・自動化への展開は慎重に
便利である反面、注意点もあります。
すぐに考えたくなるのは、
- コマンドを順番に実行していくような手順書の内容全部ここに書いたら、自動化システム完了するんじゃない?
- 自動化システム完成させて、ノートブックをみんなに配布したら、誰でも同じオペレーションが実施・再現可能になるのでは?
みたいなアイデアだと思います。しかし、その自動化システムの運用・保守のフェーズまで考えると、そのまま実践するのは慎重になる必要があると思われます。
コマンドの実行環境が見た目よりもややこしい
注意を要するのは、Pythonのsubprocessモジュール、Jupyter Notebookなどを経由する過程で、実行環境が何層にも仮想化されている点です。つまり、仕組みが見た目以上に複雑で、実行時のシェルやPATHの相違により、同じコマンドでも挙動が変わる場合があるのです。したがって、直接ターミナルを起動してコマンドを実行する場合と、結果がいつも一致するとは限りません。
たとえば、自動化ツールの一部として本格的に導入された際に想定されるのは、ターミナルからの実行は成功したのに、自動化ツールではエラーが出るといったトラブルが生じることです。とくに、決まった時間内にやり終える必要のあるオペレーションでは、「安易に自動化したせいで、時間の使い方に計画性がなくなり、トラブル対応に疲弊する」といった「自動化の副作用」には注意したいところです。
本格的な自動化に進む際には、エラー原因調査・デバッグの手法は予め計画しておいたほうがよさそうです(CLIのバージョンの揃え方・環境変数の揃え方など)。
もしくは、Dockerなどを用いて、あらかじめコマンドの実行環境も徹底的に統一させることで、オペレーションの安全性を高めていくのも良さそうです。
現実的な妥協点は、調査・参考・学習などの試験的な活用かも
しかし、それでもCLI操作のハードルを下げ、学習・比較・記録を一体化できるJupyter Notebookは、やはり非常に魅力があると思います。大事なのは、その便利さにどこまで任せるかの線引きかもしれません。
- ちょっとした確認、学習目的での使用にとどめ、結果の確認は参考程度にとどめておく
- リソースの設定変更、新規作成、削除といった、重大なオペレーションでは使用しない
- 自分の手元で使う「業務メモ」程度にとどめて、本格的なツール配布はしない
といった活用が無難かもしれません。
まとめ
Jupyter Notebookを使ってCLIコマンドを扱うことで、インフラ操作の試行錯誤や学習のハードルはぐっと下がります。
特に、MarkdownとPythonコードが共存できるNotebookは、「調べる」「試す」「記録する」が一体化できる点で、CLIと親和性が高いと思います。
CLI操作が日常の人にとって、「Notebookで記録しながら触る」という選択肢が、新しいスタイルとして少しでも広がれば嬉しいです。
筆者からひと言
- 筆者はAzureを使ったことがないので、詳しい方がもしいたら、Azureでの活用事例を教えてください
- Jupyter Notebook、subprocess等の環境の仮想化の仕組み、揃え方に詳しい方がいたら教えてください
参考リンク