AWS明細データの歩き方 - Sanwa Systems Tech Blog
こんにちは、AWS 担当のwakです。今年もよろしくお願いいたします。ずいぶん間が空いてしまいましたが、今年はペースアップしていこうと思います。
今年は猫年(だったはず)
AWS 料金明細データ
さて、今回はAWS の利用料金明細データの話をします。AWS の現時点での料金、過去数ヶ月の料金などは
請求ダッシュボード
、
AWS Cost Explorer
などで参照することができますが、この元となる詳細なデータは、事前に「リソースとタグを含む詳細な請求レポート」を出力するように
設定
しておくことでS3にCSV ファイルとして出力することができます。
このファイルは
999999999999-aws-billing-detailed-line-items-with-resources-and-tags-2019-01.csv.zip
という書式の名前のzipファイル*1 で、費目・1時間ごとに1行記載される形となっています。たとえばEC2を1ヶ月起動していると、1時間ごとに
EC2の利用料金
EC2のネットワークI/O料金(IN)
EC2のネットワークI/O料金(OUT)
EBSの利用料金
の4行*2 が発生し、1ヶ月=720時間では数千行に達します。今回はこのファイルを細かく集計してみたい人に向けて明細データの読み方について書きます。
ファイル概要
標準的なカンマ区切りのテキストファイル(UTF-8 エンコーディング 、改行はLF)です。数値を含め、全てのフィールドはダブルクオートでくくられています。また "$0.0037 per 10,000 GET and all other requests"
のようにカンマを含むフィールドが多数存在するため、ダブルクオートを無視してカンマ区切りで読み込もうとすると悲しいことになります。awk などで処理したい場合は ","
を区切り文字とすれば良いでしょう。
記載されている内容
毎月月初にAWS から請求書(PDF形式)がメールで届きますが、明細データにはこの1ヶ月分の請求書の内容がまとめて出力されています。RIを購入した場合は別途請求が発生するのでこちらには含まれません。
カラム数は固定(ただし設定次第)
カラム数は固定です。ただし一括請求を有効にすると Rate
, Cost
カラムは BlendedRate
, BlendedCost
, UnBlendedRate
, UnBlendedCost
カラムになります(後述)。
また、「コスト配分タグ」でタグ(たとえば IsDev
タグと Project
タグ)を追加すると、行の末尾に user:IsDev
, user:Project
カラムが追加されます(アルファベット順にソートされるようです)。このタグの値をもとに
AWS Cost Explorer
などで料金を集計することができます。設定を変更するとカラム数も変わってしまいます。
請求書番号
明細データの最初のカラムは InvoiceID
で、請求書の上部に記載されているInvoice Numberが書いてあります。月の途中の場合は請求書がまだ発行されていない(=Invoice Numberが確定していない)ため全ての行で "Estimated"
になります。
レコードID
各行には RecordId
というフィールドがあり、行ごとにユニークな値が振られています。IDは整数形式ですが、 155050012134381272590339883
(=1.55*1026 、287 ) のように非常に大きな値で、かつレコード間で差が10~20前後しかないものがあるので、大抵の場合は文字列として扱う必要があります(64bitのfloat型などではまるで精度が足りません)。
末尾には特殊な行がある
ファイルの末尾には
を記載した行があります。集計する場合はここを考慮する必要があります。(料金総額は除いておく、サポート・消費税は利用料金に含めておくなど)
レコードの内容
具体的に1レコード(1行)の内容を見ていきます。
# カラム名 概要
1 InvoiceID 前述。請求書に書いてあるInvoice Number
2 PayerAccountId 料金を支払うアカウントのアカウント番号
3 LinkedAccountId 料金を発生させたアカウントのアカウント番号。一括請求を使わない場合は(2)と同じ
4 RecordType ほとんどが"LineItem"(後述)
5 RecordId 前述。レコードに振られたユニークなID
6 ProductName プロダクト名。 "Amazon Simple Storage Service"、"AWS Lambda" など
7 RateId -
8 SubscriptionId -
9 PricingPlanId -
10 UsageType 費目1
11 Operation 費目2
12 AvailabilityZone AZ名
13 ReservedInstance RIが適用されているなら"Y"、そうでないなら"N"
14 ItemDescription この行の説明
15 UsageStartDate この行のタイムスタンプ("2019-01-02 03:00:00"の書式。1時間単位)
16 UsageEndDate 同上(その1時間後)
17 UsageQuantity 使用量
18 BlendedRate 単価1。後述
19 BlendedCost 料金1((17)×(18)に等しい)
20 UnBlendedRate 単価2。後述
21 UnBlendedCost 料金2((17)×(20)に等しい)
22 ResourceId リソースIDまたはARN
23以降 user:XXXX 出力するように設定したタグの値
RecordType
について
実際の料金が記載された行(ほとんどがこれ)は LineItem
となっています。集計に使う場合は LineItem
の行だけ抜き出せばいいです。それ以外の行はファイル末尾にしかありません。
UsageType
について
あまり綺麗なデータではありません。たとえばEC2に限っても、 APN1-BoxUsage
, APN1-BoxUsage:m5.large
, APN1-EBSOptimized:m5.large
のようにインスタンス サイズがあったりなかったりします。
末尾のタグについて
たとえば Project
というタグを指定した場合、23カラム目にはその行のリソース(EC2インスタンス 、RDSインスタンス 、S3バケット ……)の Project
タグの値が入ってきます。
すべてのレコードにこのタグが出力されるわけではありません。タグを付け忘れたリソースの行にはもちろん空文字が入ります。また(徐々に対応するサービスが増えてはいますが)2019年1月現在、CloudWatchやAPI Gateway にはタグを付けることができないため、ここは空文字が入ります。別途 ProductName
, ResourceId
で集計するなどの工夫が必要になります。
(Un)BlendedCost
, (Un)BlendedRate
について
AWS の料金のほとんどは使えば使うほど割安になっていきます。たとえば2019年1月現在、東京リージョンのS3標準ストレージの料金(ストレージ使用分)は次の通りです。
最初の50TBまでは $0.025/GB・月
次の450TBまでは $0.024/GB・月
500TB以上は $0.023/GB・月
ではアカウントが2個(A・Bとします)あり、それぞれS3を100TBずつ利用しており、さらに一括請求を利用している場合の料金はどうなるでしょうか。
公式ドキュメント
によれば、1個のアカウントで200TBを使ったときと同じ料金になります。つまり、
最初の50TB分($0.025×50,000=$1,250)
残りの150TB分($0.024×150,000=$3,600)
で合計 $4,850 ということになります。
ところが明細データはアカウント別にレコードが出力されますので、これを無理やりアカウントAとBに分けなければなりません。そこで、明細データの上では
便宜上 アカウントAで最初の50TBを利用($0.025×50,000=$1,250)
アカウントAで残りの50TBを利用($0.024×50,000=$1,200)
アカウントBでさらに100TBを利用($0.024×100,000=$2,400)
というデータが出力されます(AとBどちらが選ばれるかは謎です)。ここで適用される単価が UnBlendedRate
で、それをもとに算出された料金が UnBlendedCost
です。しかし、まったく同じようにS3を使っているのにアカウントAとBで料金が違う(ように算出される)のでは困ります。そこで、一括請求を前提としてこれを平準化した単価が BlendedRate
、それをもとに算出された料金が BlendedCost
です。
UnBlendedRate
, UnBlendedCost
の良いところは、単価がAWS の公表しているものと一致しているので検証しやすいことです。悪いところは実態と合わない(アカウント・リソース間で割引の有無の差異が発生して料金に差が出てしまう)ことです。総額は一致するので、どちらか使いやすい方を選びましょう。
EC2 RIについて
EC2 RIについても触れておきます(以下、OSはすべてLinux とします)。
サポート利用料は月の請求に載る
RIを購入するたびに別途請求書が発行され、支払いはその都度行います。しかしサポート料金*3 は月の料金に応じて決まるため、サポート利用料は月ごとの請求書の方に載ります。ここを忘れていると、RIで高額な支払いを済ませた翌月に料金が跳ね上がっていてびっくりすることになります。
RIは特定のインスタンス に紐付くわけではない
RIはあくまで「特定のインスタンス タイプのインスタンス を安く利用できる仕組み」です。さらに(ありがたいながらも)ややこしいことに、
RIの柔軟性
という仕組みがあります。これがどういうことが例示します。
まず m3.2xlarge の全額前払いRIを4個購入したとします。また、
m3.2xlarge のインスタンス A, B, C, D
m3.xlarge のインスタンス E (※料金は m3.2xlarge の50%)
m3.medium のインスタンス F, G (※料金は m3.2xlarge の12.5%)
を起動していたとします。
RIは1時間ごとにA~Gの いずれか に適用されます。したがって、
というケースもありますが、
A~CにRIが3個分適用される(A, B, Cは無料になる)
残る1個のRIが次のように分配される
Dには25%分適用される(Dの料金は25%引きになる)
E には50%分適用される(Eの料金は m3.2xlarge の50%なのでEは無料になる)
F, G にはそれぞれ12.5%分適用される(F, Gの料金は m3.2xlarge の12.5%なのでF, Gは無料になる)
ということもあり得ます(いずれも料金の総額は変わりません)。後者の場合、次のようなレコードが出力されます。
ResourceId ItemDescription(概要) ReservedInstance UsageQuantity UnBlendedRate
A m3.2xlargeのRI適用 Y 1 0
B m3.2xlargeのRI適用 Y 1 0
C m3.2xlargeのRI適用 Y 1 0
D m3.2xlargeのRI適用 Y 0.25 0
D 標準料金 ($.077/h) N 0.75 0.77
E m3.2xlargeのRI適用 Y 1 0
F m3.2xlargeのRI適用 Y 1 0
G m3.2xlargeのRI適用 Y 1 0
インスタンス E, F, Gのインスタンス タイプは m3.xlarge, m3.medium なのに( UsageType
カラムにはそれぞれ APN1-BoxUsage:m3.xlarge
, APN1-BoxUsage:m3.medium
と書いてあります)、 ItemDescription
には「m3.2xlargeのRIを適用した」と書いてあるのがポイントです。
BlendedRate
, BlendedCost
はRIでも働いていて、こういった料金を平準化した料金が記載されています。
調整したい場合は?
とはいえ、「自分はこのインスタンス の料金を前払いしたんだ」という気持ちでRIを購入することもあるでしょう(たとえば上のケースですとインスタンス A~Dの料金を常に0とし、E~Gの ReservedInstance
が Y
となっている行に標準料金を加算したいといった感じです)。そのような場合は、
RIの柔軟性 に記載されているインスタンス サイズと係数のテーブル
UsageType
カラムに記載されているそのインスタンス のサイズやOSから求めた標準料金
ItemDescription
カラムに記載されている適用されたRIのタイプとサイズ
などを組み合わせて求める形に修正してやる必要があります。非常に面倒なのでオススメはしません……
スナップショットの料金
EBSのスナップショットはS3に保存され、1時間ごとにストレージ利用料金が加算されていきます。 ResourceId
カラムにはスナップショットのARNが記載されています:
arn:aws:ec2:ap-northeast-1:999999999999:snapshot/snap-0123456789abcdef0
2019年1月時点では、AMIを作成した際に生成されるスナップショットにはタグが付きません(手動で追加することはできます)。タグの値が空ですとこのスナップショットの正体が分かりません。料金がどのEBSから発生したものかを知りたければ、このARNからスナップショットを取得して作成元のEBSを特定する必要があります。しかし、AMIやスナップショットを定期的に作成・削除するような運用をしている場合、料金集計をしようとした時点では既にそのスナップショットが存在しないということがあり得ます。AMI/スナップショットを作るたびにタグを追加するか、Snapshot IDとEBS Volume IDの対応表を定期的に取得して保存しておくような処理を仕込んでおくと良いでしょう(LambdaとDynamoDBを使うと楽です)。
RDSのストレージ利用料金
RDSのバックアップに利用しているストレージ利用料金は、(なぜか)それがどのインスタンス のものかは分からず、 ResourceId
が空文字になります。これはどうしようもないので、
ResourceId
が空文字以外のものについてRDSの料金を集計する
RDSの利用料金に応じてストレージ利用料金を按分する
という手で振り分けてしまうのがいいと思います。
集計!
というわけで、たとえば Project
というタグの値に基づいて明細データの料金集計をしたい場合、次のような流れになります。
zipファイルをS3から取得、解凍
RDSやRなどに読み込む
RecordType
が LineItem
の行だけ抜き出す
Cost
または BlendedCost
の値を user:Project
の値に応じて合算する
user:Project
の値が空文字のレコードについては2パターンがある(タグを付けるのを忘れていたもの、タグを付けられないもの)
タグを付け忘れていたものについてはデータ修正を行って再集計する
それ以外のものは ProductName
, ResourceId
の値に応じて Cost
または BlendedCost
の値を合算する
以上、明細データの見方についてハマりやすいところを簡単にまとめてみました。正しくコストを把握して正しくAWS を利用していきましょう。今年もよろしくお願いします。
引用をストックしました
ストック一覧を見る
閉じる
引用するにはまずログインしてください
ログイン
閉じる
引用をストックできませんでした。再度お試しください
閉じる