ちょっと話題の記事

AWS Config の料金がなぜこんなに高い? Amazon Athena でどのリソースが Config の記録対象になっているか調べてみた

AWS Config の configuration item recorded の内訳をマネジメントコンソールから確認するのは骨が折れます。 Amazon Athena でクエリしてお手軽に確認しましょう。 だいじょうぶ Athena こわくない。

うわっ… Config の料金、高すぎ…?


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

AWS Config では、記録された設定項目(configuration item recorded)ごとに 0.003 USD かかります。(2021年9月時点の東京リージョンの場合。)

リソースの新規作成や設定変更、削除が頻繁に行われる環境では意図せず料金が膨らむ場合もあります。


▲ 過去に見たことがある Config の料金が爆発した例


AWS Config のダッシュボードではその時点で記録対象となっているリソースの数を確認できますが、既存のリソースに設定変更が多く発生している・あるいは作成/削除が繰り返されている場合には、設定項目数の内訳を確認するのは難しいです。

そのようなケースにおいて、 S3 バケットに出力された Config のスナップショットファイルを Athena で分析することで対象を特定できるため、手順を確認してみることにしました。

ほぼほぼ以下の内容をなぞったものになっています。

今回の登場人物

この方々です。

# 登場人物 説明
1 Config レコーダー どのリソースを記録するかの定義をしている
2 Config 配信チャネル どの S3 バケットに出力するかの定義をしている
3 Config 出力先 S3 バケット #2 から出力された履歴、スナップショットが格納されている
4 Athena #3 の中身をクエリしよう!
5 Athena 出力先 S3 バケット #4 の結果が格納される

わたしの検証環境で試していきます。

Config の設定確認

AWS Config 配信チャネルで、出力先の S3 バケットがどこであるか確認しましょう。

普段独立したリソースとして意識する機会は少ないと思いますが、マネジメントコンソールで以下から確認できる部分は配信チャネルの設定を表しています。

AWS_Config_Athena

S3 バケットに格納されたオブジェクトの URI の例は以下です。

s3://バケット名/AWSLogs/アカウント番号/Config/ap-northeast-1/2021/9/24/ConfigSnapshot/ファイル名.json.gz

ちょっとした気づきですが、yyyy/mm/dd形式になっていません。2021/09/24のように月や日を 2 桁に揃えてくれるわけでなく、元の数字が 1 桁のままであればそのまま 1 桁です。

Athena のクエリ結果の出力先 S3 バケットの作成

今回は初めて Athena を利用するケースを想定し、順番に進めていきます。

後ほど出力先設定が必要となるので、あらかじめ適当なバケットを用意しておきましょう。Athena を利用するリージョンと同じリージョンに用意してください。

クエリを実行する AWS エンティティ( マネジメントコンソールを操作する IAM ユーザーや IAM ロール)が S3 にアクセスできれば良いので、 Athena 特有のバケットポリシーなどは必要ありません。

既存のものを使用するのであればそれでも大丈夫です。

Athena のセットアップ

Athena のサービス画面に移動します。「クエリエディタ」という画面で操作することになるので、進みます。

Athena1

デフォルトで用意されているワークグループprimaryに遷移します。ワークグループは、Athena における一番でかい箱だと思ってください。

最初のクエリを実行する前に、Amazon S3 でクエリ結果の場所を設定する必要があります。という注意書きがあります。設定を進めないとクエリが実行できないため、設定画面に移ります。

Athena2

ワークグループprimaryとしての、クエリ結果の出力先 S3 バケットの設定をします。

Athena3

先ほど用意した出力用バケットを選択して保存すればOKです。

Athena4

これで最初の準備ができました。

Athena テーブルの作成

テーブルを作成していきます。クエリエディタに以下をペーストし実行してください。なお、ハイライト部のロケーションは環境に合わせて修正してください。

CREATE EXTERNAL TABLE awsconfig (
         fileversion string,
         configSnapshotId string,
         configurationitems ARRAY < STRUCT < configurationItemVersion : STRING,
         configurationItemCaptureTime : STRING,
         configurationStateId : BIGINT,
         awsAccountId : STRING,
         configurationItemStatus : STRING,
         resourceType : STRING,
         resourceId : STRING,
         resourceName : STRING,
         ARN : STRING,
         awsRegion : STRING,
         availabilityZone : STRING,
         configurationStateMd5Hash : STRING,
         resourceCreationTime : STRING > > 
) 
ROW FORMAT SERDE 'org.apache.hive.hcatalog.data.JsonSerDe' LOCATION 's3://バケット名/AWSLogs/アカウント番号/Config/リージョン/2021/';

↑ハイライト部には初めに確認した Config の出力先バケットとプレフィックスを指定します。わたしは2021というプレフィックスまで指定しましたが、より広くしても狭くしても問題ありません。

実行すると、先頭行で指定しているawsconfigという名称でテーブルが作成されました。特に指定をしていないためdefaultというデータベースの中にテーブルが作成されています。

Athena5

以降のクエリではdefault.awsconfigという形でデータベースおよびテーブル名を指定しますが、別の名称で作成された場合には適宜読み替えてください。

Athena のスキャン対象のサイズはどのくらい?

Athena の料金はクエリ実行時にスキャンしたデータサイズによって変動します。東京リージョンでは スキャンされたデータ 1 TB あたり 5.00 USD です。

参照系のクエリ実行時には、テーブル作成時に指定した S3 バケットのプレフィックス配下をすべてスキャンすることになります。

わたしの環境でのサイズを確認すると、およそ 28.2 MiB でした。以降のクエリ実行では、都度このサイズをスキャンすることになります。

% aws s3 ls バケット名/AWSLogs/アカウント番号/Config/ap-northeast-1/2021/ --recursive --summarize --human-readable > /tmp/hoge.txt && tail -n 2 /tmp/hoge.txt
Total Objects: 1770
   Total Size: 28.2 MiB

そこまでサイズは大きくないので問題なさそうです。指定するプレフィックスにより変動するので、意識するようにしましょう。

今回は使用しませんが、スキャン対象を限定するためのパーティションという考え方もあります。覚えておきましょう。

Athena でのクエリの実行

いくつかのパターンで実行します。

日別の設定項目数を確認する

クエリの例は以下です。ハイライト部の期間は環境に合わせて修正してください。

SELECT result.configurationitemcapturetime,
         count(result.configurationitemcapturetime) AS NumberOfChanges
FROM 
    (SELECT regexp_replace(configurationItem.configurationItemCaptureTime,
         '(.+)(T.+)', '$1') AS configurationitemcapturetime
    FROM default.awsconfig
    CROSS JOIN UNNEST(configurationitems) AS t(configurationItem)
    WHERE "$path" LIKE '%ConfigHistory%'
            AND configurationItem.configurationItemCaptureTime >= '2021-07-01T%'
            AND configurationItem.configurationItemCaptureTime <= '2021-08-28T%') result
GROUP BY  result.configurationitemcapturetime
ORDER BY  result.configurationitemcapturetime

期間内の日ごとに、Config の設定項目( configuration item )数を確認できます。

Athena6

リソースごとの設定項目数を降順にソートする

クエリの例は以下です。

SELECT configurationItem.resourceType,
         configurationItem.resourceId,
         COUNT(configurationItem.resourceId) AS NumberOfChanges
FROM default.awsconfig
CROSS JOIN UNNEST(configurationitems) AS t(configurationItem)
WHERE "$path" LIKE '%ConfigHistory%'
        AND configurationItem.configurationItemCaptureTime >= '2021-08-01T%'
        AND configurationItem.configurationItemCaptureTime <= '2021-08-28T%'
GROUP BY  configurationItem.resourceType, configurationItem.resourceId
ORDER BY  NumberOfChanges DESC

リソース ID ごとに、Config の設定項目数を確認できます。

Athena7

リソースタイプごとの設定項目数を降順にソートする

クエリの例は以下です。

SELECT configurationItem.resourceType,
         COUNT(configurationItem.resourceType) AS NumberOfChanges
FROM default.awsconfig
CROSS JOIN UNNEST(configurationitems) AS t(configurationItem)
WHERE "$path" LIKE '%ConfigHistory%'
        AND configurationItem.configurationItemCaptureTime >= '2021-04-01T%'
        AND configurationItem.configurationItemCaptureTime <= '2021-04-30T%'
GROUP BY  configurationItem.resourceType
ORDER BY  NumberOfChanges DESC

特定のリソースで設定項目が多ければ先ほどのクエリで確認できますが、「一つ一つのリソースでは少ないがリソース数自体が多い」というケースにはマッチしません。

リソースタイプの単位で確認したい時にはこちらのクエリを使用してください。

Athena8

( IAM ロールだけで 912 の設定項目……どういう時にこんなことになるんでしょうね。ちっとも分かりません。)

特定のリソースタイプに限定してクエリする

クエリ例は以下です。 「リソースごとの設定項目数を降順にソートする」をベースに、WHERE 句 に条件を追加しています。

SELECT configurationItem.resourceType,
         configurationItem.resourceId,
         COUNT(configurationItem.resourceId) AS NumberOfChanges
FROM default.awsconfig
CROSS JOIN UNNEST(configurationitems) AS t(configurationItem)
WHERE "$path" LIKE '%ConfigHistory%'
        AND configurationItem.configurationItemCaptureTime >= '2021-04-01T%'
        AND configurationItem.configurationItemCaptureTime <= '2021-04-30T%'
        AND configurationItem.resourceType = 'AWS::IAM::Role'
GROUP BY  configurationItem.resourceType, configurationItem.resourceId
ORDER BY  NumberOfChanges DESC

特定のリソースタイプだけに限定して、リソース ID ごとの設定項目数を確認できます。

Athena9

( IAM ロールごとの設定項目数はほぼ 1 なので、IAM ロールが 900 個くらい増えた時期があったんですかね。なんでだろう。ちっとも分かりません。)

Config レコーダーで記録対象を変更する

ここまでのクエリで、お手元の環境では特定のリソースや特定のリソースタイプに設定項目が集中していることが確認できたのではないでしょうか。

ループ処理のように意図せず作成/削除が行われていた、といった原因であればリソース側の設定変更で回避できるかと思います。

とは言え、今後同じことが起こらないように記録対象から除外しておきたい、必要があって定常的に発生する処理なのでリソース側での設定変更はしたくない、ということもあるでしょう。その場合には Config レコーダーの設定を変更することで対応できます。

Config の「設定」から、記録するリソースタイプを選択できます。画像ではすべてのリソースを選択する設定となっています。

AWS_Config_Console_recorder

「特定のリソースタイプを記録する」に切り替えることによって、記録対象をコントロールできます。記録する対象を一つずつ選択していく方法もあれば、記録したくないリソースを除いていく方法もあります。

後者の場合、一度以下のようにすべての AWS リソースタイプを記録するようにして設定を保存してください。

AWS_Config_Console_recorder-2548255

再度設定を開き直すと以下のようにリソースタイプが全選択された状態となっているため、除外したいものを削除していってください。

AWS_Config_Console_Recorder-2548332

Config による記録はなるべく多くのリソースタイプに対して有効になっていることが望ましいですが、コスト見合いで必要なもののみを選択する、というのも大事な視点です。

終わりに

Athena で AWS Config の記録された設定項目数の内訳を確認する手順を試してみました。

Athena をあまり使ったことがなかったのですが、サンプルが提供されていたのでそこまで迷わず試せました。きちんと対象を絞れば料金もそこまでかからなさそうであるため、これまで使ったことがない方は試してみてはいかがでしょうか。

AWS Confg の料金暴騰の原因特定にお役立てください。

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