ローカルPCのDocker上でCloudWatch Logs Insights連携の簡易分析基盤(Elasticsearch)を使う

AWSを運用しているCloudWatch Logsを分析することが良くあると思います。

数年前はCloudWatch Logsのファイルをダウンロードしてきて、分析していて面倒でしたが、 CloudWatch Logs Insights が出てきてそれもかなり楽になりました。

それでも毎回調べながらクエリを打つのは結構面倒なので、ログ分析基盤としてElasticsearchなどを利用する場合もあると思います。

この記事ではログ分析基盤が無い環境でも、ローカルのElasticsearchに流し込んで簡単に分析できる環境をDockerで整理したので書いていきます。

前提

  • Docker
  • docker-compose
  • git
  • chrome

全体像

JupyterLab上のPythonでログデータをロードして、Kibanaでデータを分析する構成としています。

f:id:yomon8:20200817212803p:plain

リポジトリ

github.com

使い方

ダウンロードからのコンテナ起動

上記のリポジトリをクローンしてきて、docker-compose up を実行します。 初回はElasticsearchやKibanaのイメージをダウンロードしたり、JupyterLabのイメージを構築するため時間がかかります。

git clone git@github.com:yomon8/cloudwatchlogs-elasticsearch.git
cd cloudwatchlogs-elasticsearch
docker-compose up -d

コマンドが返ってきたら以下のように3つのコンテナが起動していることを確認します。

$ docker-compose ps
 Name                Command               State                Ports
-----------------------------------------------------------------------------------
es01      /tini -- /usr/local/bin/do ...   Up      0.0.0.0:9200->9200/tcp, 9300/tcp
jupyter   /bin/sh -c jupyter lab --a ...   Up      0.0.0.0:8888->8888/tcp
kibana    /usr/local/bin/dumb-init - ...   Up      0.0.0.0:5601->5601/tcp

Jupyter Lab接続

以下からJupyterLabにアクセスします。

http://localhost:8888/lab

cwlogs_es.ipynb のnotebookを開きます。関連しそうなリンクも貼ってあります。私はElasticsearchの操作にはElasticsearch Headを好んで使っているのでそのリンクも貼っています。

f:id:yomon8:20200817224354p:plain

パラメータ設定

Pythonでパラメータ書いてあるので調整します。 f:id:yomon8:20200817223235p:plain

パラメータの補足は以下に記載しています。

AWS Profile

AWSのプロファイルです。JupyterLabにはPC上の ~/.aws をマウントしてあるので、そのまま利用できます。AWS CLIやSDKで普段利用しているプロファイル名を利用します。

# AWS Connection
aws_profile = 'YOUR_PROFILE_NAME'

以下のようにdocker-composeにマウントの記載しています。

    volumes:
      - $HOME/.aws:/root/.aws:ro
CloudWatch Logs

対象のロググループ名を書きます。複数指定可です。

cw_logs_groups=[
    '/aws/lambda/your-function-a',
    '/aws/lambda/your-function-b',
]

クエリ対象の期間を書きます。UTCです。

cw_logs_start='2020-08-16T00:00:00'
cw_logs_end='2020-08-17T00:00:00'

クエリも書けます。 AWS側の制約で limitは最大 10000件となります。

cw_logs_query=f"""
fields {' ,'.join(cw_logs_fields)}
| limit 100
"""

この時点でフィルタリングしておいた方が後々分析しやすいです。

cw_logs_query=f"""
fields {' ,'.join(cw_logs_fields)}
| filter @message like /(?i)(Exception|error|fail|5dd)/
| limit 100
"""

パラメータの調整が終わったら以下のコメントで始まるセルを実行しておきます。

###############################################
# Initialize
###############################################

データロード

Initializeのセルの実行が終われば、ロードが実行可能になります。

f:id:yomon8:20200817224852p:plain

実行すると以下のようにログが出力されます。この例では100件のログがElasticsearchに転送されました。

f:id:yomon8:20200817225117p:plain

Kibanaで分析

ここではKibanaの使い方は詳しく書きませんが、以下でアクセス可能です。

http://localhost:5601/app/kibana

デフォルトではcwlogsというインデックスで作られているはずなので、それをIndex Patternsに設定します。

f:id:yomon8:20200817225333p:plain

@timestampのフィールドをTime Filterに設定できるようにしてあります。

f:id:yomon8:20200817232253p:plain

個人的にはログ分析の場合は、基本のDiscoveryのKQLの検索機能だけでもかなり使えると思っています。JupyterLabからPythonでゴリゴリするのもアリだと思います。

f:id:yomon8:20200817230508p:plain

後片付け

以下のコマンドで全て片付けられます。

Volumeを設定しているので、docker-compose down するだけならデータはPC側のディスクに残って次回起動時に使うことが可能です。

$ docker-compose down --rmi all --volumes
Removing jupyter ... done
Removing kibana  ... done
Removing es01    ... done
Removing network cloudwatchlogselasticsearch_es-net
Removing volume cloudwatchlogselasticsearch_esdata01
Removing image docker.elastic.co/elasticsearch/elasticsearch:7.8.1
Removing image cloudwatchlogselasticsearch_jupyter
Removing image docker.elastic.co/kibana/kibana:7.8.1