Java
AWS
AWS_SDK
SORACOM
あのボタン

SORACOM LTE-M ButtonでChaosMonkey

はじめに

タイトルそのままですが、SORACOM LTE-M Buttonをクリックすることで、ChaosMonkey的にランダムにEC2インスタンスを落とすようにしてみました。
一応障害テストにも使えますが、「押すなよ押すなよ」的な使い方に最適かと思われます。

実装

 クリック時の動作

シングルクリックで1インスタンス、ダブルクリックで2インスタンス、ロングクリックで3インスタンスがterminateされます。
実装によっては、ロングクリックで全消し、というバルスボタンを作ることも可能です。

ボタンのセットアップ

ボタンを1Clickサービスに登録してアクションを紐づけるところまでは、こちらのエントリに詳しく書かれています。
https://dev.classmethod.jp/soracom/setup-soracom-ltem-button-by-android/

こちらのエントリでは、SMSを送信するアクションを選択していますが、今回は以下で実装するLambdaを選択します。

AWS Lambdaの実装

Javaで書いてありますが、このような実装になります。

public class ChaosMonkeyButton implements RequestHandler<ClickEvent, String> {

  AmazonEC2 ec2;

  public ChaosMonkeyButton() {
    ec2 = AmazonEC2ClientBuilder.standard().withRegion(Regions.US_EAST_2).build();
  }

  @Override
  public String handleRequest(ClickEvent input, Context context) {

    DescribeInstancesResult describeInstances = ec2.describeInstances();

    //terminateするインスタンス数をクリックタイプによって変える
    int terminateNum = input.deviceEvent.buttonClicked.clickType.ordinal() + 1;
    context.getLogger().log("terminateNum:" + terminateNum);

    //インスタンスリストからランダムにterminate対象を取り出す
    List<Instance> terminateList = describeInstances.getReservations().stream()
        .flatMap(res -> res.getInstances().stream()).filter(this::isRunning)
        .collect(Collectors.collectingAndThen(Collectors.toList(), collected -> {
          Collections.shuffle(collected);
          return collected.stream();
        })).limit(terminateNum).collect(Collectors.toList());

    if (terminateList.isEmpty() == false) {
      //インスタンスをterminate
      List<String> idList = terminateList.stream().map(t -> t.getInstanceId()).collect(Collectors.toList());
      idList.stream().forEach(i -> {
        context.getLogger().log("terminate " + i);
        ec2.terminateInstances(new TerminateInstancesRequest().withInstanceIds(i));
      });
    } else {
      context.getLogger().log("There are no running instances");
    }

    return "OK";
  }

  private boolean isRunning(Instance instance) {
    return InstanceStateName.Running.toString().equals(instance.getState().getName());
  }
}

ソースコードやビルドスクリプトは以下に置いておきます。リクエストは1Clickボタンで共通なので、Javaの方であれば簡単にカスタマイズできると思います。
https://github.com/c9katayama/soracom-lte-m-button-lambda

動作確認

先輩、システム構築終わりました!!
スクリーンショット 2018-11-03 9.56.14.png

おー、よくできたね。どれどれ ポチー(ロングクリック)
15411830590660.jpg

ギャーーー!
スクリーンショット 2018-11-03 9.56.48.png

おわりに

今回は、EC2を落とすという使い方でしたが、SORACOM LTE-M ButtonはLambdaを直接叩けるので、適切にLambdaにロールを割り当てることで、自分のAWS環境のリソースをボタンクリックで変化させることができます。
例えばセキュリティグループを一瞬開けるとか、IAMに権限を一時的に付与するといった、承認を得て作業するようなシチュエーションの場合に、ハンコを押す感覚で上司が操作できるのは面白いかなと思いました。
またボタンの場合、認証はハードウェアに内蔵されたeSIMに任せることができます。このため、例えばボタンを押す人を変える場合も、AWSのクレデンシャルやその他の認証情報を人に渡す必要がなく、複数人で利用するようなユースケースでは便利に使えるケースもありそうです。