Yappli Tech Blog

株式会社ヤプリの開発メンバーによるブログです。最新の技術情報からチーム・働き方に関するテーマまで、日々の熱い想いを持って発信していきます。

インターン生が開発環境のコスト削減してみた!

f:id:TateyamaKaito:20200909153256p:plain
AWS 構成図

はじめに

 広島大学の谷です。8月中旬から9月はじめまでの4週間、ヤプリのSREチームでインターンをさせてもらっています!この記事では私がインターン期間中に取り組んだ、開発用EC2インスタンスの自動起動/自動停止と、Slackからコマンドで開発用EC2インスタンスを起動/停止できるようにした話をしたいと思います。

取り組んだ内容

目的

  • 開発環境で使っているEC2インスタンスを夜間と休日に停止したい。
  • 停止しているインスタンスをSlackから起動させたい

使った技術

  • AWS
    • Systems Manager Automation(SSM Automation)
    • Lambda
    • API gateway
    • CloudWatch Events
  • terraform

仕組み

仕組みとしては、2つ経路があります。

1.Slackからコマンドを打つ経路

  • Slack botのSlash CommandsからAPI gatewayを叩く
  • API gatewayからLambdaを起動
  • Lambdaでslack botの引き数を見て行う処理を決める
  • SSM Automationを起動、もしくは直接EC2に対して処理を行う

2.CloudWatch Eventsで定期的に実行する経路

  • CloudWatch Eventsでcronで指定したruleから、定期的にSSM Automationを起動
  • EC2を起動/停止

はじめはAWSに慣れるためにあまりコードを書かなくて済むSSM Automationを触ってみましょうということになり、CloudWatch Events + SSM Automationが先に出来上がりました。そのあとでSlackから起動できたらいいね、という話になり、すでにあったSSM Automationを利用してLambdaからキックする構成になりました。

便利だと思ったところ

SSM Automation

EC2をただ起動、停止するだけなら公式からdocumentが提供されていて、簡単な処理はコードを書く必要がなくて便利です。 ただ、今回はリソースグループを指定するなど少し複雑なことを行おうとしたので、そうなると参考になる物が少なくて、Lambdaの方が参考例が多くて楽なのではないかとも思いました。

terraform

今回初めてまともにterraformを触ったのですが、これすごいですね!destroyの安心感がすごいし、コンソールでGUIぽちぽちするのが苦手な自分にはとても合っていました。ただ、AWSはコンソールからやるとroleなどをいい感じにやってくれるのに対し、terraformからだと明示的に指定する必要があるので、少し注意が必要です。

詰まったところ

terraformのaws provider

今回の構成は全てterraformに落とし込んだのですが、かなり時間をかけてハマってしまったところとして、今回(terraform 0.12.29, aws provider 3.3)の環境だとSSM AutomationのdocumentのARNをCloudWatchEventから指定するときに、そのまま参照でとってくるとエラーになってしまうので、ARNの document/automation-definition/ に変更する必要があります。 こちらのissue を参考に以下のようにして乗り切りました。

resource "aws_cloudwatch_event_target" "target_name" {
  ...
  arn       = replace(<SSM Automation DocumentのARN>, "document/", "automation-definition/")
  ...
}

OpsWorksがEC2が落ちたときに自動起動を行ってしまう

EC2の定時停止ができるようになりチェックで動かしていると、なぜかEC2が停止して7-8分後にEC2が勝手に起動してしまうという現象が起こりました。しばらくメンターの方と考えて、OpsWorksのAuto HealingがONになっているのが原因だとわかりました。 AWSの公式ドキュメント によると、Auto HealingはデフォルトでONになっていて、インスタンスをOpsWorksを経由せずに停止させると、自動で起動するようです。 OpsWorksのAuto HealingをOFFにすることで解決しました。

cronの曜日指定

CloudWatch Eventsのruleでcronを用いてインスタンスの起動/停止時刻を設定する時はJSTではなくUTCです。このことは 公式ドキュメント を読んで分かっていたつもりでしたが、曜日を考慮せずにやっていたため、1日ずれてしまいました。 UTC(cronにかく実際の値)が15以上23以下の場合、JSTでは翌日の0-8時となるので曜日をJSTより一日分前を指定する必要があります。

まとめ

SSM Automation, Lambda, Slack botを利用してインスタンスの自動停止と自動起動、Slackからのインスタンス起動停止を行うことができました。 これで開発にかかる費用を削減!インターン生として少しは貢献できたでしょうか?