やりたいこと
最近、AWSのAI系サービスを検証しており、あまり詳しくないサービスを触っているうちに、知らないうちにAWS料金が大量にかかってしまうリスクを感じています。
毎日マネジメントコンソールで料金を確認するのが面倒なので、AWS利用料金を定期的にSlackに送信する仕組みを作ってみました。
①Slackアプリの作成
以下のURLにアクセスして、Slackアプリを作ります
https://api.slack.com/apps?new_app=1
manifestを設定。アプリ名を決めて、その他は全部デフォルトで大丈夫。
②SlackのIncoming Webhooksを設定
左メニューの「Incoming Webhooks」をクリックし、設定を「On」に
少し下スクロールして、「Add New Webhook to Workspace」をクリック
チャンネル検索のところに、自分自身の名前を検索し設定し、「許可」
(特定のチャンネルへ投稿する場合はチャンネル名で設定しますが、今回は自分へDMを送りたいため名前で検索します。)
すると、Webhook URLが作成されました。いったんコピーしておきます。
③Parameter Storeの設定
AWSの「System Manager」を開き、左メニューの「パラメータストア」をクリックし、「パラメータの作成」
タイプを「文字列」にし、タイプ型を「text」にし、値を先ほどコピーしたSlackのWebhookで入力し、「パラメータを作成」
④Lambdaの作成
「一から作成」を選択し、関数名を入力します。今回はPython3.13で作ります。「関数の作成」をクリック
以下のソースでデプロイします。
import base64
import urllib3
import json
import boto3
import datetime
http = urllib3.PoolManager()
def lambda_handler(event, context):
# SSMクライアントを作成
ssm_client = boto3.client('ssm')
# パラメータを取得
parameter_name = 'slack-url' # Parameter Storeに保存されているパラメータ名
response = ssm_client.get_parameter(Name=parameter_name, WithDecryption=True)
# URLを取得
slack_endpoint = response['Parameter']['Value']
print(f"Retrieved URL: {slack_endpoint}")
# Cost Explorer クライアントの作成
ce_client = boto3.client('ce')
# 今日の日付と月初の日付を取得
today = datetime.date.today()
start_of_month = today.replace(day=1)
try:
response = ce_client.get_cost_and_usage(
TimePeriod={
'Start': start_of_month.strftime('%Y-%m-%d'),
'End': today.strftime('%Y-%m-%d')
},
Granularity='MONTHLY',
Metrics=['UnblendedCost']
)
# 合計料金を取得
total_cost = response['ResultsByTime'][0]['Total']['UnblendedCost']['Amount']
currency = response['ResultsByTime'][0]['Total']['UnblendedCost']['Unit']
msg = {
"text": f"今月のAWS料金:{total_cost} {currency}",
}
encoded_msg = json.dumps(msg).encode('utf-8')
resp = http.request('POST', slack_endpoint, body=encoded_msg)
print(resp)
return {
"statusCode": 200,
"body": json.dumps("Message sent successfully!")
}
except Exception as e:
return {
"statusCode": 500,
"body": json.dumps(str(e))
}
ソースの実施内容
SSMからSlackのWebhook URLを取得
↓
Cost Exploreから今月のAWS利用料金を取得
↓
SlackのDMで自分へ送る
⑤Lambdaのレイヤー設定
しかし、Lambdaでパラメータストアからパラメータを取りたい場合、aws-sdkだけでは足りないです。レイヤーの設定が必要となります。
画面を少し下スクロールし。「レイヤー」の「レイヤーを追加」をクリック
「AWSレイヤー」を選択し、「AWS-Parameters-and-Secrets-Lambda-Extension」の最新バージョンを選択し、「追加」
⑥LambdaのIAMロール設定
Lambdaに「SSM」と「Cost Explore」へのアクセス権限を付与する必要があります。
「設定」>「アクセス権限」をクリックします。デフォルトで作成されたIAMロールはCloudWatch関連の権限しかないはずですので、ロールをクリックし編集します。
Cost Explorer Serviceに関する以下の権限を与えます。
ce:GetCostAndUsage
ce:DescribeReport
Systems Managerに関する以下の権限を与えます。
ssm:GetParameter
リソースは作ったパラメータのARNにします
⑦Lambdaのタイムアウト設定
もう一度Lambdaに戻ります。
デフォルトのタイムアウト時間が足りない恐れがありますので、「設定」>「一般設定」>「編集」
⑧Lambdaのトリガー設定
毎朝九時に、定期的にAWS料金を送ってもらいたいので、定期実行のトリガーを設定します。
「新規ルールを作成」をクリックし、ルール名を入力し、「追加」
「スケジュール式」を選択し、「cron(0 0 * * ? *)」を入力します。(UTC時間の朝九時の意味)
「Event Bridge」を確認すると、イベントスケジュール の内容がこのように表示され、以後10回のトリガー時間が表示されます。
⑨SlackのDMを待つ
明日の朝九時まで待つのは面倒くさいので、いったんトリガーのスケジュールを「cron(40 2 * * ? *)」(朝11:45)に変えてみて、結果を見ましょう!
参考サイト