LoginSignup
4
7

More than 3 years have passed since last update.

AWSの課金情報をSlackへ送るまでにとても苦労した話

Last updated at Posted at 2018-08-08

はじめに

  • 毎月のAWSの課金情報をちゃんと把握したい
  • いちいちAWSにログインして確認したしたくない
  • そろそろLambda使ってみたい
  • 自分が把握するものをSlackに集約している

こんな理由から、やってみようと考えた。

Slack

まずは課金情報を受け取るChannelを作成する。
名前や目的は後で修正できるけれど、ちゃんと決めておくことをオススメします。
Slackのチャンネル作成

続いて、Webhook URLの取得。
https://slack.com/services/new/incoming-webhook から取得できる。
通知を受け取るチャンネル(さっき作ったやつ)を指定する。
Webhook URLが出来上がるので、忘れずにコピーしておく。

チャンネルを指定しよう

Webhook URLができた

ローカル(Mac)

いきなり壁にぶつかる

Terminalで以下コマンドを叩いてlambda-uploaderをインストール。
・・・とはうまくいかなかった。

$ pip install lambda-uploader 

なんでだろ?と考えた結果、以下のメッセージが出ているからでは?と考えた。

You are using pip version 10.0.1, however version 18.0 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.

よしわかった、アップグレードしてやろうじゃないか。

$ pip install --upgrade pip

途中でエラー発生。

Could not install packages due to an EnvironmentError: [Errno 13] Permission denied: '/Library/Python/2.7/site-packages/pip-10.0.1-py2.7.egg/EGG-INFO/PKG-INFO'
Consider using the `--user` option or check the permissions.

仕方ない、やり直し。

$ pip install --upgrade pip --user

Successfullyは出ているけれど、ちゃんとできているか不安。
ここでPythonのバージョンを確かめてみようと思った。

$ python --version
Python 2.7.10

Python 3.5.0とか入れてなかったっけ?何インストールできるんだっけと思って、pyenvを実行。

$ pyenv install --list
-bash: pyenv: command not found

pyenvが使えない・・・仕方がないので、gitから持ってくることにする。

$ git clone git://github.com/yyuu/pyenv.git ~/.pyenv
$
$ echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bash_profile
$ echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bash_profile
$ echo 'eval "$(pyenv init -)"' >> ~/.bash_profile
$ source ~/.bash_profile

ちょっと前のコマンドを実行。

$ pyenv install --list

インストールできるバージョンのリストが表示されたので、その中から3.5.0をインストールすることに。

$ pyenv install 3.5.0

インストールがエラーなくうまくいったので、2.7.10から3.5.0にバージョンを変えてみる。

$ pyenv global 3.5.0
$ python --version
Python 2.7.10

あれ?
Pythonはどこを見ている?

$ which python
/Users/xxxxxx/.pyenv/shims/python

色々調べて、以下の通り~/.bash_profileに追記をすることに。

$ export PATH="'$HOME/.pyenv/shims:$PATH"
$ source ~/.bash_profile

さて、これでどうだ。

$ python --version
Python 3.5.0

あぁ、ようやくうまくいった。

各種インストール

lambda-uploaderをインストール。

$ pip install lambda-uploader

OK、次にaws cliをインストール。

$ pip install awscli

続いてaws configureで設定をするのだが、Access KeyとSecret Access Keyが必要になる。
作成していない場合は、セキュリティ認証情報のページから作成する。

$ aws configure
AWS Access Key ID [None]: *****************
AWS Secret Access Key [None]: *****************
Default region name [None]: ap-northeast-1
Default output format [None]: text

東京リージョンを指定する場合は、ap-northeast-1を指定するようだ。

AWS

CloudWatch

AWSの管理コンソール、請求ダッシュボード->設定に移動して、請求アラートを受け取る にチェックが付いていることを確認する。
付いていない場合はチェックを入れておく。

CloudWatchのアラート設定

Lambda関数を作成

コードをlambda-uploaderでデプロイするためには、あらかじめ空の関数を用意する必要があるらしい。

Lambdaで 一から作成 を選択。
名前とロール名はわかりやすいものを指定、ランタイムは Python3.6 にした。
ロールは テンプレートから新しいロールを作成 を選択し、ポリシーテンプレートは 基本的な Lambda@Edge のアクセス権限 (CloudFront トリガーの場合) を選択。
これで大丈夫なはず。多分・・・。
関数の作成 ボタンを押して、空の関数の作成は完了。

関数の作成を選択

一から作成を選択

設定値を入力

空の関数が完成

IAMロール

Lambda関数を作成した時に、IAMロールを作成した。(テンプレートから新しいロールを作成を選んだから)
そのIAMロールにCloudWatchReadOnlyAccessポリシーをアタッチする。
コスト情報をLambdaから読みだすのに必要とのこと。
アタッチ後に、ロールARNをコピーしておく。

作成したロールを選択

ポリシーをアタッチするよ

CloudWatchReadOnlyAccessをチェック

アタッチを確認

コード(ローカル)

ローカルでコードを編集する。
個人的に好きなATOMを利用して編集する。

ディレクトリとファイルは以下のようにする。

ファイルの構成

lambda_function.py

lambda_function.py
#!/usr/bin/env python
# encoding: utf-8

import json
import datetime
import requests
import boto3
import os
import logging

# Logger の設定
logger = logging.getLogger()
logger.setLevel(logging.INFO)

# Slack の設定
SLACK_POST_URL = os.environ['slackPostURL']
SLACK_CHANNEL = os.environ['slackChannel']

# CloudWatch
# region_nameはus-east-1にしておくこと
response = boto3.client('cloudwatch', region_name='us-east-1')

# ValueはUSDじゃないとダメ
get_metric_statistics = response.get_metric_statistics(
    Namespace='AWS/Billing',
    MetricName='EstimatedCharges',
    Dimensions=[
        {
            'Name': 'Currency',
            'Value': 'USD'
        }
    ],
    StartTime=datetime.datetime.today() - datetime.timedelta(days=1),
    EndTime=datetime.datetime.today(),
    Period=86400,
    Statistics=['Maximum'])

cost = get_metric_statistics['Datapoints'][0]['Maximum']
date = get_metric_statistics['Datapoints'][0]['Timestamp'].strftime('%Y年%m月%d日')

def build_message(cost):

    text = "%sまでのAWSの課金額は、$%sです。" % (date, cost)

    color = "#ffffff" # black

    atachements = {"text":text,"color":color}

    return atachements

def lambda_handler(event, context):
    content = build_message(cost)

    # 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)

lambda.json

  • name: Lambda関数の名前を入れる
  • description: Lambda関数の説明を入れる
  • region: リージョンを入れる、東京ならこのまま。
  • handler: ハンドラーの名前を入れる
  • role: IAMロールのARNを入れる
  • slackPostURL: SlackのWebhookURLを入れる
  • slackChannel: Slackで投稿するチャネルを入れる ex.#aws
lambda.json
{
  "name": "Lambda関数の名前",
  "description": "Lambda関数の説明",
  "region": "ap-northeast-1",
  "handler": "lambda_function.lambda_handler",
  "role": "IAMロールのARN",
  "timeout": 300,
  "memory": 128,
  "variables":
    {
      "slackPostURL":"Slack WebhookのURL",
      "slackChannel":"Slackの投稿チャネル"
    }
}

requirements.txt

requirements.txt
requests

デプロイする

デプロイするときは、上記ファイルを置いたディレクトリに移動してから行うこと。

$ lambda-uploader
λ Building Package
λ Uploading Package
λ Fin

AWS-CloudWatch

CloudWatchのイベントを作成する。
CloudWatchに移動して、イベント->ルールの作成 を選択する。
20201107_IMG_1238.png

「スケジュール」にチェックを入れる。
「Cron式」に値を入れる。Cron式の書き方は参考にリンクを付けた。
ターゲットは「Lambda関数」で、機能で作成した関数を選択する。
20201107_IMG_1241.png

ルールの名前と説明はお好きなように。
20201107_IMG_1242.png

これでCloudWatchのルールが完成。
20201107_IMG_1243.png

結果

綺麗にうまくいった!と言いたいところだが、実際はうまく飛んでこなくて試行錯誤。
その結果が、上のコードです。
lambda_function.pyregion_name と Dimensionsの Value かな、引っ掛かったのは。
それ以外はうまくいった。

参考

修正

  • AWS-CloudWatchの画像リンクが切れていたので、新しいものに差し替え(2020/11/7)
4
7
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
4
7