Nginx ログで学ぶ CloudWatch Logs Insights の基本

2024年5月31日

Amazon EKS

CloudWatch Logs Insights は、AWS が提供するログデータの解析サービスです。SQL のような独自のクエリ言語を使って、CloudWatch Logs に保存されたログを検索したり分析したりすることができます。CloudWatch Logs の Log stream を横断して検索できたり、クエリ言語を使って検索条件を細かく指定できたり、結果を集計できたりするのが便利です。

この記事では EKS 上で稼働する Nginx の Pod のログを例に、CloudWatch Logs Insights の基本的な使い方を紹介します。

目次

  1. CloudWatch Logs に記録された Nginx のアクセスログ
  2. Log Group の指定
  3. Nginx のログと、ログの保存日時を出力するクエリ構文
  4. ログの日時を指定したい場合
  5. 出力件数を数えたい場合
  6. 10 分ごとのログの件数を数えたい場合
  7. 10 分ごとにログの件数を数え、件数の多い順に並べ替えたい場合
  8. ログの中の特定の文字列を抽出したい場合
  9. 抽出した文字列ごとにログの件数を数えて、件数の多い順に並べ替えたい場合
  10. CloudWatch Logs Insights の料金

CloudWatch Logs に記録された Nginx のアクセスログ

今回は EKS で稼働する Nginx Pod のログを例に紹介します。Pod のログは CloudWatch Observability EKS add-on を利用して CloudWatch Logs に保存されるように設定しています。Nginx のアクセスログである /var/log/access.log の内容は "log" というフィールドに保存されています。

{
    "time": "2024-05-25T06:35:35.830809538Z",
    "stream": "stdout",
    "_p": "F",
    "log": "10.0.0.10 - - [31/May/2024:06:35:35 +0000] \"GET /api/v1/hello HTTP/1.1\" 200 259 \"https://myapp.example.com/\" \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36\" \"-\"",
    "kubernetes": {
        "pod_name": "nginx-7869dbf94b-jfdjf",
        "namespace_name": "my-namespace",
        "pod_id": "4b5f5f2b-e102-4aca-b6fd-6c904d9e1542",
        "host": "ip-10-0-0-20.ap-northeast-1.compute.internal",
        "container_name": "nginx",
        "docker_id": "8435345046a89d993fd461a0cfc1aa30101753121d5669ce310812b17ec374bf",
        "container_hash": "docker.io/library/nginx@sha256:ec881e8e2b068e388e992e0e12360ff9f93737f90eb3e346d0ceac83710383d8",
        "container_image": "docker.io/library/nginx:1.26"
    }
}

CloudWatch Observability EKS add-on の導入方法は過去に書いた記事を参考にしてください。

Amazon EKS
CloudWatch Observability EKS add-onでEKSのメトリクスとログ収集

CloudWatch Observability EKS add-on を試してみたので備忘録。これまで EKS のメト ...

続きを見る

Log Group の指定

CloudWatch Logs Insights の画面を開いたら、まずはじめに、画面の上のほうで、Log Group を選択します。

CloudWatch Observability EKS add-on を利用している場合、Pod のログは /aws/containerinsights/<eks-cluster-name>/applicationの Log Group に保存されています。

Nginx のログと、ログの保存日時を出力するクエリ構文

ログの保存日時と Nginx のログを出力したい場合は以下のクエリを実行します。

fields @timestamp, log
| filter kubernetes.container_name = 'nginx'
| order by @timestamp desc
| limit 20

fields は、指定したフィールドを取得します。SQL の SELECT column1, column2 のイメージです。
filter は、抽出条件を指定します。SQL の WHERE のイメージです。
sort は、出力を並び替えます。SQL の ORDER BY のイメージです。
limit は、出力件数を指定します。SQL の LIMIT のイメージです。
ひとつ前の章で指定した Log Group は SQL の FROM のイメージです。

クエリ構文について詳細は CloudWatch Logs Insights クエリ構文 - Amazon CloudWatch Logs を参照してください。

ログの日時を指定したい場合

Logs Insights の画面の右上から対象データの日時を設定できます。Timezone も指定できます。

出力件数を数えたい場合

filter kubernetes.container_name = 'nginx'
| stats count()

stats 構文を使って集計を行うことができます。stats 構文は count の他にも max, min などいろんな集計ができます。詳細は クエリ構文 | stats - Amazon CloudWatch Logs を参照。

10 分ごとのログの件数を数えたい場合

時間ごとのログの量の分布を調べたいときなどに。

filter kubernetes.container_name = 'nginx'
| stats count() by bin(@timestamp, 10m)
2024-05-25 01:10:00.000,5679
2024-05-25 01:00:00.000,44956
2024-05-25 00:50:00.000,11454

by は SQL の GROUP BY のイメージです。binの引数には 1h なども指定できます。

10 分ごとにログの件数を数え、件数の多い順に並べ替えたい場合

ログの多い時間帯を調べたい場合などに。

filter kubernetes.container_name = 'nginx'
| stats count() as count by bin(@timestamp, 10m)
| sort count desc
"bin(@timestamp, 10m)",count
2024-05-25 01:00:00.000,44956
2024-05-25 00:50:00.000,11454
2024-05-25 01:10:00.000,5679

SQL のように、as で名前をつけて、sort の条件に指定することができます。bin には 1h なども指定できます。

ログの中の特定の文字列を抽出したい場合

以下は、ログの先頭にあるアクセス元の IP アドレスだけを出力するときの例です。

filter kubernetes.container_name = 'nginx'
| parse log /^(?<client_ip>\d+\.\d+\.\d+\.\d+)/
| display client_ip
| limit 10
client_ip
10.0.0.10
10.0.0.20
10.0.0.30

parse は、正規表現を利用してログを抽出し、それを抽出フィールドとして利用できるようにします。上記の例ではログの先頭の IP アドレス部分を名前付きキャプチャグループを使用し、client_ip という名前のフィールドにしています。詳細は クエリ構文 | parse - Amazon CloudWatch Logs を参照。

display は、指定したフィールドを表示します。最初に紹介した fields と一緒に指定した場合、display の項目が優先されます。

抽出した文字列ごとにログの件数を数えて、件数の多い順に並べ替えたい場合

さきほど抽出した IP アドレスごとにログの件数を調べ、件数の多い順に並び替える例です。

filter kubernetes.container_name = 'nginx'
| parse log /^(?<client_ip>\d+\.\d+\.\d+\.\d+)/
| stats count(*) as count by client_ip
| display client_ip, count
| sort count desc
| limit 20
client_ip,count
10.0.0.10,734
10.0.0.20,572
10.0.0.30,343

CloudWatch Logs Insights の料金

記事を書いた時点では、東京リージョンで、スキャンしたデータ 1 GB あたり USD 0.0076 が発生します。クエリを組み立てるときなど、トライアンドエラーを繰り返すときは少量のデータが対象になるようにしましょう。

詳細は Amazon CloudWatch 料金表 を参照してください。

-技術ブログ
-