0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

AWSリソースのコストを試算するLambda関数を作成してみた

0
Posted at

はじめに

本記事では、標準試算条件テンプレートを取得して、AWSリソースの概算コストを算出し、ドル円為替レートを取得するLambda関数を作成します。

今回は、AWSリソースで構成されるHULFT10 for Container Servicesというサービスについて試算してみます。
サービスの詳細は公式サイトをご確認ください。
https://www.saison-technology.com/service/product/lineup/hulft-10/function/

本記事では、以下のLambda関数を作成します。

  • 標準試算条件テンプレート取得
  • AWSリソースの概算コスト試算
  • ドル円為替レート取得

目次

  1. 標準試算条件テンプレートファイル作成

  2. Lambda関数作成(標準試算条件テンプレート取得)

  3. Lambda関数作成(概算コスト試算)

  4. Lambda関数作成(ドル円為替レート取得)


1. 標準試算条件テンプレートファイル作成

AWSリソース概算コスト試算する際に使用する試算条件のデフォルト値を記載したJSON形式のテンプレートを作成します。

以下はリソースの1つ(Aurora)のみを記載した設定例です。

実際には全リソース分を設定します。

{
  "resources": [
    (省略)
    {
      "resource": "Aurora",
      "serviceCode": "AmazonRDS",
      "region": "Asia Pacific (Tokyo)",
      "apiFilters": [
        {
          "Type": "TERM_MATCH",
          "Field": "location",
          "Value": "Asia Pacific (Tokyo)"
        },
        {
          "Type": "TERM_MATCH",
          "Field": "databaseEngine",
          "Value": "Aurora MySQL"
        },
        {
          "Type": "TERM_MATCH",
          "Field": "instanceType",
          "Value": "db.t4g.large"
        }
      ],
      "monthlyUsage": {
        "instanceCount": 1,
        "runningHoursPerMonth": 730
      },
      "pricingParameters": {
        "engine": "Aurora MySQL",
        "edition": "Aurora Standard",
        "vCpu": 2,
        "memory": "8GiB",
        "networkPerformance": "Up to 5 Gbps",
        "instanceFamily": "General purpose",
        "licenseModel": "100%",
        "purchaseOption": "OnDemand"
      }
    },
    (省略)
  ]
}

作成した標準試算条件テンプレートファイルはAmazon S3上の任意のバケット/フォルダにアップロードします。

標準試算条件テンプレートファイル作成②


2. Lambda関数作成(標準試算条件テンプレート取得)

Lambdaで、[関数を作成]を押下します。

Lambda関数作成(標準試算条件テンプレート取得)①

[関数名]と[ランタイム]を設定し、[関数を作成]を押下します。

Lambda関数作成(標準試算条件テンプレート取得)②

Amazon S3上に置いたJSON形式の標準試算条件テンプレートファイルを取得し、Agentに返却するコードを作成します。

以下はPythonコードの例です。

import json
import os
import boto3

s3 = boto3.client("s3")

def lambda_handler(event, context):
    try:
        # 環境変数からS3情報取得
        bucket = os.environ["TEMPLATE_BUCKET"]
        key = os.environ["TEMPLATE_KEY"]

        # S3からJSON取得
        response = s3.get_object(
            Bucket=bucket,
            Key=key
        )

        # JSON読み込み
        body = response["Body"].read().decode("utf-8")
        template = json.loads(body)

        # Agentへ返却
        return {
            "success": True,
            "template": template
        }

    except Exception as e:
        return {
            "success": False,
            "error": str(e)
        }

コードで環境変数を使用している場合は、[設定]⇒[環境変数]で環境変数を設定します。

Lambda関数作成(標準試算条件テンプレート取得)④

[設定]⇒[アクセス権限]⇒[ロール名]をクリックし、S3からオブジェクトを取得する権限を追加します。

Lambda関数作成(標準試算条件テンプレート取得)⑤

[許可を追加]⇒[インラインポリシーを作成]を押下します。

Lambda関数作成(標準試算条件テンプレート取得)⑥

JSONエディタを使用して、以下のように、指定したリソースからのS3オブジェクト取得を許可します。

以下は取得するS3オブジェクトのARNが「arn:aws:s3:::ito01/pricing-templates/*」の場合の設定例です。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::ito01/pricing-templates/*"
    }
  ]
}

[次へ]を押下します。

Lambda関数作成(標準試算条件テンプレート取得)⑧

[ポリシー名]を設定し、[ポリシーの作成]を押下します。

Lambda関数作成(標準試算条件テンプレート取得)⑨

3. Lambda関数作成(概算コスト試算)

Lambdaで、[関数を作成]を押下します。

Lambda関数作成(概算コスト試算)①


[関数名]と[ランタイム]を設定し、[関数を作成]を押下します。

Lambda関数作成(概算コスト試算)②


AWS Price List Query APIを利用してAWSリソースの概算コストを算出し、Agentに返却するコードを作成します。

以下はPythonコードのメイン関数の例です。

# Lambdaメイン処理
def lambda_handler(event, context):
    # API Gateway経由の場合bodyを取得
    if "body" in event:
        event = json.loads(event["body"])

    resources = event.get(
        "resources",
        []
    )

    # リソース別取得料金を保持
    prices = {}

    # 全リソースの料金取得を実行
    for item in resources:
        resource = item["resource"]

        # Auroraの場合
        if resource == "Aurora":
            prices[resource] = get_price(
                resource,
                item["serviceCode"],
                json.dumps(
                    item["apiFilters"],
                    sort_keys=True
                )
            )

            if isinstance(prices[resource], dict):
                prices[resource] = prices[resource]["price"]

        省略

    # 取得料金と利用量から月額計算
    result = calculate(
        resources,
        prices
    )

    # AIエージェントへ結果を返却
    return {
        "success": True,
        "total_usd_month": round(
            result["total"],
            2
        ),
        "resources": result["details"]
    }

以下はPythonコードのAPIで料金取得する関数の例です。

# AWS Pricing APIから単価を取得
@lru_cache(maxsize=100)
def get_price(
        resource,
        service_code,
        filters_json
):

    # JSON形式のフィルタを復元
    filters = json.loads(
        filters_json
    )

    # Pricing API検索結果を格納
    price_list = []

    # Pricing API呼び出し
    response = pricing_client.get_products(
        ServiceCode=service_code,
        Filters=filters
    )

    # 初回取得結果を追加
    price_list.extend(
        response["PriceList"]
    )

    # ページング結果を追加取得
    while response.get("NextToken"):
        # Pricing API呼び出し
        response = pricing_client.get_products(
            ServiceCode=service_code,
            Filters=filters,
            NextToken=response["NextToken"]
        )

        price_list.extend(
            response["PriceList"]
        )

        print(
            "PRODUCT COUNT:",
            len(price_list)
        )

    # 取得した商品の料金を確認
    for item in price_list:
        product = json.loads(item)

        # オンデマンド料金情報を取得
        terms = (
            product
            .get("terms", {})
            .get("OnDemand", {})
        )

        # 料金単位ごとに確認
        for term in terms.values():
            for dimension in term["priceDimensions"].values():
                unit = dimension["unit"]

                price = float(
                    dimension["pricePerUnit"]["USD"]
                )

                description = dimension.get(
                    "description",
                    ""
                )

                省略

                # Auroraインスタンス料金を取得
                elif resource == "Aurora":
                    if (
                        unit == "Hrs"
                        and
                        "IO-optimized" not in description
                    ):
                        return price

                省略

    # 対象料金が見つからない場合
    raise Exception(
        {
            "error": "price not found",
            "resource": resource
        }
    )

[設定]⇒[アクセス権限]⇒[ロール名]をクリックし、AWS Price List Query APIを利用して料金情報を取得するための権限を追加します。

Lambda関数作成(概算コスト試算)⑤


[許可を追加]⇒[インラインポリシーを作成]を押下します。

Lambda関数作成(概算コスト試算)⑥


JSONエディタを使用して、以下のように、AWS Price List Query APIを利用した料金情報の取得を許可します。

以下は設定例です。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "pricing:GetProducts"
      ],
      "Resource": "*"
    }
  ]
}

[次へ]を押下します。

Lambda関数作成(概算コスト試算)⑦


[ポリシー名]を設定し、[ポリシーの作成]を押下します。

Lambda関数作成(概算コスト試算)⑧

4. Lambda関数作成(ドル円為替レート取得)

Lambdaで、[関数を作成]を押下します。

Lambda関数作成(ドル円為替レート取得)①


[関数名]と[ランタイム]を設定し、[関数を作成]を押下します。

Lambda関数作成(ドル円為替レート取得)②


Free Currency Exchange Rate API(fxapi.app) を利用してドル円の為替レートを取得し、Agentに返却するコードを作成します。

以下はPythonコードの例です。

import json
import urllib.request
from datetime import datetime, timezone, timedelta

def get_usd_jpy_exchange_rate():
    url = "https://fxapi.app/api/USD/JPY.json"

    request = urllib.request.Request(
        url,
        headers={
            "User-Agent": "AWS-Lambda-ExchangeRate-Agent/1.0"
        }
    )

    with urllib.request.urlopen(request, timeout=5) as response:
        data = json.loads(response.read().decode("utf-8"))

    # UTC → JST
    utc_dt = datetime.fromisoformat(
        data["timestamp"].replace("Z", "+00:00")
    )

    jst = timezone(timedelta(hours=9))
    jst_dt = utc_dt.astimezone(jst)

    return {
        "currencyPair": "USD/JPY",
        "exchangeRate": round(data["rate"], 2),
        "rateDateTime": jst_dt.strftime("%Y-%m-%d %H:%M:%S JST")
    }

def lambda_handler(event, context):
    try:
        result = get_usd_jpy_exchange_rate()

        return {
            "statusCode": 200,
            "body": json.dumps(result, ensure_ascii=False)
        }

    except Exception as e:
        return {
            "statusCode": 500,
            "body": json.dumps(
                {"errorMessage": str(e)},
                ensure_ascii=False
            )
        }

最後に

本記事では、AWS Lambdaを利用して、標準試算条件テンプレートの取得、AWSリソースの概算コスト試算、ドル円為替レートの取得を行うLambda関数を作成しました。

これらのLambda関数をAIエージェントから呼び出すことで、最新のAWS料金や為替レートを取得し、試算条件の取得からコスト試算、為替換算までの処理を自動化することができます。

このブログでは、今後も様々なTopics記事や接続検証等、皆さんの参考になるような記事を投稿していきたいと思います!
ここまで読んでいただきありがとうございました。それでは、また!:raised_hand:

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?