blog

DeNAのエンジニアが考えていることや、担当しているサービスについて情報発信しています

2025.02.07 技術記事

EC2 インスタンスのコスト変化の調査にかかる負担を減らす取り組みについて [DeNA インフラ SRE]

by Kotaro Watanabe

#infrastructure #sre #aws

はじめに

こんにちは、IT 本部 IT 基盤部第三グループの渡邊です。 IT 基盤部では、組織横断的に複数のサービスのインフラ運用を行っており、インフラの安定的な稼働やコスト削減に取り組んでいます。

IT 基盤部は QCD の鼎立 1 をミッションに掲げており、チームカルチャーとして根付いています。

今回は、我々のグループが取り組んだコストコントロールの施策の一部である、EC2 インスタンスのコスト変化の調査にかかる負担を減らした事例についてご紹介します。

解決したい課題

2023年、私の所属する第三グループは新たにいくつかのサービスの運用を開始しました。これらのサービスはすでにローンチされており、1つのアカウント上で複数のサービスが稼働している状況でした。

運用開始当初は、コストコントロールに関する仕組みが整備されていなかったため、まずは定期的にコスト変化をレポートすることにしました。 AWS Lambda と AWS Cost Explorer を利用して、月初からレポートの通知日までの期間中に発生したコストと前月比を通知するシンプルなシステムを構築しました。サービスに関わるメンバーにコスト意識を持ってもらうため、関係者が含まれる Slack チャンネルに通知するようにしています。また、Slack チャンネルに通知されることで AWS Console へのログインの手間も省けます。

次の画像は実際に通知されているレポートです。

コストレポート

コストレポート

レポートができるようになったので、次はコスト変化の調査です。

定期的に通知されるレポートを分析したところ、とくに EC2 のコスト変化が激しいことがわかりました。EC2 のコスト変化には、負荷対策での一時的なインスタンス増減や PoC で使用したインスタンスの増減など、さまざまな要因が考えられます。

原因を特定し、コスト変化が妥当であるかを判断するためには、いつ、誰が、どのリージョンで、どのインスタンス(インスタンスタイプや OS プラットフォーム)をどのように操作し、どれぐらいのコストが発生しているかを調査する必要があります。

しかし、サービスやリージョンごとに開発メンバーが異なり、開発・運用のスタイル、使用している OS やツールもさまざまであったため、上記の情報を得るためにはかなりの労力を要しました。

この課題を解決するため、次は調査の負担を減らすための施策に取り組み始めました。

課題解決へのステップ

要件を整理する

まずはグループ内で議論し、要件を整理しました。

  1. いつ、誰が、どのリージョンで、どのような操作を行い、どのぐらいのコストが発生するかを一覧で表示できること
  2. システムにかかる金銭的なコストを低く抑えられること
  3. ローカル PC 上で調査できること

調査のしやすさを考慮し、普段からグループメンバーが CLI ツールを多用していること、共有環境の構築・維持にかかるコスト、ログインの手間を考えた結果、ローカル PC 上で調査を完結させる方針に決定しました。

調査プロセスを分解する

次に調査に必要なステップを分解しました。データソースには AWS CloudTrail を使用します。

  1. 調査対象のリージョンを指定する
  2. 前月からレポートの通知日までの期間を指定する
  3. 属性キーに「イベント名」を指定し、値に EC2 の操作イベントを1つ指定する
  4. 結果から、イベントを発生させた日付、人物、システムを特定し、記録する
  5. 1 ~ 4 を取得したいイベント、利用しているすべてのリージョンで繰り返す
  6. 集めた情報を元にコストを計算する

取得したい EC2 の操作イベントには次の値を指定します。

ブログ執筆時点では、1つの属性キーに対して複数の値を設定できない 2 状況であるため、取得したい操作イベント分の処理を繰り返し実行する必要があります。

整理した要件と分解した調査プロセスを元に、調査の負担を減らすためのシステムを構築します。

システムの構築

最終的に次のシステム構成になりました。

コストモニタリング アーキテクチャ

コストモニタリング アーキテクチャ

使用した AWS リソースは次の通りです。

システム構成について解説します。

RDS

RDS は発生したイベントを永続化するために使用します。

CloudTrail のイベント履歴は過去90日間までしか参照できないため、直接利用すると分析できる期間が限定されてしまいます。また、証跡も記録していますが、アカウント運用の都合上、特定のメンバーしか閲覧が許されていません。

以上の理由から、RDS でイベントデータを永続化することにしました。

RDS には次の4つのテーブルを作成しています。

  1. 資産管理テーブル
  2. イベント履歴管理テーブル
  3. リージョン管理テーブル
  4. 価格管理テーブル

リージョン管理テーブルは、使用中の リージョンを特定するために使用します。

価格管理テーブルは、履歴を元にコスト計算を行うときに使用します。 このテーブルには AWS Price List APIs で取得できるデータを元にインスタンスタイプ、リージョン、OS プラットフォームごとの料金を保持しています。

すでにグループ内で料金取得のためのスクリプトを作成していたので、そちらを流用しました。 価格管理テーブルを作成することで API へのリクエスト/レスポンスに関する複雑な実装を省略でき、単純な SQL を実行するだけで料金を取得できるようにしています。

データベースの認証については、データベースのパスワード管理の手間を省くために IAM データベース認証 を採用しています。

batch 用 Lambda

batch 用 Lambda は、先述の RDS の資産管理テーブルとイベント履歴管理テーブルに対してイベントデータの追加・更新処理を行います。

EventBridge に設定されたイベントスケジュールをトリガーに起動した Lambda は、RDS から使用中の リージョンを取得します。 取得した リージョンと EC2 の操作イベントをパラメーターに設定して CloudTrail の LookupEvents API に対してリクエストします。

リクエストが正常に成功した場合、次のデータ構造でレスポンスされます。 Lambda は後続の処理として “Events” をパースして RDS の資産管理テーブルとイベント履歴管理テーブルに追加・更新処理を実行します。

{
   "Events": [
      {
         "AccessKeyId": "string",
         "CloudTrailEvent": "string",
         "EventId": "string",
         "EventName": "string",
         "EventSource": "string",
         "EventTime": number,
         "ReadOnly": "string",
         "Resources": [
            {
               "ResourceName": "string",
               "ResourceType": "string"
            }
         ],
         "Username": "string"
      }
   ],
   "NextToken": "string"
}

LookupEvents API は1度のリクエストで最大50件までしかデータを取得できず、次のページを取得するにはレスポンスに含まれる NextToken を使用しつつ、前回のリクエスト時の AttributeKeyAttributeValue パラメーターの値を揃えてリクエストする必要があるため注意が必要です。

batch 用 Lambda には上記の処理を再帰的に実行するよう実装しています。

API Gateway と api 用 Lambda

過去のブログ でも紹介されている通り、DeNA では AWS Transit Gateway AWS Direct Connect を使用して社内ネットワークと AWS 間の内部接続を実現しています。

しかし、今回はネットワークの設計が普段と異なる環境であったため、内部通信を行うことができず、ローカル PC からの実行を行うという要件を満たすためにはインターネット経由でアクセスする必要がありました。

セキュリティの観点から RDS を外部アクセス可能な Public Subnet に配置するのは避けたかったので、API Gateway へのリクエストをトリガーに api 用 Lambda を起動して RDS にクエリを実行し、データを整形して返す構成をとりました。

API Gateway では アクセスコントロール の手段が3つ提供されています。

  1. Lambda オーソライザー
  2. JWT オーソライザー
  3. AWS IAM Role と Policy

DeNA では全社的な SSO の仕組みが用意されている3ので、実装が容易であることから IAM Role によるアクセスコントロールを採用しました。

api 用 Lambda には batch 用 Lambda で RDS に追加・更新したデータを元に「コスト変化の履歴の取得」するための処理を実装しています。 API Gateway へのリクエストをトリガーに起動し、RDS に保存されているデータを取得して json データを返すシンプルな実装です。

batch, api 用 Lambda のログは CloudWatch Logs に蓄積しています。

ローカル PC 上で実行するスクリプト

スクリプトの実行者は自身の PC 上で認証を行い、一時的なクレデンシャルを取得したあとリクエストが可能となります。

レスポンスを受け取ったスクリプトは、取得したデータをパースして表示します。

サンプルとはなりますが、次のような表示になります。 *** にはイベント発生時刻から --end で指定された日付の前日までのコストを計算して表示されます。

$ costcli history --start 2025-01-01 --end 2025-01-10
Time Period: 2025-01-01 to 2025-01-10
Cost Effect: $***
+----------------+-------------+----------------+----------+-----------------+-----------------------+------------------------------------+---------------------+-----------------+
| Instance Name  | Instance ID | region         | Platform | Triggered By    | Event                 | Event Detail                       | Event Date (UTC)    |  Cost Effect($) |
+================+=============+================+==========+=================+=======================+====================================+=====================+=================+
| test-instance  | i-aabbcc    | ap-northeast-1 | linux    | kotaro.watanabe | change_instance_state | stopped -> terminated ( t3.small ) | 2025-01-09T06:12:42 |             *** |
+----------------+-------------+----------------+----------+-----------------+-----------------------+------------------------------------+---------------------+-----------------+
| test-instance2 | i-ddeeff    | ap-northeast-3 | windows  | kotaro.watanabe | create_instance       | c5a.large                          | 2025-01-09T12:16:40 |             *** |
+----------------+-------------+----------------+----------+-----------------+-----------------------+------------------------------------+---------------------+-----------------+
| test-instance3 | i-gghhii    | us-west-2      | linux    | kotaro.watanabe | change_instance_type  | c5.large -> c6a.large              | 2025-01-09T17:07:30 |            -*** |
+----------------+-------------+----------------+----------+-----------------+-----------------------+------------------------------------+---------------------+-----------------+

金銭的コスト

主なコストは RDS の運用コストとスケジュールによって起動する batch 用 Lambda、調査時に実行される API Gateway と api 用 Lambda の4つです。

API Gateway は API コールと転送データ量の従量課金であり、Lambda の実行に必要なスペックを必要最小限に、 RDS も必要最小限のスペックを使用しています。

以上から金銭的なコストに関しても最小限の構成となっています。

解説は以上となります。

このシステムの導入により、EC2 のコスト変化が生じた際、各人のローカル PC 上でスクリプトを実行するだけで調査を完了させることができるようになり、状況の確認と対応を即座に依頼できるようになりました。

おわりに

今回は、我々のグループが取り組んだコストコントロールの施策の一部である、EC2 インスタンスのコスト変化の調査にかかる負担を減らした事例について紹介させていただきました。

今後もコストコントロール、運用の負担の軽減といった観点での課題解決や運用改善を進めていきます。


  1. システムの Quality・Cost・Delivery ↩︎

  2. Viewing recent management events with the AWS CLI  ↩︎

  3. AWS アカウントの DeNA 的管理手法(スイッチロール補助編)  ↩︎

最後まで読んでいただき、ありがとうございます!
この記事をシェアしていただける方はこちらからお願いします。

recruit

DeNAでは、失敗を恐れず常に挑戦し続けるエンジニアを募集しています。