Amazon Web Services ブログ

Amazon Athena を使用して AWS のサービスログを簡単にクエリする

多くの組織では、AWS のサービスログを含むさまざまなログの保存先として Amazon Simple Storage Service (Amazon S3) を主に使用しています。ログデータを Amazon S3 に保存する利点の 1 つは、さまざまな方法でアクセスできることです。一般的な方法の 1 つは、S3 上のデータに対するサーバーレスのクエリエンジンである Amazon Athena を使用してクエリを実行することです。ログのクエリの一般的なユースケースは、サービスとアプリケーションのトラブルシューティング、パフォーマンス分析、およびセキュリティ監査です。Athena で最高のパフォーマンスを得てクエリコストを削減するには、AWS ビッグデータブログの「Top 10 Performance Tuning Tips for Amazon Athena」で概説されているように、一般的なベストプラクティスに従うことをお勧めします。これらのベストプラクティスには、Apache Parquet のようなデータを円柱形式に変換し、結果として得られたデータを S3 で分割することが含まれます。

この記事では、Athena Glue Service Logs (AGSlogger) として知られる Python ライブラリをオープンソース化しています。このライブラリには、最も一般的なログ形式を解析および最適化するための定義済みテンプレートがあります。このライブラリは、AWS Glue のスキーマの定義、パーティションの管理、および抽出、変換、ロード (ETL) ジョブ内でのデータ変換のためのメカニズムを提供します。AWS Glue は、サーバーレスのデータ変換およびカタログ作成サービスです。このライブラリを AWS Glue ETL ジョブと組み合わせて使用すると、ログデータを処理するための共通のフレームワークを有効にできます。

AWS Glue ETLで Python ライブラリを使用する

AWS Glue ETL の機能の 1 つは、Python ライブラリをジョブにインポートする機能です (ドキュメントに記載されているとおり)。ご紹介するアプローチでこの機能を利用します。この機能を使用すると、まず選択した Python モジュールを含む Amazon S3 の .zip ファイルへのリンクを AWS Glue に提供します。次に、AWS Glue が実行時にそれらをインポートします。

AWS Glue のジョブをできるだけシンプルにしながら、新しいバージョンのライブラリを簡単にロールアウトできるようにしたいと思います。これを実現するために、すべてのセットアップ、設定、および変換ロジックがライブラリに含まれており、AWS Glue は単にジョブを実行します。新しいログ形式がライブラリで追加または更新されると、新しいバージョンの .zip ファイルを S3 にデプロイできます。その後、関連する AWS Glue ジョブによって自動的にインポートされます。これが ETL スクリプトの例です。

from athena_glue_service_logs.job import JobRunner
 
job_run = JobRunner(service_name='s3_access')
job_run.convert_and_partition()

AGSlogger ライブラリについて

このライブラリは GitHub の athena-glue-service-logs リポジトリにあります。これは AWS のサービスログの初期変換を行い、さらに新しいログが S3 に配信されるときに継続的な変換を実行するように設計されています。以下のログタイプがサポートされています。

  • Application Load Balancer
  • Classic Load Balancer
  • AWS CloudTrail
  • Amazon CloudFront
  • S3 Access
  • Amazon VPC Flow

追加のログを変換するには、スクリプト内の service_name 変数、および必要なテーブル名と Amazon S3 の場所を指すさまざまなジョブパラメータを更新します。

スクリプトにはいくつかの制限があります。

  • スクリプトは、大量のログデータ (100 GiB 超) でテストされていません。
  • 大量のログファイルがある場合は、Apache Spark executor 設定を増やす必要があるかもしれません。AWS Glue ジョブを編集して、次のジョブパラメータを追加します。

key: --conf
value: spark.yarn.executor.memoryOverhead=1G

  • S3 Access のような特定の種類のログについて最近のログ (30 日以内) がない場合、スクリプトは最適化されたテーブルを適切に生成できない可能性があります.
  • requestParameters や responseElements などのいくつかの CloudTrail フィールドは JSON 文字列として残されます – クエリ時に Athena を使用してこの JSON からデータを抽出することができます。

始める前に

始める前に、いくつかの前提条件があります。

  1. AWS Glue で使用する IAM ロールを作成します。詳細については、AWS Glue ドキュメントの「AWS Glue 用の IAM ロールを作成する」を参照してください。
  2. 自分のアカウントから Athena にアクセスできることを確認してください。
  3. このスクリプトの例として Amazon S3 サーバーアクセスログを使用しているので、Amazon S3 バケットでのアクセスログを有効にします。詳細については、「サーバーアクセスログを有効にする方法」を参照してください。
    S3 ドキュメント
  4. AWS Glue ETL ジョブを実行するのと同じ AWS リージョンの Amazon S3 バケットに Python ライブラリをダウンロードして保存します。最新リリースを https://github.com/awslabs/athena-glue-service-logs/releases からダウンロードしてください。その後、次のように .zip ファイルを Amazon S3 バケットにコピーします。

aws s3 cp athena_glue_converter_v5.3.0.zip s3://<bucket>/glue_scripts/

これで、AWS Glue ETL ジョブを作成する準備が整いました。

ライブラリを使用して AWS Glue ETL ジョブを作成する

この記事では、Amazon S3 サーバーアクセスログ (ドキュメントで説明されています) に焦点を当てます。デフォルトでは、これらのログは Amazon S3 の単一の場所に配信されます。Parquet に変換してこれらのログを分割すると、クエリのパフォーマンスが大幅に向上し、クエリのコストが削減されます。

このリリースに関連するリポジトリを複製した場合は、「make」コマンドを使用してジョブの作成を自動化できます。AWS Glue コンソールでのジョブの作成プロセスについても説明します。設定が必要な [ジョブのプロパティ] ページにはいくつかの特定の設定があります。

AWS Glue ETL ジョブを作成するには

  1. AWS Glue コンソールで、ナビゲーションペインの [ETL] から [ジョブ] を選択し、次に [ジョブの追加] を選択します。ジョブ作成ウィザードに従います。「あなたが作成した新しいスクリプト」が選択されていることを確認してください。後でそのコード指定します。ここで使う ETL 言語は Python です。詳細プロパティで、[ジョブブックマーク] を有効にします。ジョブのメトリクスはジョブを監視するときにも役立ちますが、必須ではありません。
  2. [Python ライブラリパス] セクションの [スクリプトライブラリ] の下に、前に示したように Amazon S3 バケットにアップロードした .zip ファイルへのフルパスを入力します。
    s3://<bucket>/glue_scripts/athena_glue_converter_v5.3.0.zip

    処理能力が多かれ少なかれ必要と思われる場合は、DPU を調整できます。ここでは 10 のままで構いません。
  1. 以下で詳細に説明するように、いくつかの異なるタイプのパラメータを指定します。
  • Amazon S3 サーバーアクセスログのソース。
  • 変換されたログを保存する場所。

サービスログの詳細」で説明されているように、AWS のサービスログはさまざまな場所に保存できます。Amazon S3 サーバーのアクセスログを保存するには、アクセスログを有効にした S3 バケットで設定したものと一致するバケットとプレフィックスを指定します。

  • AWS Glue Data Catalog に作成したデータベース名とテーブル名。

デフォルトでは、変換されたログは日付ごとに分割されています。スクリプトは必要なテーブルを作成し、その後のジョブの実行時にパーティションを最新の状態に保ちます。AWS Glue クローラを使用する必要はありませんが、同様の機能を提供できます。設定する必要があるさまざまなプロパティは次のとおりです。

キー
--raw_database_name source_logs
--raw_table_name s3_access
--converted_database_name aws_service_logs
--converted_table_name s3_access
--s3_converted_target s3://<bucket>/converted/s3_access
--s3_source_location

s3://<bucket>/s3_access

 

  1. ウィザードの残りの部分に進み、ジョブの作成フローを終了します。スクリプトエディタが開きます。スクリプトエディタのすべてのコードをインポート行も含めて次の行に置き換えます。
    from athena_glue_service_logs.job import JobRunner
     
    job_run = JobRunner(service_name='s3_access')
    job_run.convert_and_partition()
  1. スクリプトを保存して、[ジョブの実行] を選択します。 ジョブが開始すると、スクリプトの下をスクロールするジョブからログ出力が表示されます。

今作成したスクリプトは、標準のバケット内の S3 に保存されます。AWS Command Line Interface を使用して AWS Glue ETL ジョブを作成することもできます。最初に S3 の前のスクリプトをコピーし、それを ScriptLocation パラメータとして指定します。

aws glue create-job --name S3AccessLogConvertor \
--description "Convert and partition S3 Access logs" \
--role AWSGlueServiceRoleDefault \
--command Name=glueetl,ScriptLocation=s3://<bucket>/glue_scripts/s3_access_job.py \
--default-arguments '{
  "--extra-py-files":"s3://<bucket>/glue_scripts/athena_glue_converter_v5.3.0.zip",
  "--job-bookmark-option":"job-bookmark-enable",
  "--raw_database_name": "source_logs"、
  "--raw_table_name": "s3_access"、
  "--converted_database_name": "aws_service_logs"、
  "--converted_table_name": "s3_access"、
  "--TempDir":"s3://<bucket>/tmp",
  "--s3_converted_target":"s3://<bucket>/converted/s3_access",
  "--s3_source_location":"s3://<bucket>/s3_access/"
}'

将来の実行をスケジュールする

デフォルトでは、このジョブは手動で実行されるように設定されています。定期的に実行するには、希望の頻度でジョブを実行するように AWS Glue に新しいスケジュールトリガーを設定します。最適化されたクエリの最近のログを見つけやすくするため、毎時スケジュールすることをお勧めします。

ジョブが実行されるたびに、スクリプトは新しいログデータを探し、それを Parquet 形式に変換します。その後、スクリプトは変換の結果として追加された可能性のある新しいパーティションを追加します。このスクリプトは AWS Glue のジョブブックマークを使用して、新しく配信されたデータを確実に処理します。ブックマークの詳細については、AWS Glue ドキュメントの「ジョブのブックマークを使用した処理済みデータの追跡」を参照してください。

Athena で最適化されたデータをクエリする: 例

データを行ベースのログファイルから列ベースの Parquet に変換したので、Athena を使用してこのデータに対するクエリを作成できます。スクリプトを最初に実行した後、AWS Glue ETL ジョブプロパティで指定されたテーブルが自動的に作成されます。ここに始めるのにちょうどよいサンプルクエリをいくつか示します。

例 1: 最もリクエストが多い S3 キー

SELECT key, COUNT(*) AS count
FROM "aws_service_logs"."s3_access"
WHERE operation IN ('REST.GET.OBJECT', 'REST.COPY.OBJECT', 'REST.COPY.OBJECT_GET')
GROUP BY 1
ORDER BY 2 DESC
limit 100;

例 2: 昨日バケットにアクセスしたトップ IP アドレス

SELECT remote_ip, COUNT(*) FROM "aws_service_logs"."s3_access"
WHERE year=date_format(current_date, '%Y') AND month=date_format(current_date, '%m') AND day=date_format(current_date + interval '-1' day, '%d')
GROUP BY 1
ORDER BY 2 DESC
limit 100;

GROUP BY と ORDER BY 操作では、文字列ではなく数字を使用していることに注意してください。これは Athena クエリの最適化の 1 つです。他の最適化については、「パフォーマンスチューニングのヒントトップ 10」のブログ記事をぜひチェックしてみてください。

さらに、年、月、日のパーティション列を使用して、スキャンされるデータ量を制限し、クエリのコストを削減します。

まとめ

この記事では、AWS Glue を使用してさまざまなタイプの AWS のサービスログを効率的に処理するために使用できる新しいオープンソースライブラリを紹介しました。このライブラリは、一般的なベストプラクティスの適用を自動化して、Amazon Athena と Amazon Redshift を使用して高性能で費用対効果の高いデータクエリを可能にします。このライブラリが役に立つことを願っています。そしてプルリクエストもお寄せください。新しいログタイプを追加する場合は、AWS Labs athena-glue-service-logs リポジトリのコードをチェックしてみてください。

 


著者について

Damon Cortesi は、アマゾン ウェブ サービスのビッグデータアーキテクトです