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

2022.12.03

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

困っていた内容

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

どう対応すればいいの?

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

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

上記を CloudWatch Events で定期的に実行して Slack に通知します。

やってみた

実行環境

Lambda 作成リージョン:バージニア北部(us-east-1)
ランタイム:python 3.9
デフォルトの実行ロールの変更:ReadOnlyAccess ポリシーを持った IAM ロール

コスト

def getCostAndUsage():
    now = datetime.datetime.today()
    _start_date = str((now - timedelta(1)).date())
    _end_date = str(now.date())
    params = {
        'TimePeriod': {
            'Start': _start_date,
            'End': _end_date
        },
        'Granularity': 'DAILY',
        'Metrics': ['BlendedCost']
    }
    client = boto3.client('ce') 
    res = client.get_cost_and_usage(**params)
    cost = res['ResultsByTime'][0]['Total']['BlendedCost']['Amount']
    global msg
    msg += 'コスト(USD):' + cost + LF
    ec2describeInstances()

前日から当日のコストを取得しています。 まず、_start_date と _end_date という変数に今日と昨日の日付を入れています。このスクリプトが 10/9 に実行された場合は START は 10/8 で END は 10/9 になります。 結果は msg という変数に入れて後で Slack に送るメッセージの一部として使用します。

台数

def ec2describeInstances():
    client = boto3.client('ec2', region_name='ap-northeast-1') #東京リージョンが対象
    res = client.describe_instances()
    cnt = len(res['Reservations'])
    global msg
    msg += 'EC2: ' + str(cnt) + '台起動中です!' + LF

describe_instances のレスポンスである Reservations の長さがインスタンス数になります。 コストと同様に台数を msg という変数に入れます。 同じ考え方で例えば RDS のインスタンス数なども簡単にとれます。

Slack 送信

def send_slack():
    url = "https://slack.com/api/chat.postMessage"
    SLACK_TOKEN = os.environ['SLACK_TOKEN']
    SLACK_CHANNEL = os.environ['SLACK_CHANNEL']
    payload = {
        "token": SLACK_TOKEN,
        "channel": SLACK_CHANNEL,
        "text": msg,
    }
    try:
        res = requests.post(url, params=payload)
        json = res.json()
    except Exception as e:
        print("post_slack {}".format(e))
        raise
    else:
        return

受け取った msg という引数をSlackに送信します。 トークンなどの機密情報は環境変数に入れてコード上ではos.environ['【環境変数名】']で参照します。 こちらは下記のブログを参考に作成させていただきました。

AWSサービス毎の請求額を毎日Slackに通知してみた

EventBridge (CloudWatch Events) 設定

例えば下記のようにEventBridge (CloudWatch Events) を登録することで定期的にこのLambda 関数を実行することができます。

下記のケースでは毎日 16:10 JST に実行するように設定しています。

実行結果

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

全コード

import os
import requests
import json
import boto3
import re
import logging
from base64 import b64decode
import datetime
from datetime import timedelta

LF = '\n'
msg = 'tes1' + LF

def lambda_handler(event, context):
    getCostAndUsage()

def getCostAndUsage():
    now = datetime.datetime.today()
    _start_date = str((now - timedelta(1)).date())
    _end_date = str(now.date())
    params = {
        'TimePeriod': {
            'Start': _start_date,
            'End': _end_date
        },
        'Granularity': 'DAILY',
        'Metrics': ['BlendedCost']
    }
    client = boto3.client('ce') 
    res = client.get_cost_and_usage(**params)
    cost = res['ResultsByTime'][0]['Total']['BlendedCost']['Amount']
    global msg
    msg += 'コスト(USD):' + cost + LF
    ec2describeInstances()

def ec2describeInstances():
    client = boto3.client('ec2', region_name='ap-northeast-1') #東京リージョンが対象
    res = client.describe_instances()
    cnt = len(res['Reservations'])
    global msg
    msg += 'EC2: ' + str(cnt) + '台起動中です!' + LF
    send_slack()

def send_slack():
    url = "https://slack.com/api/chat.postMessage"
    SLACK_TOKEN = os.environ['SLACK_TOKEN']
    SLACK_CHANNEL = os.environ['SLACK_CHANNEL']
    payload = {
        "token": SLACK_TOKEN,
        "channel": SLACK_CHANNEL,
        "text": msg,
    }
    try:
        res = requests.post(url, params=payload)
        json = res.json()
    except Exception as e:
        print("post_slack {}".format(e))
        raise
    else:
        return

費用

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

関連情報

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

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

最後に

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