1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

LambdaでAWS利用料金をSlackへDM送信する方法

Last updated at Posted at 2025-01-25

やりたいこと

最近、AWSのAI系サービスを検証しており、あまり詳しくないサービスを触っているうちに、知らないうちにAWS料金が大量にかかってしまうリスクを感じています。

毎日マネジメントコンソールで料金を確認するのが面倒なので、AWS利用料金を定期的にSlackに送信する仕組みを作ってみました。

こんなことをやりたいです↓
image.png

①Slackアプリの作成

以下のURLにアクセスして、Slackアプリを作ります
https://api.slack.com/apps?new_app=1

「From a manifest」で作成
image.png

ワークスペースを選択
image.png

manifestを設定。アプリ名を決めて、その他は全部デフォルトで大丈夫。
image.png

設定内容をレビューして、「Create」
image.png

②SlackのIncoming Webhooksを設定

アプリ作成できたら、このような画面に遷移されます。
image.png

左メニューの「Incoming Webhooks」をクリックし、設定を「On」に
image.png

少し下スクロールして、「Add New Webhook to Workspace」をクリック
image.png

チャンネル検索のところに、自分自身の名前を検索し設定し、「許可」
(特定のチャンネルへ投稿する場合はチャンネル名で設定しますが、今回は自分へDMを送りたいため名前で検索します。)
image.png

すると、Webhook URLが作成されました。いったんコピーしておきます。
image.png

③Parameter Storeの設定

AWSの「System Manager」を開き、左メニューの「パラメータストア」をクリックし、「パラメータの作成」
image.png

パラメータ名を入力し、「標準」利用枠にします。
image.png

タイプを「文字列」にし、タイプ型を「text」にし、値を先ほどコピーしたSlackのWebhookで入力し、「パラメータを作成」
image.png

作成に成功しました!
image.png

④Lambdaの作成

AWSのLambdaを開き、「関数を作成」
image.png

「一から作成」を選択し、関数名を入力します。今回はPython3.13で作ります。「関数の作成」をクリック
image.png

作成完了後、この画面に遷移
image.png

以下のソースでデプロイします。

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だけでは足りないです。レイヤーの設定が必要となります。

画面を少し下スクロールし。「レイヤー」の「レイヤーを追加」をクリック
image.png

「AWSレイヤー」を選択し、「AWS-Parameters-and-Secrets-Lambda-Extension」の最新バージョンを選択し、「追加」
image.png

⑥LambdaのIAMロール設定

Lambdaに「SSM」と「Cost Explore」へのアクセス権限を付与する必要があります。

「設定」>「アクセス権限」をクリックします。デフォルトで作成されたIAMロールはCloudWatch関連の権限しかないはずですので、ロールをクリックし編集します。
image.png

IAMの編集画面へ遷移します。ポリシーをクリックします。
image.png

「編集」をクリック
image.png

「ビジュアル」タブをクリックし、「許可をさらに追加」
image.png

Cost Explorer Serviceに関する以下の権限を与えます。
ce:GetCostAndUsage
ce:DescribeReport

image.png

Systems Managerに関する以下の権限を与えます。
ssm:GetParameter
リソースは作ったパラメータのARNにします
image.png

「次へ」>「変更を保存」
image.png

⑦Lambdaのタイムアウト設定

もう一度Lambdaに戻ります。

デフォルトのタイムアウト時間が足りない恐れがありますので、「設定」>「一般設定」>「編集」

image.png

10秒まで増やして「保存」
image.png

⑧Lambdaのトリガー設定

毎朝九時に、定期的にAWS料金を送ってもらいたいので、定期実行のトリガーを設定します。

「関数の概要」>「トリガーを追加」をクリック
image.png

トリガーの設定に「Event Bridge」を検索
image.png

「新規ルールを作成」をクリックし、ルール名を入力し、「追加」
「スケジュール式」を選択し、「cron(0 0 * * ? *)」を入力します。(UTC時間の朝九時の意味)
image.png

すると、トリガーが追加されました!
image.png

「Event Bridge」を確認すると、イベントスケジュール の内容がこのように表示され、以後10回のトリガー時間が表示されます。
image.png

⑨SlackのDMを待つ

明日の朝九時まで待つのは面倒くさいので、いったんトリガーのスケジュールを「cron(40 2 * * ? *)」(朝11:45)に変えてみて、結果を見ましょう!

すると、時間になったらメッセージが送られてきました!
image.png

メッセージ内の料金は、請求内容とは一致しています!
image.png

参考サイト

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?