CloudWatch の GetMetricData API の料金が高い時はサードパーティの監視ツールを使っていないか確認しよう

GetMetricData API 呼び出しは CloudTrail に記録されないため呼び出し元は直接は確認できません。呼び出しが大量の場合はサードパーティの監視ツールによるものでないかをまず確認しましょう。

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

コンバンハ、千葉(幸)です。

CloudWatch の料金がなんかずっと高い、という相談をお客様よりいただいたケースがありました。

改めてコストの見直しをかけたところ CloudWatch の月額料金が高止まりしており、特に$0.01 per 1,000 metrics requested using GetMetricData API - Asia Pacific (Tokyo)が月に 200 USD 程度 発生している、という状況でした。

CloudWatchGetMetricData

ひとまずこのGetMetricDataAPI を実行しているのは誰だと CloudTrail から調査したくなりますが、この API の呼び出しは CloudTrail に記録されません。

結果的に当該 API コールはサードパーティの監視ツールによるものだと判明したのですが、調べた過程のもろもろをまとめておきます。

先にまとめ

  • GetMetricDataの API 呼び出しは CloudTrail イベントに記録されない
  • GetMetricDataによる料金が高い場合、サードパーティの監視ツールによるものであるケースが多い
  • ツールが対応しているのであれば CloudWatch Metric Stream への変更も検討しよう

GetMetricData API にかかる料金が高い!

繰り返しになりますが、今回のケースでは CloudWatch の GetMetricData API の呼び出しで 200 USD/月 程度コストが生じていました。

料金の内訳 を確認してみると、東京リージョンの場合以下となります。

  • リクエストされた 1,000 件のメトリクスごと 0.01USD

CloudWatch_data_cost

ここで注意していただきたいのは、基準となるのは「API コール数」ではなく「リクエスト対象のメトリクス数」であることです。

GetMetricDataでは一度の API コールで最大 500 のメトリクスを取得できます。500 のメトリクスを指定して GetMetricDataを 2回実行した場合、それだけで 0.01 USD のコストが発生するということです。

冒頭の例ではひと月で 2,000 万強のメトリクスをリクエストしていました。

GetMetricData API は CloudTrail イベントとして記録されない

GetMetricData API 呼び出しによるコストが多く発生している、では果たして誰がそれを呼び出しているのか?その調査は一筋縄ではいきません。

こういったケースでまず第一に思い浮かぶのは CloudTrail のイベント履歴を確認することですが、GetMetricDataは CloudTrail の記録対象外なのです。

CloudWatch のアクションのうち、CloudTrail の記録対象となっているものは以下ドキュメントから確認できます。

CloudWatch のアクションの全量から考えると記録対象であるものの方が少ないです。そんな話を以下のエントリで書きましたのであわせてご参照ください。

GetMetricData API コールによる高コストはサードパーティツールの可能性高し

CloudTrail から確認できないのであればどうしたらいいのか……?そんなときに参考になるソースがありました。

以下の AWS フォーラムでの投稿で、今回と同様に「GetMetricData API による高コストが発生しているので呼び出し元を確認したい」という内容でした。

フォーラム内で AWS の中の人からの回答があったため、機械翻訳した結果を引用します。(原文は上記リンクからご参照ください。)

AWSフォーラムに投稿していただきありがとうございます。GetMetricDataの請求額が非常に高いことを理解しており、その理由を知りたいと思います。

残念ながら、GetMetricDataのソースをチェックするためのツールはありません。その理由は、このAPI呼び出しがCloudTrailに記録されていないためです。

したがって、それを確認するには、AWSのテクニカルサポートチームに連絡する必要があります。このチームは内部チームに連絡し、内部チームはこれらのAPI呼び出しのソースを見つけるためにログダイビングを行います。

ただし、その前に、これらのAPI呼び出しの高額な請求は、通常、DataDog、Splunkなどのサードパーティツールが原因であることをお知らせします。その理由は、これらのサードパーティツールは1分あたりのAPI呼び出しの数が多く、結果として高額になるためです。DataDogが顧客に非常に高い請求をもたらすケースをたくさん見てきました。

したがって、AWSの技術チームに懸念を表明する前に、DataDogなどのサードパーティのモニタリングツールを使用していないことを確認してください。

実際にDataDogを使用している場合は、DataDogサポートに連絡して、実行されるAPI呼び出しの数を減らすことができるかどうかを尋ねる必要があります。

サードパーティツールが原因であることが多い、とされています。テクニカルサポートチームに問い合わせることで GetMetricData API の呼び出し元を確認できる可能性があるものの、その前段としてサードパーティのモニタリングツールの使用有無を確認しておく必要がある、とのことです。

今回のケースでは「何かサードパーティの監視ツール使用されてますか?」とお客様にヒアリングしたところまさに使われていたので、この段階でほぼほぼ原因の特定に至りました。

他のアプローチでの確認

CloudTrail から 他の API コールを確認してみる

概ね原因が特定できたものの、もう少し土台固めをしてみようということで他のアプローチで調査を続けてみます。

GetMetricDataは CloudTrail には記録されませんが、同じ実行元が他の API を呼び出しているかもしれません。

イベントソースとしてCloudWatch のサービスエンドポイントであるmonitoring.amazonaws.comを指定してフィルタリングしてみると、DescribeAlarmHistoryを定期的に呼び出している実行元を確認できました。

CloudTrail_Management_Console_Integration

実行元がサードパーティツールのインテグレーション(連携)用の IAM ロールであったため、原因特定の判断材料として役立ちました。

余談ですが、ユーザー名としてこの IAM ロール(のセッション名)を指定してイベントをフィルタリングすると、各種サービスの Get や List を行なっている様子が確認できました。

AWS/Usage の CallCount メトリクスをみてみる

API コールの実行元は確認できませんが、実行数は CloudWatch メトリクスから確認できます。名前空間AWS/UsageCallCountメトリクスが該当します。

日本語のマネジメントコンソールでは「使用」というグループで表現されています。Serviceディメンションで CloudWatch を指定してフィルタリングすれば、CloudWatch サービスの API コール数だけを確認できます。

CloudWatch_Management_Console_Usage

GetMetricDataAPI の1日あたりのコール数を確認してみると、おおよそ3,700 ほどでした。今回の例ではひと月で 2,000 万強のメトリクスがリクエストされていたため、2,000 万 / ( 3,700 * 30日)で 1回の API コールあたりのリクエストされたメトリクス数が約 180 であることが分かりました。

CloudWatch_Management_Console_Usage_Callcount

少し本題からずれますが、API コール数に応じて料金が発生するメトリクスについてもここからカウントを確認できます。

Metrics_API_CallCount

CloudWatch Metric Streams への乗り換えも検討しよう

ここまで見てきたGetMetricDataAPI は、サードパーティツールによる呼び出し(ポーリング)の形式でした。CloudWatch から見ればプルされる形です。それに対して CloudWatch 側からプッシュする CloudWatch Metric Streams という仕組みもあります。

一定間隔のポーリングではなく値が更新されたタイミングでのストリーミングのため、レイテンシが低く抑えられます。加えて、GetMetricDataAPI と料金の形態が異なるため、コストを削減できる可能性もあります。

  • GetMetricData 形式
    • リクエストされた 1,000 件のメトリクスごと 0.01USD
  • CloudWatch Metric Streams 形式
    • 更新された 1,000 件のメトリクスごと 0.003 USD
    • Kinesis Data Firehose の利用料金(取り込みデータ量 1GB あたり 0.036 USD より)
    • 場合によってはプラスアルファ(クロスリージョンの場合のデータ転送料金や Firehose でデータ変換をする場合の料金)

ものすごく雑に考えると、GetMetricDataAPI が1回呼び出される間隔と CloudWatch Metric Stream によって値が更新される間隔が同じであれば後者の方が安くなりそうです。その割合が 1:3 くらいまでであれば、まだ後者の方にメリットが出そうです。

このあたりの間隔などはサードパーティツール側の仕様によりそうなので、採用の前に確認することをお勧めします。

終わりに

CloudWatch の GetMetricData API による料金が高い場合、サードパーティの監視ツールが原因である可能性が高いため確認してみよう、という話でした。

CloudTrail で呼び出し元を確認できないのがつまづきポイントですが、他のアプローチも踏まえつつまずは監視ツールが原因であると仮定して調査してみるとよいでしょう。もちろんサードパーティツールによるものではなく自前で作り込んだスクリプトが原因の場合もあるかと思います。

今回は取り上げませんでしたが、IAM ユーザーや IAM ロールの最終アクティビティを確認して定期的にアクティビティを行なっているものを洗い出す、アクセスアドバイザーから Amazon CloudWatch サービスへのアクセスが行われているものを絞り込む、というアプローチも有効かと考えます。

なんか CloudWatch の料金高いな……という場合の参考になれば幸いです。

以上、 チバユキ (@batchicchi) がお送りしました。

参考