AWS の料金、気づいたら予想以上に使ってたって事ないでしょうか。
サービスもどんどん増え、サービスの料金も複雑で結局いくらかかるのか不安!
こんな場合は、AWS の料金を定期的にチェックする事をおすすめします。
今回は、 AWS 利用料金を定期的に Slack に通知する設定方法をご紹介します。
目次
設定の概要
今回設定する仕組みは以下のとおりです。
- Billing の予算機能を利用
- 予算の値をチェックし、Slack へ通知する Lambda を用意する
- CloudWatch イベントで定期的に予算チェック Lambda を実行する
今回の設定はコチラの記事を参考にさせていただきました。
@isobecky74 さんありがとうございます。
@isobecky74 さんの記事と違うのは値を Billing の予算から取ってきているところだけです。
Budgets を作成する
取得するデータの基となるBudgets( 予算 ) を作成します。
請求ダッシュボードを開きます。
メニューの「予算」をクリックし、[ 予算を作成 ] ボタンをクリックします。
予算のタイプの選択と予算の名前、予算額を決めます。
予算額は $10 にしました。個人アカウントなので 1500 円くらいで。
その他はデフォルトで。
メールでも通知したい場合は、この画面でアラート設定でいます。
現在の利用料金と、予測がすぐに表示されます。
今月はこのまま利用すると予算より 132% オーバーしそうです。
Lambda が実行する IAM Role を設定する
Lambda が Billing の予算情報を取得できるように IAM Role を設定します。
IAM 画面を開きます。
ロールを選択します。
ロールを使用するサービスの選択で Lmanbda を選びます。
ポリシーフィルターに Billing と入力して Billing ポリシーをアタッチします。
ロールの名前をつけます。
ロール ARN を Lambda をデプロイするときに使うのでメモっておいてください。
Slack の Webhook URL を取得する
Slack へメッセージを通知するための URL を取得します。以下の URL にアクセスします。
https://slack.com/services/new/incoming-webhook
投稿したいチャンネルを選択して [ 新着 Web フック インテグレーションの追加 ] をクリックします。
次の画面で Webhook URL が発行されますのでコピーしておきます。
また、この画面最下部で、通知する際のボットの名前やアイコンも変更できます。
Lambda を作る
AWS Lambda のコンソールを開いて関数を作成します。
関数名を awscost_to_slack にしました。
ランタイムは Python 3.6 にしてください。
ロールは先程作成したロールを指定しましょう。
プログラムを用意する
以下のファイルを用意してください。
awscost_to_slack% tree
├── lambda.json
├── lambda_function.py
└── requirements.txt
lambda.json
{
"name": "awscost_to_slack",
"description": "function to notify Slack of AWS cost",
"region": "ap-northeast-1",
"handler": "lambda_function.lambda_handler",
"role": "作成したロールのARN",
"timeout": 300,
"memory": 128,
"variables":
{
"slackPostURL":"取得したSlackのWebfookURL",
"slackChannel":"投稿するSlackチャンネル",
"budgetName":"作成した予算名",
"accountId":"AWSアカウントID"
}
}
lambda_function.py
#!/usr/bin/env python
# encoding: utf-8
import json
import datetime
import requests
import pytz
from dateutil import parser
import boto3
import os
import logging
logger = logging.getLogger()
logger.setLevel(logging.INFO)
# Slack の設定
SLACK_POST_URL = os.environ['slackPostURL']
SLACK_CHANNEL = os.environ['slackChannel']
# Budgets の設定
BUDGET_NAME = os.environ['budgetName']
ACCOUNTID = os.environ['accountId']
client = boto3.client('budgets')
responce = client.describe_budget(
AccountId=ACCOUNTID,
BudgetName=BUDGET_NAME
)
#予算
budget = responce['Budget']['BudgetLimit']['Amount']
#現行
cost = responce['Budget']['CalculatedSpend']['ActualSpend']['Amount']
#予測
predicted = responce['Budget']['CalculatedSpend']['ForecastedSpend']['Amount']
utcdate = responce['ResponseMetadata']['HTTPHeaders']['date']
jst_date = parser.parse(utcdate).astimezone(pytz.timezone('Asia/Tokyo'))
cost = round(float(cost))
predicted = round(float(predicted))
date = jst_date.strftime('%Y-%m-%d')
def build_message(cost, predicted):
if float(cost) >= budget:
color = "#ff0000" #red
emotion = "予算を超えてます!不要なリソースは削除しましょう!"
elif float(predicted) > budget:
color = "warning" #yellow
emotion = "予算を超えそうなので気をつけましょう。"
else:
color = "good" #green
emotion = "予算内におさまってます。"
text = " %sまでのAWSの料金は、$%sです。今月の予測料金は$%sになりそうです。" % (date, cost, predicted)
text = text + emotion
atachements = {"text":text,"color":color}
return atachements
def lambda_handler(event, context):
content = build_message(cost,predicted)
# SlackにPOSTする内容をセット
slack_message = {
'channel': SLACK_CHANNEL,
"attachments": [content],
}
# SlackにPOST
try:
req = requests.post(SLACK_POST_URL, data=json.dumps(slack_message))
logger.info("Message posted to %s", slack_message['channel'])
except requests.exceptions.RequestException as e:
logger.error("Request failed: %s", e)
requirements.txt
requests
pytz
作成したファイルを AWS にアップロードします。Lambda へコードをアップロードするには一度、 zip で圧縮して AWS コンソールか、 AWS CLI でアップロードします。
ただ、それだとめんどくさいので、 lambda-uploader でアップロードします。インストールしてない場合は、 pip install しましょう。
$ pip install lambda-uploadera
アップロード前に credential の設定をしておきましょう。私は direnv を使って作業フォルダごとに credential を設定してます。
credential の設定がただしいか、念の為 AWS CLI で先程作成した Lambda 関数の情報を取得してみましょう。
% aws lambda list-functions
FunctionName に先ほど作成した関数名が表示されてたら OK です。
では、コードをデプロイしましょう。
% lambda-uploader
λ Building Package
λ Uploading Package
λ Fin
Fin がでると成功です。
テスト実行してみる
コードのデプロイができたのでテスト実行してみます。
Lambda の画面で [ テスト ] をクリックします。
今回の Lambda に受け渡すイベント値はないのでそのまま、適当な名前をつけて [保存] をクリックします。
成功すると上記の様に表示されます。
Slack にはこの様に表示されます。
CloudWatch Events から定期実行する
Lambda を実行するタイミングを設定します。今回は CloudWatch Events から毎朝 11 時に実行するようにします。
CloudWatch Event 画面を開いて [ ルールの作成 ] をクリックします。
0 2 ? * * *
実行時間が GMT なので日本時間からマイナス 9 時間した値を設定します。今回は 11 時に実行したいので 2 時で設定します。
ターゲットに作成した Lambda を選択して、 [ 設定の詳細 ] をクリックします。
ルールの名前と説明を入力して [ ルールの作成 ] ボタンをクリックして終了です。
編集後記
スクリンショットとって編集するのめんどいのでどうにかしたい。