AWSのコスト可視化の取り組み
はじめに
こんにちは、レンティオでエンジニアをしている坂元です。
レンティオではAWSコスト最適化の一環として、
Cost and Usage Report(CUR)とAthena、Redash、Slackを使ったAWSコストの可視化を行ったのでその取り組みについて紹介します。
Cost and Usage Report(CUR)とは
AWSのコストや使用状況の詳細なレポートをS3に出力してくれるサービスです。レポートは、Athena、Redshift、QuickSightとの統合などAWSの他サービスと連携して分析や可視化を行うことができます。
構成
レンティオではBIツールとしてRedashを使っており、RedashからAthenaのクエリを実行する環境が整っていました。
また、Redash Slack botでSlackからダッシュボードのキャプチャを確認できるようになっているので、Redashでダッシュボードを作成し毎日Slackにキャプチャを投稿する構成にしました。
構築
以下の手順で構築しました。
この手順はRedashやRedash Slack botの構築が済んでいることが前提の手順です。
- CURのレポート出力の設定
- Athenaのテーブル作成
- Redashでダッシュボード作成
- Slackにリマインダーを設定
1. CURのレポート出力の設定
AWSマネジメントコンソールの 請求とコスト管理
> データエクスポート
から作成します。
今回は、
- CUR 2.0
- Parquet形式
を選択して作成しました。
2. Athenaのテーブル作成
レポートに出力されるカラムとデータ型はAWSのドキュメントに記載されていますので、ここを参考にテーブルを作成します。
テーブル作成
CREATE EXTERNAL TABLE `cur` (
`bill_bill_type` string,
`bill_billing_entity` string,
`bill_billing_period_end_date` timestamp,
`bill_billing_period_start_date` timestamp,
`bill_invoice_id` string,
`bill_invoicing_entity` string,
`bill_payer_account_id` string,
`bill_payer_account_name` string,
`cost_category` map < string, string >,
`discount` map < string, string >,
`discount_bundled_discount` double,
`discount_total_discount` double,
`identity_line_item_id` string,
`identity_time_interval` string,
`line_item_availability_zone` string,
`line_item_blended_cost` double,
`line_item_blended_rate` string,
`line_item_currency_code` string,
`line_item_legal_entity` string,
`line_item_line_item_description` string,
`line_item_line_item_type` string,
`line_item_net_unblended_cost` double,
`line_item_net_unblended_rate` string,
`line_item_normalization_factor` double,
`line_item_normalized_usage_amount` double,
`line_item_operation` string,
`line_item_product_code` string,
`line_item_resource_id` string,
`line_item_tax_type` string,
`line_item_unblended_cost` double,
`line_item_unblended_rate` string,
`line_item_usage_account_id` string,
`line_item_usage_account_name` string,
`line_item_usage_amount` double,
`line_item_usage_end_date` timestamp,
`line_item_usage_start_date` timestamp,
`line_item_usage_type` string,
`pricing_currency` string,
`pricing_lease_contract_length` string,
`pricing_offering_class` string,
`pricing_public_on_demand_cost` double,
`pricing_public_on_demand_rate` string,
`pricing_purchase_option` string,
`pricing_rate_code` string,
`pricing_rate_id` string,
`pricing_term` string,
`pricing_unit` string,
`product` map < string, string >,
`product_comment` string,
`product_fee_code` string,
`product_fee_description` string,
`product_from_location` string,
`product_from_location_type` string,
`product_from_region_code` string,
`product_instance_family` string,
`product_instance_type` string,
`product_instancesku` string,
`product_location` string,
`product_location_type` string,
`product_operation` string,
`product_pricing_unit` string,
`product_product_family` string,
`product_region_code` string,
`product_servicecode` string,
`product_sku` string,
`product_to_location` string,
`product_to_location_type` string,
`product_to_region_code` string,
`product_usagetype` string,
`reservation_amortized_upfront_cost_for_usage` double,
`reservation_amortized_upfront_fee_for_billing_period` double,
`reservation_availability_zone` string,
`reservation_effective_cost` double,
`reservation_end_time` string,
`reservation_modification_status` string,
`reservation_net_amortized_upfront_cost_for_usage` double,
`reservation_net_amortized_upfront_fee_for_billing_period` double,
`reservation_net_effective_cost` double,
`reservation_net_recurring_fee_for_usage` double,
`reservation_net_unused_amortized_upfront_fee_for_billing_period` double,
`reservation_net_unused_recurring_fee` double,
`reservation_net_upfront_value` double,
`reservation_normalized_units_per_reservation` string,
`reservation_number_of_reservations` string,
`reservation_recurring_fee_for_usage` double,
`reservation_reservation_a_r_n` string,
`reservation_start_time` string,
`reservation_subscription_id` string,
`reservation_total_reserved_normalized_units` string,
`reservation_total_reserved_units` string,
`reservation_units_per_reservation` string,
`reservation_unused_amortized_upfront_fee_for_billing_period` double,
`reservation_unused_normalized_unit_quantity` double,
`reservation_unused_quantity` double,
`reservation_unused_recurring_fee` double,
`reservation_upfront_value` double,
`resource_tags` map < string, string >,
`savings_plan_amortized_upfront_commitment_for_billing_period` double,
`savings_plan_end_time` string,
`savings_plan_instance_type_family` string,
`savings_plan_net_amortized_upfront_commitment_for_billing_period` string,
`savings_plan_net_recurring_commitment_for_billing_period` string,
`savings_plan_net_savings_plan_effective_cost` double,
`savings_plan_offering_type` string,
`savings_plan_payment_option` string,
`savings_plan_purchase_term` string,
`savings_plan_recurring_commitment_for_billing_period` double,
`savings_plan_region` string,
`savings_plan_savings_plan_a_r_n` string,
`savings_plan_savings_plan_effective_cost` double,
`savings_plan_savings_plan_rate` double,
`savings_plan_start_time` string,
`savings_plan_total_commitment_to_date` double,
`savings_plan_used_commitment` double,
`split_line_item_actual_usage` double,
`split_line_item_net_split_cost` double,
`split_line_item_net_unused_cost` double,
`split_line_item_parent_resource_id` string,
`split_line_item_public_on_demand_split_cost` double,
`split_line_item_public_on_demand_unused_cost` double,
`split_line_item_reserved_usage` double,
`split_line_item_split_cost` double,
`split_line_item_split_usage` double,
`split_line_item_split_usage_ratio` string,
`split_line_item_unused_cost` double
)
PARTITIONED BY (`billing_period` string)
ROW FORMAT SERDE 'org.apache.hadoop.hive.ql.io.parquet.serde.ParquetHiveSerDe'
WITH SERDEPROPERTIES ('serialization.format' = '1')
STORED AS PARQUET
LOCATION 's3://xxx/data'
TBLPROPERTIES (
'projection.enabled' = 'true',
'projection.billing_period.format' = 'yyyy-MM',
'projection.billing_period.interval' = '1',
'projection.billing_period.interval.unit' = 'MONTHS',
'projection.billing_period.range' = '2024-01,NOW',
'projection.billing_period.type' = 'date',
'storage.location.template' = 's3://xxx/data/BILLING_PERIOD=${billing_period}/'
)
3. Redashでダッシュボード作成
RedashからAthenaのクエリが実行できることを確認したら、クエリやダッシュボードを作成します。
表示項目は模索中ですが、レンティオでは下記の項目を表示しています。
- 先月との比較
- 日毎の使用タイプごとの料金
- 3ヵ月分のサービスごとの料金
4. Slackにリマインダーを設定
ダッシュボードのURLを投稿するリマインダーを設定します。
Redash Slack botについてはこちら
Redashで各クエリのRefresh Schedule
をリマインダーよりも前の時間に設定しておくことで、毎日最新のキャプチャがSlackに投稿されます。
おわりに
以上、コスト可視化の取り組みについての紹介でした。
この記事が参考になれば幸いです。
採用情報
レンティオでは絶賛、エンジニアを募集しています!
Discussion