HAQM Web Services ブログ
AWS Savings Plans: 効果的なチャージバック戦略を実装する方法
組織が成長するにつれて、クラウドインフラの管理はますます複雑になり、コストを最適化するための高度な財務戦略が必要になります。AWS Savings Plans は、1 年または 3 年の期間にわたって 1 時間あたりの米ドル (USD) で測定される一定の使用量をコミットしていただく代わりに、AWS サービスの使用料金を大幅に節約できる柔軟な価格モデルを提供します。多くの場合、個々のチームが直接購入したり、FinOps チームが特定のアカウントで購入したりすることで、複数の Savings Plans が採用されています。これらの戦略は大幅なコスト削減につながる可能性がある一方で、公平かつ効果的なチャージバック (※) プロセスを確保する上では複雑さも増すことにもなります。
※訳注:チャージバックとは、組織の内部会計プロセスを通じて、発生した費用を実際にそのサービスやリソースを使用した部門等に請求する仕組みのことを指します。詳細はこちらのドキュメントをご覧ください。
本記事では、管理アカウント、連結アカウント、またはその両方で購入した Savings Plans のコストを、その割引を受けたアカウントに適切に配分するチャージバックの仕組みを定義する方法について説明します。それを理解していただくことで、Savings Plans 割引の恩恵を受けたアカウントを特定し、その具体的な使用状況に基づいてチャージバックする適切な金額を算出できるようになります。
Savings Plans の割引共有について
AWS では、同じ AWS Organizations の organization (組織) に属するアカウント間で Savings Plans の割引を共有することが可能です。Savings Plans の時間単位のコミットメント料金はそれを購入したアカウントに請求されますが、共有が有効になっている場合、割引は organization 内の複数のアカウントに適用される可能性があります。Savings Plans の割引は、まず Savings Plans を購入したアカウント内のすべての対象となるリソースに適用されます。割引を適用できるオンデマンド使用量がそれ以上なく “未使用のコミットメント” が生じる場合には、使い切れていないコミットメントは organization 内の他の連結アカウント (メンバーアカウント) で使用されます。
共有によって節約効果を最大化できますが、その一方で共有による恩恵を organization 全体に適切に配分するには追加の労力が必要になる場合があります。Savings Plans の割引の恩恵を受けるすべてのアカウントに、Savings Plans のコミットメント料金を (AWS に対して直接) 支払う責任があるわけではありません。コミットメントのコストを負担しているアカウント (つまりコミットメントを購入しているアカウント) 以外が Savings Plans の恩恵を受けることもあります。そのため、恩恵 (つまり割引) が共有された場合には、慎重にコスト配分を行い各アカウントに対して公平に請求が行われるようにする必要があります。
Savings Plans の仕組みと、共有が Savings Plans に与える影響について理解できたので、次はコストと使用状況レポート (CUR) 2.0 のデータを使用したチャージバック戦略を見てみましょう。
前提条件
AWS Data Export により CUR 2.0 でエクスポート (※) を作成し、データをカタログ化するように AWS Glue を設定します。これにより、HAQM Athena を使用してクエリを実行し、CUR 2.0 のデータを分析することができます。これを実現するには、次のことを行う必要があります。
※訳注:AWS Data Export においてエクスポートされるデータのことを「エクスポート」と呼びます。
1. AWS Data Export による CUR 2.0 の設定
- AWS マネジメントコンソールにサインインします。
- AWS 請求とコスト管理に移動します。[データエクスポート (Data Export)] を選択し、[作成 (Create)] をクリックしてエクスポートの設定を開始します。
- [標準データエクスポート (Standard data export)] を選択し、エクスポート名を指定し、データテーブルタイプとして [CUR 2.0] を選択します。
- [リソース ID を含める (Include resource IDs)] と [コスト配分データを分割 (Split cost allocation data)] の有効化はオプションです。
- 時間粒度として [時間単位 (Hourly)] を選択します。
- 圧縮形式として [Parquet] を設定し、ファイルのバージョニングのために [既存のデータエクスポートファイルを上書き (Overwrite existing data export file)] を選択します。
- CUR 2.0 データを保存する宛先の HAQM S3 バケットとパスプレフィックスを指定します。
- [作成 (Create)] を選択して設定を完了します。(※)
※訳注:設定後、S3 バケットに CUR 2.0 のエクスポートが配信されるまで最大 24 時間かかります。
2. CUR データをクエリするための AWS Glue の設定
- AWS Glue コンソールに移動し、[Data Catalog] > [Crawlers] を選択して CUR 2.0 データのカタログ化プロセスを開始します。
- [Create crawler] をクリックして、一意のクローラー名を割り当てます。[Next] をクリックします。
- [Is your data already mapped to Glue tables?] の質問については、[Not yet] を選択します。
- [Add a data source] をクリックし、[S3] を選択して、(AWS Data Export 内で設定した) CUR 2.0 データがエクスポートされる HAQM S3 の場所を以下の形式で指定します。
s3://<bucket-name>/<prefix>/<export-name>/data/
- [Add an S3 data source] をクリックし、[Next] をクリックします。
- [Create new IAM role] をクリックすると、新しい AWS Glue ロールが作成されます。このロールにより、Glue は CUR 2.0 ファイルが保存されている S3 バケットにアクセスできるようになります。[Next] をクリックします。
- [Add database] をクリックしてターゲットデータベースを作成します。データベース名を入力し、[Create database] をクリックします
- AWS Glue コンソールに戻り、前のステップで作成したデータベースを選択します。クローラーのスケジュールを [On demand] に設定して、必要な場合にのみ実行するようにします。[Next] をクリックします。
- 設定を確認し、[Create crawler] を選択します。
- クローラーの準備ができたら、クローラーを選択して [Run] をクリックします。これにより、データが処理されてカタログ化され、HAQM Athena からアクセス可能なテーブルが作成されます。(※)
※訳注:データエクスポートの設定後、S3 バケットに CUR 2.0 のエクスポートが配信されるまで最大 24 時間かかります。まだ配信されていない状態でクローラーを実行してもカタログ化およびテーブルの作成はされないため、クローラーの実行はエクスポートが配信されるまでお待ちください。
CUR 2.0 を使って Savings Plans のチャージバックを行う
上記の前提条件を設定したら、以下のクエリを使用して、Savings Plans の割引を受け取った連結アカウントを特定します。[Effective Cost] 列には、連結アカウントで使用された Savings Plans のコミットメントの金額に対応するコストが表示されます。これが個々の連結アカウントへのチャージバックに使用する金額になります。
- HAQM Athena コンソールに移動してクエリを実行します。Athena での SQL クエリの実行に関する詳細についてはこちらをご覧ください。
- 以下のクエリをクエリエディタにコピーします。クエリのテーブル名を更新してください (※)。
※訳注:具体的には、クエリ内の 59 行目の「<Table Name>」を Glue テーブルのデータベース名 (前述の流れでエクスポートや Glue テーブルを作成した場合は「data」) で置き換えてください。
※訳注:以下のクエリは、実行日の前月の 請求期間 (1 か月) を対象に分析を行うことを想定しています。先述の設定で CUR 2.0 のエクスポートを初めて S3 バケットに出力した場合、その前月のエクスポートは存在しないため、クエリ自体は成功するもののクエリ結果は空になります。その場合は 62 行目の「INTERVAL '1' month
」の「1
」を「0
」に修正して、クエリ実行当月 (その時点まで) の CUR 2.0 エクスポートを分析対象にするようにしてみてください。
select
DATE_FORMAT(bill_billing_period_start_date,'%Y-%m-%d') as "Date"
, line_item_usage_account_id as "Account Id"
, savings_plan_offering_type as "Savings Plan Type"
, split_part(savings_plan_savings_plan_a_r_n, '/', 2) AS "Saving Plan ID"
, savings_plan_payment_option as "Savings Plan Payment Option"
, line_item_line_item_type as "Item Type"
, sum(
case
when line_item_line_item_type = 'SavingsPlanCoveredUsage' then 0
else savings_plan_recurring_commitment_for_billing_period
end
) + sum(
case
when line_item_line_item_type = 'SavingsPlanCoveredUsage' then 0
else savings_plan_amortized_upfront_commitment_for_billing_period
end
) as "Savings Plan Fee"
, sum(
case
when line_item_line_item_type = 'SavingsPlanCoveredUsage' then 0
else savings_plan_recurring_commitment_for_billing_period
end
) + sum(
case
when line_item_line_item_type = 'SavingsPlanCoveredUsage' then 0
else savings_plan_amortized_upfront_commitment_for_billing_period
end
) - sum(savings_plan_used_commitment) as "Unused commitment"
, sum(
case
when line_item_line_item_type = 'SavingsPlanRecurringFee' then 0
else savings_plan_savings_plan_effective_cost
end
) as "Effective Cost"
, sum(
case
when line_item_line_item_type = 'SavingsPlanRecurringFee' then 0
else line_item_unblended_cost
end
) - sum(
case
when line_item_line_item_type = 'SavingsPlanRecurringFee' then 0
else savings_plan_savings_plan_effective_cost
end
) - ( sum(
case
when line_item_line_item_type = 'SavingsPlanCoveredUsage' then 0
else savings_plan_recurring_commitment_for_billing_period
end
) + sum(
case
when line_item_line_item_type = 'SavingsPlanCoveredUsage' then 0
else savings_plan_amortized_upfront_commitment_for_billing_period
end
) - sum(savings_plan_used_commitment) ) as "Savings"
from
<Table Name>
where
line_item_line_item_type in ('SavingsPlanCoveredUsage', 'SavingsPlanRecurringFee')
and bill_billing_period_start_date = DATE_TRUNC('month', CURRENT_DATE) - INTERVAL '1' month
group by
bill_billing_period_start_date
, line_item_usage_account_id
, savings_plan_offering_type
, savings_plan_savings_plan_a_r_n
, savings_plan_payment_option
, line_item_line_item_type
order by
sum(savings_plan_savings_plan_effective_cost) desc
これをよりよく理解するために、AWS CUR 2.0 にある 2 つの重要なコンポーネントを詳しく見てみましょう。
- SavingsPlanRecurringFee:これは出力内で「
Item Type = 'SavingsPlanRecurringFee'
」であるフィールドです。これは、Savings Plans の購入アカウントがそのコミットメントに対して支払う義務があるコストを表します。これはコミットメントの全額が使用されたかどうかにかかわらず固定費です。Savings Plans の種類に応じて、この金額は非ブレンドコストまたは償却コストとして表示されます。 - SavingsPlanCoveredUsage: これは出力内で「
Item Type = 'SavingsPlanCoveredUsage'
」であるフィールドです。これは Savings Plans の実際の使用量を表しており、コミットされた Savings Plans のうち、organization 全体での使用量にどの程度適用されたかを示します。organization の構造とワークロードの分散状況によっては、この使用量が複数のアカウントに分散される可能性があります。
Savings Plans のチャージバックを行うには、連結アカウントごとの「Effective Cost」列を使用する必要があります。この列には、各連結アカウントで使用された Savings Plans のコミットメントの割合に相当するコストが表示されています。これにより、各連結アカウントが Savings Plans から受けた恩恵に応じて Savings Plans の料金を確実に負担することができるようになります。
SavingsPlanRecurringFee
のある行の「Unused Commitment」列を確認することも重要です。この列の値が $0 より大きい場合は、Savings Plans が十分に活用されていないことを示しています。これは一見すると節約機会の損失のように見えるかもしれませんが、実際にそうであるかどうかの検証が重要です。組織は意図的に想定使用量をやや上回る Savings Plans のコミットメントをあえて購入することがあります。これは、未使用分のコストを考慮しても、割引による全体的な節約効果の方が大きく、organization 全体としては正味の節約効果が見込める可能性があるからです。
例
以下の表では、Savings Plans のタイプは「No Upfront
」です。関連する「SavingsPlanRecurringFee」フィールドを確認すると、毎月の定期料金 (“Savings Plan Fee” 列) はアカウント ID Aに請求されています。Savings Plans を購入したアカウントはアカウント ID A であるため、アカウント ID A の対象となる使用量に対して最初に割引が適用されます。月額コミットメント $12,410.68 のうち、$8,363.12 がアカウント ID A にチャージバックされる実効コスト (“Effective Cost” 列) です。アカウント B は、定期 (月額) コミットメントのうち $1,361.26 を使用しており、これがアカウント B に請求されるチャージバック額になります。また、未使用のコミットメント (“Unused Commitment” 列) が $0 で、実効コスト (“Effective Cost” 列) の合計が定期料金 (“Savings Plan Fee” 列) と一致していることも確認できます。これは、Savings Plans が十分に活用されていることを示しています。
別の例を見てみましょう。
以下の表では、Savings Plans のタイプが「All Upfront
」であることがわかります。これは、請求期間における前払い金額の償却部分に相当します。データによると、「未使用のコミットメント (“Unused Commitment” 列)」は $0 であるため、Savings Plans はアカウント ID A で購入されており、かつアカウント ID A で完全に使い切られていることがわかります。この場合、Savings Plans の恩恵を受けているアカウントは (アカウント ID A の) 1 つだけであるため、定期料金 (“Savings Plan Fee” 列) が実効コスト (“Effective Cost” 列) と一致しています。
まとめ
この記事では、Savings Plans の共有がその使用量に与える影響について説明しました。共有を有効にすると、Savings Plans の料金を支払うことなく Savings Plans の割引の恩恵を受けられるアカウントが存在する可能性があります。Savings Plans の料金を (AWS に対して直接) 支払う義務は、それを購入したアカウントのみにあります。
AWS Cost and Usage Report (CUR) 2.0 で “対象を絞ったクエリ” を実行することで、Savings Plans の割引を受けているすべての対象アカウントと、それぞれに請求すべき定期料金の割合を特定できるチャージバックの仕組みを設計しました。この戦略により、Savings Plans を保有しているアカウントにのみ請求するのではなく、社内固有のチャージバックの仕組みを使用して、使用量とそれによって得られた節約額に基づいて正確にアカウントにチャージバックできるようになります。この方法により、Savings Plans のコストと恩恵の両方を公正かつ透明に分配することができ、財務責任を実際の使用状況に合わせて調整するのに役立ちます。
この戦略により、透明性と説明責任が高まり、チーム全体での思慮深いクラウド利用を促進します。Savings Plans のメリットを享受した分に応じて各アカウントに適切に請求することで、組織全体でのコスト意識の向上につながります。