SORACOM LTE-M Button powered by AWS(通称 #あのボタン)を使って EC2 のインスタンス代を節約した話

この記事は SORACOM Advent Calendar 2019 ふたつめ の 12 月 3日分です。

はじまり

最近、開発用の PC の調子が悪かったのもあって EC2 インスタンス上にいろいろな開発環境を構築してみています。 そうするとどの PC を使っても同じ開発環境で作業を継続できると思ったからです。

近頃は VS Code のリモート接続拡張を使うことで、あたかもローカルにファイルがあるかのようにリモートホスト上のファイルが編集でき、統合ターミナルを使って自然にリモートホスト上でコマンドを実行できますので、リモート接続していることを忘れてしまうときがあるほどなので、これさえあればだいぶ行けるだろうと思ったのです。

最初はお試しと思って t3.micro インスタンスで始めたものの、自分の書いたプログラムを Fuzzing したいと思ってぶっ通しでプログラムを実行しようとしたら CPU クレジット不足になってしまったので c5.large にインスタンスタイプを変更し、Fuzzing が終わって今度はいろいろテストを実行していたらメモリ不足になってしまったので r5.large に更に変更し、という感じで今に至っています。

ソラコムでは社員の福利厚生(?)として AWS のサービス使い放題というのがあるのですが、貧乏性の私はさすがに r5.large インスタンスを起動しっぱなしはもったいないなぁと感じてしまい、弊社の リーダーシップステートメント にも Avoid Muda とあるように少しでもコストを削減しようと思い、開発業務をしていない間はインスタンスをちゃんと停止しようと考えました。

r5.large インスタンスは Tokyo リージョンでは $0.152/hour (2019年12月現在)ですので、使っていない時間が1日の半分(12時間)あったとして1ヶ月(30日)で $0.152 * 12 * 30 = $54.72 のムダが生じていることになります。(実際には休日などもありますし、1日12時間も働くことはまれですし、もっとムダが生じてしまうことになるはずです。)

しかしながら生来のめんどくさがりである私は、インスタンスを起動したり停止したりするために AWS コンソールにログインして EC2 のページから自分のインスタンスを検索して起動したり停止したりするのは非常に面倒であると思いました。 aws コマンドを使ってコマンドラインで実行するともう少し手間は少ないかもしれませんが。

というわけで、ここはテクノロジーの力で解決しよう!(大げさ)と思って取り出したのがこちらの商品です。

soracom.jp

そう、「AWS ボタン」とか「#あのボタン」と呼ばれているものです。

設計(というほどのものでもない、ただの思いつき)

目論見はこうです。

  1. 仕事を始めるタイミングでボタンを押す。インスタンスが起動する。
  2. 仕事を終えるタイミングでボタンを押す。インスタンスが停止する。

これだけです。 究極にシンプルです。

AWS ボタンは、1回押し(シングルクリック)、2回押し(ダブルクリック)、長押し(ロングクリック)の3タイプの押し方ができますので、これをそれぞれ以下のような機能に割り当てることにしました。

  • シングルクリック:現在のインスタンスの状況(稼働中か、停止中かなど)を Slack のチャンネルに報告
  • ダブルクリック:インスタンスが停止していたら起動。Slack のチャンネルに報告。
  • ロングクリック:インスタンスが起動していたら停止。Slack のチャンネルに報告。

実装

ではここから実装に入っていきます。

AWS IoT 1-Click の設定

まずは AWS IoT 1-Click で AWS ボタンを Claim(登録)して有効化します。 手順などはこちらを参考にしてください。

dev.soracom.io

Lambda で起動される関数を先に作成

今回は Go で Lambda 関数を作成しました。 Gist にコードを上げておきました。これをビルドして ZIP してアップロードします。

https://gist.github.com/bearmini/99e99ead08ed0e8aff39c6379f5aeeae

AWS IoT 1-Click に戻り、プロジェクトを作成

AWS IoT 1-Click で Project と Device template を作成します。

f:id:bearmini:20191203124552p:plain
このような設定をしました

起動する Lambda は先程作ったものを指定します。

プレイスメントの設定

そのボタンで起動/停止したいインスタンスインスタンス ID、リージョン、通知先の Slack の Incoming Webhook URL をプレイスメントで指定します。

実行!

ボタンを押してみます。

まずは恐る恐るシングルクリック。

ボタンの LED がオレンジ色に点滅して10秒ほど待つと緑色に光ります。 すると程なくして Slack に通知がくるはずです。

f:id:bearmini:20191203125817p:plain
シングルクリックした際の通知。現在の状態(running)が通知された。

インスタンスを停止する際は長押しします。

f:id:bearmini:20191203125931p:plain
インスタンス停止時の通知

インスタンスを起動する際はダブルクリックです。

f:id:bearmini:20191203130041p:plain
インスタンス起動時の通知

インスタンスを停止すると、瞬間的に VS Code は画面が暗くなって再接続を試み始めます。

インスタンスを起動すると VS Code は再接続に成功します。画面を一度リロードする必要がありますが、それ以降は何事もなかったかのように作業を継続できます。(開いていたターミナルなどは閉じてしまいますが、screen コマンドなどでセッションを維持するようにすればそれも問題なく継続できるでしょう)

おわりに

というわけで、ちょっとの投資とちょっとの工夫、そしてちょっとの実装でこんなに簡単に節約ができました。

みなさんも、何かアイディアを思いついたら、Just Do It! してみましょう。