【AWS】ALB,CloudFrontのログをAthenaで分析する🐱
概要📝
ALBとCloudFrontのログを有効化してS3に格納し、Athenaで分析してみる方法について記載しています
私はAWSエンジニアとしてまだまだ駆け出しなので、もっと良い分析方法があるかと思いますが、少しでも参考になれば幸いです🙇♂️🙇♂️
対象読者🔖
- ALB・CloudFrontのログを見たことがない方
- ALB・CloudFrontのログを有効化はしてみたがどうすればいいかわからない方
目的、気持ち🔥
- 想定: わたしは、せんぱいからきほんの監視業務を教えてもらった!🕺
我々のプロダクトでは、
CloudFront(FE用・BE用) + 一般的3層アーキテクチャ + ECS(Fargate) +α
の構成を採用していました🍍
先輩に「日々どんな監視を行なったら良いでしょうか?」と聞いたところ、
その中のひとつとして「CloudFront・ALBで5xxエラーが発生したら、調査してBEに連携して、改善すべきかどうか記録しておくといいですよ」という内容がありました🎯
他にもさまざまな監視項目・方法が考えられると思いますが、今回は上記について記載します
(特にNew Relicのようなツールを使った改善フローも構築してみたいですが、現状は経験がありません🙇♂️)
コスト💰
アクセスログを溜め続けることで、S3の料金
Athenaのクエリを叩くことで、Athenaの料金
がかかります
特にAthenaのクエリは対象のデータを読み込むと意外に料金がかかってしまうことがありますので、
・テーブルを作成する際に範囲を限定
・パーティションを使う
といった工夫を、必要に応じて検討した方が良いと思います💸
手順👓
ログをS3に格納⚙️
ALBのログを有効化⚙️
- Consoleの検索窓>
EC2
>Load Balancers
>設定変更したいLoad Balancer>下タブAttributes
>Edit
>Monitoring
セクションのAccess losgを有効化
-
S3 URI
に、ログを格納したい場所の、S3バケットのプレフィックスのURIを入力
例えばmy-alb-access-logs/access-logs/
のように入力 -
Save Changes
で完了
CloudFrontのログを有効化⚙️
- Consoleの検索窓>
CloudFront
>Distributions
>設定変更したいディストリビューション>タブGeneral
>Edit
>Standard logging
セクションをOn
にする
-
S3 bucket
に、ログを格納するS3バケットの名前を入力
例えば my-cloudfront-access-logslog-bucket.s3.amazonaws.com
のように入力
-
Log prefix
にログを格納するプレフィックスを入力
例えば、access-logs/
のように入力
-
Save Changes
で完了
完了です
- (補足)CloudFrontログについて、Lambdaで毎月1日のUTC0時にプレフィックスを変えるものを実装する
CloudFrontログは、ALBログと違って、年月日ごとにプレフィックスが分かれていません
分けたい方は、下記の公式ドキュメントを参考にすると良いと思います
私は、
access-logs/ →この階層に当月分ログがある
archive-logs/year/month/day →この階層に過去月分のログがある
というプレフィックスになるようにしました
Lambdaは月1回、access-logsからarchive-logsに移動する(リネームする)処理を行います
(任意)CloudWatchダッシュボードに、5xxエラーのメトリクスを登録⚙️
- ConSoleの検索窓>
CloudWatch
>Dashboards
>開きたいダッシュボードまたはCreate Dashboard
>+
>Line
を選択してNext
>Metrics
を選択してNext
- 検索窓に
ALB
>Per AppELB, per AZ Metrics
>検索窓に5xx
>HTTPCode_Target_5XX_Count
にチェックを入れてCreate widget
まだ5xxエラーが1件も発生していない状態だと、検索で出てこない場合があります
そのときは、時間を空けて発生してから試してみると良いと思います
-
+
>Line
を選択してNext
>Metrics
を選択してNext
>検索窓の左Tokyo
からUS East(N. Virginia)us-east-1
を選択
- 検索窓に
CloudFront
>Per-Distribution Metrics
>検索窓に5xx
>5xxErrorRate
にチェックを入れてCreate widget
- 定期的にダッシュボードを見て、CloudFrontまたはALBで5xxエラーが発生していたら、Athenaで分析してみる
Athenaでの分析例は後述します
Athenaにログ分析用のテーブルを作成⚙️
テーブル名
とLocation
の部分を、変更して、Athena内でクエリを実行すればOKです
公式ドキュメント内にはパーティションを使用するものもありますが、私はLocation
で月ごとのプレフィックスをすることでクエリの対象範囲を絞っています
一度テーブル作成に成功したら、Generate table DDL
で同じクエリを使い回して、別のテーブルを作ることができます
Tables
>対象テーブルの...
を押す>Generate table DDL
ALBログ分析用のテーブル🔧
公式ドキュメントに従って、ALBログ分析用のテーブルを作成します
下記は私が現状使っているテーブルからGenerate table DDL
したものです
公式ドキュメントのものと若干差異があったので、何かエラーが出て調整した後のものかな...と思います
公式も参照しつつうまく調整をいただければ幸いです
CREATE EXTERNAL TABLE `[テーブル名]`(
`type` string COMMENT '',
`time` string COMMENT '',
`elb` string COMMENT '',
`client_ip` string COMMENT '',
`client_port` int COMMENT '',
`target_ip` string COMMENT '',
`target_port` int COMMENT '',
`request_processing_time` double COMMENT '',
`target_processing_time` double COMMENT '',
`response_processing_time` double COMMENT '',
`elb_status_code` int COMMENT '',
`target_status_code` string COMMENT '',
`received_bytes` bigint COMMENT '',
`sent_bytes` bigint COMMENT '',
`request_verb` string COMMENT '',
`request_url` string COMMENT '',
`request_proto` string COMMENT '',
`user_agent` string COMMENT '',
`ssl_cipher` string COMMENT '',
`ssl_protocol` string COMMENT '',
`target_group_arn` string COMMENT '',
`trace_id` string COMMENT '',
`domain_name` string COMMENT '',
`chosen_cert_arn` string COMMENT '',
`matched_rule_priority` string COMMENT '',
`request_creation_time` string COMMENT '',
`actions_executed` string COMMENT '',
`redirect_url` string COMMENT '',
`lambda_error_reason` string COMMENT '',
`target_port_list` string COMMENT '',
`target_status_code_list` string COMMENT '',
`classification` string COMMENT '',
`classification_reason` string COMMENT '')
ROW FORMAT SERDE
'org.apache.hadoop.hive.serde2.RegexSerDe'
WITH SERDEPROPERTIES (
'input.regex'='([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*):([0-9]*) ([^ ]*)[:-]([0-9]*) ([-.0-9]*) ([-.0-9]*) ([-.0-9]*) (|[-0-9]*) (-|[-0-9]*) ([-0-9]*) ([-0-9]*) \"([^ ]*) (.*) (- |[^ ]*)\" \"([^\"]*)\" ([A-Z0-9-_]+) ([A-Za-z0-9.-]*) ([^ ]*) \"([^\"]*)\" \"([^\"]*)\" \"([^\"]*)\" ([-.0-9]*) ([^ ]*) \"([^\"]*)\" \"([^\"]*)\" \"([^ ]*)\" \"([^s]+?)\" \"([^s]+)\" \"([^ ]*)\" \"([^ ]*)\"')
STORED AS INPUTFORMAT
'org.apache.hadoop.mapred.TextInputFormat'
OUTPUTFORMAT
'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
LOCATION
's3://[バケット名]/access-logs/AWSLogs/[アカウントID]/elasticloadbalancing/[リージョン]/[年]/[月]'
TBLPROPERTIES (
'transient_lastDdlTime'='1686285466')
CloudFrontログ分析用のテーブル🔧
公式ドキュメントに従って、CloudFrontログ分析用のテーブルを作成します
下記は私が現状使っているテーブルからGenerate table DDL
したものです
公式ドキュメントのものと若干差異があったので、何かエラーが出て調整した後のものかな...と思います
公式も参照しつつうまく調整をいただければ幸いです
CREATE EXTERNAL TABLE [テーブル名](
`date` date,
`time` string,
`location` string,
`bytes` bigint,
`request_ip` string,
`method` string,
`host` string,
`uri` string,
`status` int,
`referrer` string,
`user_agent` string,
`query_string` string,
`cookie` string,
`result_type` string,
`request_id` string,
`host_header` string,
`request_protocol` string,
`request_bytes` bigint,
`time_taken` float,
`xforwarded_for` string,
`ssl_protocol` string,
`ssl_cipher` string,
`response_result_type` string,
`http_version` string,
`fle_status` string,
`fle_encrypted_fields` int,
`c_port` int,
`time_to_first_byte` float,
`x_edge_detailed_result_type` string,
`sc_content_type` string,
`sc_content_len` bigint,
`sc_range_start` bigint,
`sc_range_end` bigint)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '\t'
STORED AS INPUTFORMAT
'org.apache.hadoop.mapred.TextInputFormat'
OUTPUTFORMAT
'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
LOCATION
's3://[バケット名]/access-logs'
TBLPROPERTIES (
'skip.header.line.count'='2',
'transient_lastDdlTime'='1676855653')
(例)分析用クエリ🔧
先ほどテーブル作成の際に紹介した ALBとCloudFrontの公式ドキュメントにもクエリ例が載っています
Classmethodさんのブログ記事なんかにも、いろんな分析方法が載っていますので、検索してみると良いと思います
CloudFrontログの項目 - 標準ログファイルフィールド
ALBログの項目 - 構文
5xxエラーを検索👓
CloudFront
SELECT *
FROM [テーブル名]
WHERE 1=1
-- AND uri = ''
-- AND request_ip = ''
AND status >= 500
ORDER BY date DESC,time DESC;
コメントになっている部分は最初にクエリを叩いてから以下のように使ったりします
-
uri
同様のエラーが同じuriでどのくらい起きているかざっと見たい場合 -
request_ip
エラーになった前後、同じrequest_ipの人が成功しているか、何度も失敗しているか
ALB
SELECT *
FROM [テーブル名]
WHERE 1=1
-- AND request_url = ''
-- AND client_ip = ''
AND elb_status_code >= 500
ORDER BY time DESC;
著しく時間がかかっている処理がないか検索👓
5xxエラーとは別に、こちらもたまに見ています
CloudFront
SELECT uri,max(time_taken) as max_time_taken
FROM [テーブル名]
GROUP BY uri
ORDER BY max_time_taken DESC;
(例)BE担当へ共有して、改善シートに記入📌
他にも様々な監視・分析項目があると思いますが、とりあえず上記を監視して、たとえば5xxエラーが発生した場合は以下のようなスプシを作成してBE担当と原因調査をしていました
もっとスマートな方法があると思うのですが、小規模なシステムで5xxエラーも少なかったので、少しずつ対応していました🐶
年月日_調査詳細 スプシ📌
実際のログなどを貼り付ける、詳細情報があるスプシです
シート名 | 項目名 | 備考 |
---|---|---|
調査サマリ | インフラorアプリケーションエラーの切り分け | ALBログにて、elb_status_code=target_status_codeの場合、ALBはアプリケーションから受け取ったエラーコードを返しているだけ=アプリケーションエラーと考えられる |
調査サマリ | アクセス元のIP | ipinfoなどで調べたアクセス元のIPアドレス情報 |
調査サマリ | リクエストの際に叩かれたURI | |
調査サマリ | 上記URIを叩いた時の処理内容 | |
調査サマリ | エラーの発生原因 | |
調査サマリ | エラーを再発防止すべきか、静観で良さそうか | |
CloudFrontログ | - | CloudFrontのログを必要な範囲で貼り付けて、調査対象に色を塗る |
ALBログ | - | ALBのログを必要な範囲で貼り付けて、調査対象に色を塗る |
Appログ | - | Appのログ(CloudWatchのlog streamなど)を必要な範囲で貼り付けて、調査対象に色を塗る |
改善シート スプシ📝
詳細スプシをいちいち見ているとめんどくさいので、こちらにまとめておきます
シート名 | 項目名 | 備考 |
---|---|---|
調査記録 | エラー発生日時 | |
調査記録 | エラー発生場所 | どの機能で発生したかなど |
調査記録 | ステータス | 調査中 保留(解決策あり) 保留(原因不明) 解決済 問題なし などの、ステータス |
調査記録 | 問題(要約) | |
調査記録 | 解決策(要約) | |
調査記録 | 備考 | |
調査記録 | 詳細リンク | 調査詳細スプシのリンク |
編集後記📝
こんな地味な調査方法でいいのかなぁと思いつつも、ちゃんと記録していくことで、少しずつどんなエラーが発生しているかがわかるようになってきました🐝
エラーが複数回発生していても、すでに調査済みの特に直すほどでもないエラーであった場合は安心ですね♻️
また、我々のチームでは、CTO含め5名の少人数ですが、全員でQAを行なっていました🦁🦁
そもそもアプリケーションエラーが発生しないように、しっかりQAする重要性も感じました
New Relicなどのツールでスマートに調査する方法も学んでみたいと思っています...!!🙇♂️🙇♂️
Discussion