リソースの消し忘れを簡単にチェックしてコストを節約する方法を教えて下さい(CLI版)

2022.10.17

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

困っていた内容

検証したリソースを消し忘れてしまい思わぬコストがかかってしまいました。簡単に毎日チェックする方法を教えて下さい。

どう対応すればいいの?

自動でチェックしてSlackに通知してもらいましょう!そこで AWS CLI(以下 CLI)で毎日のコストと EC2 数を調べるスクリプトを作ってみました。

  • 毎日の利用コスト
  • EC2 インスタンス数

上記を CLI / シェルで作って cron で定期的に Slack に通知します。

やってみた

使用した CLI jq のバージョンは以下のとおりです。今回は、結果を見やすくするために jq がインストールされていることを前提としています。

実行環境

$ aws --version
aws-cli/1.18.107 Python/2.7.18 Linux/4.14.287-148.504.amzn1.x86_64 botocore/1.15.44

$ jq --version
jq-1.5

必要な IAM の権限

アクセスキー・シークレットアクセスキーを使用するか、実行する EC2 の IAM ロールに必要な権限が付与していることが必要です。 今回は ReadOnlyAccess ポリシーを持った IAM ロールが実行環境の EC2 に設定されていることを前提としています。 つまり、EC2 の IAM ロールがついているのでアクセスキー・シークレットアクセスキーがなくても CLI を実行できる状態です。

参考:プログラムではアクセスキー/シークレットキーを使わずにRoleを利用する

コスト

START=$(date +"%Y-%m-%d" -d"1 day ago")
END=$(date +"%Y-%m-%d")
cost=`aws ce get-cost-and-usage --time-period Start=${START},End=${END} --granularity DAILY --metrics "BlendedCost" | jq -r '.[][] | .Total.BlendedCost.Amount'`
cost='コスト(USD):'$cost

前日から当日のコストを取得します。 まず、START と END という変数に今日と昨日の日付を入れています。このスクリプトが 10/9 に実行された場合は START は 10/8 で END は 10/9 になります。 そして、AWS CLI の get-cost-and-usage を実行して出力結果がコストだけになるように jq で整形しています。 結果は cost という変数に入れて後で Slack に送るメッセージの一部として使用します。

台数

ec2Ary=(`aws ec2 describe-instance-status | jq -r '.[][] | .InstanceId'`)
res1='EC2: '${#ec2Ary[@]}'台起動中です!'

AWS CLI の describe-instance-status でインスタンスIDをとって配列に入れます。 この配列の長さがインスタンス数になります。前述のコストと同様に変数に入れて後で Slack に送るメッセージの一部として使用します。 同じ考え方で例えば RDS のインスタンス数なども簡単にとれます。

Slack 送信

LF=$'\n'
msg=$cost$LF$LF$res1
curl -X POST -F channel=【CHANNEL】-F text="$msg" https://slack.com/api/chat.postMessage -H "Authorization: Bearer 【TOKEN】"

上記を取得した情報に書き換えて実行できます。 改行キーを LF という変数に入れて msg という変数にコストと台数で取得した結果をメッセージ用に加工してセットします。 今回は curl でポストしていますが、詳細は下記のブログが参考になります。

Slackチャンネルにメッセージを投稿できるSlackAppを作成する

cron 設定

例えば、上記のスクリプトを resourceChecker.sh として保存して毎日17時に実行する場合は crontab -e で下記のような設定になるかと思います。

00 17 * * * /home/bin/resourceChecker.sh

実行結果

Slack はこんな感じになります

全コード

#!/bin/bash

# コスト
START=$(date +"%Y-%m-%d" -d"1 day ago")
END=$(date +"%Y-%m-%d")
cost=`aws ce get-cost-and-usage --time-period Start=${START},End=${END} --granularity DAILY --metrics "BlendedCost" | jq -r '.[][] | .Total.BlendedCost.Amount'`
cost='コスト(USD):'$cost

# EC2台数
ec2Ary=(`aws ec2 describe-instance-status | jq -r '.[][] | .InstanceState.Name +":"+ .InstanceId'`)
res2='EC2: '${#ec2Ary[@]}'台起動中です!'

# 送信メッセージ
LF=$'\n'
msg=$cost$LF$LF$res2

# Slack 送信
curl -X POST -F channel=【CHANNEL】-F text="$msg" https://slack.com/api/chat.postMessage -H "Authorization: Bearer 【TOKEN】"

費用

コストエクスプローラは、1 回の API 呼出に対して、0.01 USD の料金が発生します。 毎日通知すると月額で約45円(1 USD =150 円換算)の料金が発生します。

Cost Explorerによるコストの分析 | AWS

関連情報

AWS Budgets で費用が設定額を超えた場合にアラート通知できますのでこちらの設定も必須ですね。

AWS Budgets で 1-Click テンプレートが使えるようになりました

最後に

クラウドのいいところは低コストで簡単に検証できるところ。でも、検証後にリソースを消し忘れて思わぬ出費になってしまうことも。 毎回確認すれば良いのですが意外と面倒でついつい怠けがち。毎日コストと消し忘れたリソースがないか簡単に確認したかったので作ってみました。
次回は同じ機能を Lambda (Node.js) で作成予定です。
このブログがどなたかのお役にたてば幸いです。