はじめに
Terraformの.tfファイルをアップロードするとAWSの月額コストを概算してくれるツール(tf-cost-estimator)を個人開発で作っています。
もし使ってみて不具合や気になる点があれば、GitHub Issuesで教えてもらえると助かります。
AWS Price List Bulk APIを使う
AWSにはPrice List Bulk APIというものがあります。認証もアカウントも要らず、curlで叩けばそのままJSONが返ってきます。
curl -s https://pricing.us-east-1.amazonaws.com/offers/v1.0/aws/index.json | jq '.offers | keys'
これでサービスコードの一覧が取れます。EC2はAmazonEC2、VPCやTransit GatewayはAmazonVPC、という具合です。あとは欲しいサービスと東京リージョンを指定するだけ。
curl -s https://pricing.us-east-1.amazonaws.com/offers/v1.0/aws/<ServiceCode>/current/ap-northeast-1/index.json
これでSKU単位の正確な単価が手に入ります。
ハマったポイント
EC2(AmazonEC2)のファイル、442MBあります。timeoutを長めに取っておくのが無難です。
timeout 300 curl -s https://pricing.us-east-1.amazonaws.com/offers/v1.0/aws/AmazonEC2/current/ap-northeast-1/index.json -o ec2_price.json
あとNAT GatewayやENIみたいな、見た目VPC寄りのリソースがなぜかAmazonEC2側に紛れ込んでいたりします。見つからなかったら疑ってください。
この巨大なファイル、同じサービスの中で何件も単価を調べたい時(EC2だけで40種類以上のインスタンスタイプを調べるとか)、毎回律儀にダウンロードし直すと面倒なのでサービスごとに1回だけ取得してスクリプトの実行中だけメモリ上に持っておき、そこから必要な分を読み出すようにすれば、ダウンロードは1回で済みます。
downloaded = {} # サービスコード → 取得済みのJSON
def get_price_data(service_code):
if service_code not in downloaded:
downloaded[service_code] = fetch_json(service_code) # ダウンロードするのは初回だけ
return downloaded[service_code]
for instance_type in ["t3.micro", "t3.small", "m5.large", ...]: # 40種類以上
data = get_price_data("AmazonEC2") # 2回目以降は辞書から即座に返る
price = extract_price(data, instance_type)
その後
今はこの仕組みをもう少し発展させて、料金定数とAPIの対応表をマニフェストにまとめ、GitHub Actionsで月1回勝手に最新価格と照合させています。その話はまたいずれ記事にしようと思います。
とりあえず、AWSの料金をコードから正確に扱いたくなったら、Web検索よりまずこのAPIを試してみてください。