top of page
植物と本
執筆者の写真Shumpei Miyawaki

GCP 料金を定期報告する slack bot を作成する


これは何?


[GCP お支払い > レポート] から参照可能な料金体系を…

一日一回、slack に定期報告する bot を作成する



注意事項

  • docker, cloud sdk 環境が必要


メールで予算を管理するだけで十分な場合

  • [お支払い > 予算とアラート] から、予算とアラートを設定可能

  • 機能としては、事前に設定した予算をオーバーした際にアラートメールを送信してくれる

  • どちらも設定しておくと安心


GCP の料金を slack で管理する


#01. slack の Messaging API を作成

  • slack の Incoming Webhook を設定し、詳細ページに遷移して以下を行う

    • Webhook URL をコピー

    • チャンネルへの投稿 から通知先を選択

    • 名前・アイコンをカスタマイズ


  • Webhook URL を用いて以下のスクリプトを実行すると slack に Hello World! というメッセージが送信される

# python の場合
import json
import os
import requests

WEBHOOK_URL = os.environ["WEBHOOK_URL"]
data = json.dumps({"text": "Hello World!"})
requests.post(WEBHOOK_URL, data=data)

#02. BigQuery で課金データを保持するデータセットを作成

  • GCP の [BigQuery > エクスプローラ] の左のツリーから、プロジェクト名の右にある [: > データセットを作成] からデータセットを作成

    • ここでは add_billing_data という名前で作成



#03. GCP 課金データをエクスポートする

  • [GCP の お支払い > 課金データのエクスポート] から BIGQUERY EXPORT の設定を行う

    • #02. で設定したデータセット名 add_billing_data を指定して保存


#04. Cloud Functions で実行スクリプトを作成

  • GCP の Cloud Functions 関数の作成から、❶構成 を設定


  • ❷コード にて以下のスクリプトをペーストしてデプロイ

    • ランタイム: Python 3.9

    • ソースコード: インラインエディタ

    • エントリポイント: notify_slack


# main.py

# -*- coding: utf-8 -*-
# 標準出力は Cloud Logging にて確認可能

import datetime as dt
import json
import base64
from pprint import pprint
import requests

from flask.wrappers import Request
from google.cloud import bigquery

QUERY = """
SELECT
  service.description as Service,
  (SUM(CAST(cost * 1000000 AS int64))
    + SUM(IFNULL((SELECT SUM(CAST(c.amount * 1000000 as int64))
    FROM UNNEST(credits) c), 0))) / 1000000 as Cost
FROM `{sql_database}`
WHERE project.name = '<project/name>' AND invoice.month = '{month}'
GROUP BY Service
ORDER BY Cost DESC
;
"""

def notify_slack(request: Request, context=None):
    WEBHOOK_URL = "<set/your/URL>"
    SQL_DATABASE = "<sql/database>"
	INVOICE_MONTH = dt.datetime.now(dt.timezone.utc).strftime("%Y%m")
		year, month = INVOICE_MONTH[:4], INVOICE_MONTH[4:]

    # GCP 利用料金取得
		query = QUERY.format(sql_database=SQL_DATABASE, month=INVOICE_MONTH)
    client = bigquery.Client()
    query_job = client.query(query)
    rows = query_job.result()

		# slack にメッセージを送信
    messages = []
    total_cost = 0
    for row in rows:
        desc = row.Service + " "*50
        total_cost += row.Cost
        total = " "*10 + f"{row.Cost:.2f}"
        text = f"・ {total[-10:]} 円 \\t {desc[:20]}\\t"
        messages.append(text)
    messages = [f"{year}年{month}月:\\t計 {total_cost:.2f} 円", "-"*40] + messages
    message = "\\n".join(messages)
    print(message)
    try:
        post_data = json.dumps({
            "text": message,
        })
        r_post = requests.post(WEBHOOK_URL, data=post_data)
        print(r_post.status_code)  # 201
        print(r_post)
        return "success"
    except Exception as e:
        print(e)
        return "error"
# requirements.txt
flask
requests
google-cloud-bigquery
  • (注意)上記 Python スクリプト内で実行している SQL クエリ実行時の処理サイズは事前に確認すること

#05. Cloud Run で実行スクリプトを実行

  • ローカルの適当な workspace に移動

  • script.sh を以下のように作成

# Cloud Function のページに指定してある URL に変更
URL="<https://(.*?).a.run.app>"

# 以下を実行
curl -m 70 -X POST $URL \\
-H "Authorization: bearer $(gcloud auth print-identity-token)" \\
-H "Content-Type: application/json" \\
-d '{
  "data": {"message": "Hello World"}
}'
  • Dockerfile を以下のように作成

FROM google/cloud-sdk:latest

ENV APP_HOME /app
COPY script.sh $APP_HOME/
RUN chmod +x $APP_HOME/script.sh

CMD $APP_HOME/script.sh
  • docker イメージをビルド

PROJECT_ID="<your project>"
NAME="<your app name>"
TAG="gcr.io/${PROJECT_ID}/${NAME}"
docker build . -t $TAG --no-cache
  • 以下を実行

# レジストリへプッシュ
gcloud builds submit --tag ${TAG}:latest

# ジョブを作成
gcloud alpha run jobs create ${NAME} \\
  --image ${TAG} \\
  --region asia-northeast1

# 作成したジョブが実行されるか確認
gcloud alpha run jobs execute ${NAME} \\
  --region asia-northeast1
  • GCP の Cloud Run から作成したプロジェクトに遷移

    • URL を控えておく




#06. Cloud Scheduler で定期実行

  • 以下を実行

PROJECT_NUMBER=$(gcloud projects list --filter="$(gcloud config get-value project)" --format="value(PROJECT_NUMBER)")

# 05. で控えた URL
CLOUD_RUN_URL="<https://(.*?)an.a.run.app>"

# 実行頻度
# 以下は 毎日 12:00 に slack に通知する
UNIX_CRON="0 12 * * *"

# 適当なサービスアカウント
SERVICE_ACCOUNT="<your accout>"

gcloud scheduler jobs create http ${NAME} \\
  --location="asia-northeast1" \\
  --schedule=${UNIX_CRON} \\
  --uri=${CLOUD_RUN_URL} \\
  --http-method="POST" \\
  --time-zone="JST" \\
  --oidc-service-account-email=${SERVICE_ACCOUNT}
  • GCP の Cloud Scheduler からジョブが作成されていることを確認する

    • 実行頻度などを修正可能


References

  • HTTP ターゲットで認証を使用する - GCP docs

  • Cloud Run Jobsを使用してジョブをスケジュール実行する

    • https://tech.rhythm-corp.com/schedule-jobs-to-run-using-cloud-run-jobs/

  • unix cron について

    • cron ジョブ スケジュールの構成 - GCP docs

    • https://www.yoheim.net/blog.php?q=20190902


閲覧数:7回0件のコメント

最新記事

すべて表示

GPT Index #02

Github Document GPT Index #01 2. Document GPT Index では Document [doc] と呼ばれるデータクラスを扱う BaseDocument [code] という基底クラスを継承している...

月次まとめ - 2023.01

本ブログ立ち上げ以前のものも軽く追加 # ブログ GitHub / Huggingface https://github.com/tanreinama/GPTSAN https://github.com/dmvaldman/html_semantic_seg...

コメント


bottom of page