Athenaのパーティションプロジェクションを利用してCloudTrailのログ検索をする

記事タイトルとURLをコピーする

CloudTrailのログをS3に保存することがあります。 その検索にはAthenaが便利で、導入もマネージメントコンソールから簡単にできます。 しかし、マネージメントコンソールの指示にしたがって導入すると、検索速度やコストの面で問題が発生します。

これを解決するために、パーティションプロジェクションという機能を利用します。

docs.aws.amazon.com

マネージメントコンソールどおりに作成すると?

最初に、マネージメントコンソールにしたがって操作すると、どうなるのか、何が問題なのかを見ていきましょう。

まず、CloudTrailの画面で Athenaテーブルを作成 をクリックします。

f:id:swx-watanabe:20201125094112p:plain

次に、 テーブルを作成 をクリックします。

f:id:swx-watanabe:20201125094628p:plain

そして、Athenaの画面にいき、検索をします。 例えば、アクセス元のIPアドレスを検索条件としたい場合は、以下のようなSQL文になります。

SELECT * FROM "データベース名"."テーブル名" WHERE "sourceipaddress" = 'IPアドレス';

f:id:swx-watanabe:20201125095453p:plain

とても簡単に検索結果が得られました。 何が問題でしょうか?

Athenaはスキャンしたデータのサイズで課金されるのですが、それが1.47GBとなっています。 これはCloudTrailのログを保存しているS3バケットのサイズ全体と一致します。

f:id:swx-watanabe:20201125114337p:plain

したがって、長期間のログを保存し続けると、コスト的に大変なことになってしまいますし、実行時間も長くなってしまうと想像できます。

パーティションプロジェクションでスキャン量を削減

スキャンするデータのサイズを減らしましょう。 一番簡単なのは、特定の期間のログだけを検索対象とすることです。

例えば、2020年10月9日から2020年10月10日だけをスキャン対象とすれば、コストも削減し、応答速度も上がるはずです。

f:id:swx-watanabe:20201125103420p:plain

これを行うためにはパーティションを作成する必要があります。 日時指定をした時にどのS3パス部分をスキャンすればいいのかをAthenaに教え込むイメージです。

それでは、Athenaでテーブルを作ります。 CloudTrail経由で作成したテーブルが既にある場合はそれを削除するか、別の名前でテーブルで作成します。

CREATE EXTERNAL TABLE テーブル名 (
    eventVersion STRING,
    userIdentity STRUCT<
        type: STRING,
        principalId: STRING,
        arn: STRING,
        accountId: STRING,
        invokedBy: STRING,
        accessKeyId: STRING,
        userName: STRING,
        sessionContext: STRUCT<
            attributes: STRUCT<
                mfaAuthenticated: STRING,
                creationDate: STRING>,
            sessionIssuer: STRUCT<
                type: STRING,
                principalId: STRING,
                arn: STRING,
                accountId: STRING,
                userName: STRING>>>,
    eventTime STRING,
    eventSource STRING,
    eventName STRING,
    awsRegion STRING,
    sourceIpAddress STRING,
    userAgent STRING,
    errorCode STRING,
    errorMessage STRING,
    requestParameters STRING,
    responseElements STRING,
    additionalEventData STRING,
    requestId STRING,
    eventId STRING,
    resources ARRAY<STRUCT<
        arn: STRING,
        accountId: STRING,
        type: STRING>>,
    eventType STRING,
    apiVersion STRING,
    readOnly STRING,
    recipientAccountId STRING,
    serviceEventDetails STRING,
    sharedEventID STRING,
    vpcEndpointId STRING
)
COMMENT 'CloudTrail table for S3バケット名 bucket'
PARTITIONED BY ( date STRING )
ROW FORMAT SERDE 'com.amazon.emr.hive.serde.CloudTrailSerde'
STORED AS INPUTFORMAT 'com.amazon.emr.cloudtrail.CloudTrailInputFormat'
OUTPUTFORMAT 'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
LOCATION 's3://S3バケット名/AWSLogs/アカウントID/CloudTrail/'
TBLPROPERTIES (
    'projection.enabled' = 'true',
    'projection.date.type' = 'date',
    'projection.date.range' = '2020/10/01,NOW',
    'projection.date.format' = 'yyyy/MM/dd',
    'projection.date.interval' = '1',
    'projection.date.interval.unit' = 'DAYS',
    'storage.location.template' = 's3://S3バケット名/AWSLogs/アカウントID/CloudTrail/リージョン/${date}',
    'classification'='cloudtrail'
)
  • PARTITIONED BYTBLPROPERTIES 以外は、マネージメントコンソールから作成されるものと同じです。
  • テーブル名、S3バケット名、アカウントID、リージョンは、各自のものに修正が必要です。
  • 2020/10/01の部分はログ保存された最初の日付にしておけばいいと思います。
  • 詳細は パーティション射影のサポートされている型 - Amazon Athena に記載があります。

f:id:swx-watanabe:20201125104614p:plain

期間を指定して、検索をしてみます。

SELECT * FROM "データベース名"."テーブル名" WHERE "sourceipaddress" = 'IPアドレス' and date between '2020/10/09' and '2020/10/10';

f:id:swx-watanabe:20201125104951p:plain

Athenaの画面の履歴を見てみると、実行時間とスキャンしたデータが圧倒的に改善されたのがわかります。

f:id:swx-watanabe:20201125105438p:plain

まとめ

f:id:swx-watanabe:20201125113553p:plain

S3に保存したログをAthenaで検索する時は、パーティション化が不可欠です。 今回はCloudTrailの例ですが、ELBなどのログも同様です。 パーティションを考慮しなくても導入時のログが少ない時はあまり気にならないのですが、時が経ち、ログが多くなってから検索すると「あれ?終わらないな。。。」となるので気をつけましょう。

渡辺 信秀(記事一覧)

2017年入社。趣味は言語学習。