RDS RIのリソースレベル適用状況をCUR2.0から把握する by DuckDB

RDS RIのリソースレベル適用状況をCUR2.0から把握する by DuckDB

Clock Icon2025.02.17

RDSのリザーブドインスタンス(RI)が 「どのDBインスタンスに適用されているのか」 を "長期的" に把握したいです。

要件を満たすために Cost and Usage Report (CUR) 2.0DuckDB を使った分析 を本ブログでトライしてみます。
DuckDBはオンライン分析処理(OLAP)に特化したデータベースシステムです。

なお、短期的な分析(過去14日間)や 非リソースレベルの分析であれば、 Cost Explorer による リソースレベルの可視化RI使用率、カバレッジレポート で済みます。 CURより簡単に確認できます。

前提

CUR2.0のデータエクスポート設定が完了していることが前提です。 私が関わっている環境では以下のような設定でS3バケットに出力しています。

設定項目
基本 > エクスポートタイプ 標準データエクスポート
データテーブルコンテンツ CUR 2.0
コンテンツ: リソースIDを含める Yes
コンテンツ: コスト配分データを分割 No
コンテンツ: 時間粒度 日次
コンテンツ: 列選択 全て選択
配信: 圧縮タイプ Parquet
配信: ファイルのバージョニング 既存のデータエクスポートファイルを上書き

また、分析はローカルの端末で実施します。 実行環境は以下のとおりです。

  • MacBook Pro (Apple M1 Max)
  • macOS Sequoia 15.3
  • DuckDB v1.2.0

セットアップ

DuckDBのインストール

以下ガイドのとおりに、 DuckDBをローカルにインストールします。

https://duckdb.org/docs/installation/?version=stable&environment=cli&platform=macos&download_method=direct

DuckDBのインストール
brew install duckdb
DuckDBのバージョン確認、起動
duckdb --version
# v1.2.0 5f5512b827
duckdb
# v1.2.0 5f5512b827
# Enter ".help" for usage hints.
# Connected to a transient in-memory database.
# Use ".open FILENAME" to reopen on a persistent database.
# D

CURオブジェクトのダウンロード

S3に保存されているCURオブジェクトを ローカルにダウンロードします。 今回は 2025/02 途中のCURオブジェクトを 分析対象とします。

### 適宜変更ください
bucket="EXAMPLE-DOC-BUCKET"
prefix="cur2"
export_name="daily-export"

### ファイルの確認
aws s3 ls ${bucket}/${prefix}/${export_name}/data/BILLING_PERIOD=2025-02/
# 2025-02-14 07:37:06   60149849 daily-export-00001.snappy.parquet
# 2025-02-14 07:37:07   60158854 daily-export-00002.snappy.parquet
# 2025-02-14 07:37:07   60391747 daily-export-00003.snappy.parquet

### ファイルのダウンロード
aws s3 cp s3://${bucket}/${prefix}/${export_name}/data/BILLING_PERIOD=2025-02/ . --recursive
ls
# daily-export-00001.snappy.parquet
# daily-export-00002.snappy.parquet
# daily-export-00003.snappy.parquet

クエリ確認

parquet ファイルを確認できるかチェックします。

duckdb 起動後、 SELECT * FROM 'daily-export-*.snappy.parquet' LIMIT 10; を実行してみます。 以下のような出力となりました。

sc_2025-02-15_23-25-49_7977

以降、RDS RIのリソースレベル適用状況を把握するために 試したクエリを紹介していきます。

(その前に) オンデマンドインスタンスとリザーブドインスタンスのコストについて

RDS DBインスタンスの時間単位コストを求めるには、 まずは prodcut/InstanceType の値を db:* で絞るとよいです (+ 加えて lineItem/UsageType*Usage:db.* あたりで指定すると、より確実です)。 db.t3.smalldb.m5.large など、「インスタンスタイプの使用コスト」の項目を取得できます。

その明細が「オンデマンド」か「リザーブド」かは lineItem/LineItemTypepricing/term から判断できます。

lineItem/LineItemType pricing/term
オンデマンドインスタンスの場合 Usage OnDemand
リザーブドインスタンスの場合 DiscountedUsage Reserved

オンデマンドインスタンスのコストは、通常は lineItem/UnblendedCost を見ます。 リザーブドインスタンスの場合は UnblendedCost は 0 です。

リーザーブドインスタンスの節約額を見積もるには reservation/EffectiveCostpricing/publicOnDemandCost を見るとよいでしょう。 EffectiveCost が実質的なコスト、 publicOnDemandCost が「もしオンデマンドで起動していた場合のコスト」です。 2つの差分が節約額です。

sc_2025-02-15_22-06-06_936
画像引用: AWS Cost and Usage Reports【AWS Black Belt】 - YouTube

オンデマンド料金が適用されているRDSインスタンス

以下クエリを実行することで、 「オンデマンド料金が適用されているRDSインスタンスの一覧」 を取得できます。

-- ファイル名や期間は適宜変更ください
SELECT
  line_item_usage_account_name as AWSAccount,
  regexp_replace(line_item_resource_id, '^arn:aws:.+:\d+:', '') as Resource,
  product_instance_type as InstanceType,
  CAST(SUM(line_item_unblended_cost) as INTEGER) as OnDemandCost
FROM './daily-export-*.parquet'
WHERE
  pricing_term = 'OnDemand'
  AND product_instance_type LIKE 'db.%'
  AND line_item_usage_type LIKE '%Usage:db.%'
  AND line_item_usage_start_date BETWEEN DATE '2025-02-03' AND DATE '2025-02-09'
GROUP BY AWSAccount, Resource, InstanceType
HAVING CAST(SUM(line_item_unblended_cost) as INTEGER) > 0
ORDER BY AWSAccount ASC, OnDemandCost DESC;

sc_2025-02-15_23-23-00_12498
出力サンプル

出力している列の情報は以下のとおりです。

列名 説明や補足
AWSAccount AWSアカウント名
Resource DBインスタンスのリソースID(ARNの末尾部分のみ)
InstanceType DBインスタンスのインスタンスタイプ
OnDemandCost 対象期間中のオンデマンドコスト合計

リザーブドインスタンス一覧とその実質コスト

以下クエリを実行することで、 「リザーブドインスタンス一覧とその実質コスト」 を取得できます。

-- ファイル名や期間は適宜変更ください
SELECT
  line_item_usage_account_name as AWSAccount,
  regexp_replace(line_item_resource_id, '^arn:aws:.+:\d+:', '') as Resource,
  product_instance_type as InstanceType,
  CAST(SUM(reservation_effective_cost) as INTEGER) as EffectiveCost
FROM './daily-export-*.parquet'
WHERE
  pricing_term = 'Reserved'
  AND product_instance_type LIKE 'db.%'
  AND line_item_usage_type LIKE '%Usage:db.%'
  AND line_item_usage_start_date BETWEEN DATE '2025-02-03' AND DATE '2025-02-09'
GROUP BY AWSAccount, Resource, InstanceType
HAVING CAST(SUM(reservation_effective_cost) as INTEGER) > 0
ORDER BY AWSAccount ASC, EffectiveCost DESC;

sc_2025-02-15_23-20-46_10284
出力サンプル

出力している列の情報は以下のとおりです。

列名 説明や補足
AWSAccount AWSアカウント名
Resource DBインスタンスのリソースID(ARNの末尾部分のみ)
InstanceType DBインスタンスのインスタンスタイプ
EffectiveCost 対象期間中のリザーブドインスタンスによる実質コスト

これまでの分析を1テーブルに集約 + 節約額を表示

最後に これまでのクエリを1つにまとめて、 「リザーブドインスタンスによる節約額」の情報を付与したテーブルを作成します。

-- ファイル名や期間は適宜変更ください
SELECT
  line_item_usage_account_name as AWSAccount,
  regexp_replace(line_item_resource_id, '^arn:aws:.+:\d+:', '') as Resource,
  product_instance_type as InstanceType,
  pricing_term as PricingTerm,
  CAST(SUM(line_item_unblended_cost) as INTEGER) +
    CAST(SUM(reservation_effective_cost) as INTEGER) as Cost,
  CAST(SUM(pricing_public_on_demand_cost) as INTEGER) -
    CAST(SUM(line_item_unblended_cost) as INTEGER) -
    CAST(SUM(reservation_effective_cost) as INTEGER) as Saving
FROM './daily-export-*.parquet'
WHERE
  product_instance_type LIKE 'db.%'
  AND line_item_usage_type LIKE '%Usage:db.%'
  AND line_item_usage_start_date BETWEEN DATE '2025-02-03' AND DATE '2025-02-09'
GROUP BY AWSAccount, Resource, InstanceType, PricingTerm
HAVING
  CAST(SUM(line_item_unblended_cost) as INTEGER) > 0
  OR CAST(SUM(reservation_effective_cost) as INTEGER) > 0
ORDER BY AWSAccount ASC, Resource ASC;

sc_2025-02-15_23-18-23_31648
出力サンプル

出力している列の情報は以下のとおりです。

列名 説明や補足
AWSAccount AWSアカウント名
Resource DBインスタンスのリソースID(ARNの末尾部分のみ)
InstanceType DBインスタンスのインスタンスタイプ
PricingTerm OnDemand もしくは Reserved
Cost OnDemand の場合: 非ブレンドコスト
Reserved の場合: 実質コスト
Saving OnDemand の場合: 0
Reserved の場合: リザーブドインスタンスによる節約額

おわりに

RIの適用状況を把握するために CUR2.0 と DuckDB を活用してみました。 長期的なリソースレベル情報が欲しいときには CUR が役に立ちます… が、各列や各行の読み込みがやはり大変です。

基本的には CUR 以外のコストツール(Cost Explorer等)を活用して、 それらでは難しい分析においてのみ CUR を使っていくのが良いと感じました。

あとDuckDBは非常に便利です。 手元でサクッとログを分析したい場合に、今後活用していこうと思います。

以上、参考になれば幸いです。

参考

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.