Amazon Web Services ブログ
Amazon CloudWatch Logs ストリーミングと Kibana を使用した Amazon Elasticsearch Service スローログの分析
一部のお客様から Amazon Elasticsearch Service (Amazon ES) スローログの効率的な分析についてガイダンスを求められました。こうしたお客様の声の一例を下にご紹介します。
「当社では、Amazon Elasticsearch Service 環境で動作の遅いクエリを特定し、分析してトラブルを解決したいと考えています。これはクエリを送信するアプリケーションの修正が目的です。Elasticsearch スローログが Amazon ES で提供されるようになったという記事を読みました。ブログ投稿でスローログを表示する方法の説明を読みましたが、ログが当社のパフォーマンスダッシュボード (これも Amazon ES で動作しています) に流れるようにしたいのです。設定方法を教えてください!」
スロークエリの原因を知りたいですか? 最もパフォーマンスが低いクエリを特定したいですか? インデックス設定をデバッグしますか? このブログ投稿でその方法がわかります。
ソリューションの概要
Amazon ES での Elasticsearch スローログの可用性でもお知らせしましたが、Amazon ES クラスターの設定で Amazon CloudWatch Logs にスローログを送ることができるようになりました。これでスローログメッセージを確認して、ご利用の Amazon ES クラスターのパフォーマンスをより詳しく理解し、動作が低下している検索またはインデックス作成操作を特定できます。
CloudWatch Logs は、ログメッセージを処理や追加の分析のために他のサービスに提供するサブスクリプションをサポートしています。サポートされているサブスクリプションの 1 つが Amazon ES です。Amazon ES クラスターにログを送信するようにサブスクリプションを設定すると、サブスクリプションにより AWS Lambda を使用する関数が自動的に作成されます。CloudWatch がすべてのメッセージを Lambda 関数に送信し、この関数により、メッセージはターゲットの Amazon ES クラスターに挿入されます。作成される Lambda 関数は、汎用の Lambda 関数で、すべての CloudWatch Logs メッセージに適用されます。
ただし、スローログには、分析アプリケーションで使用しやすくするために抽出してフォーマットできる追加の構造と情報があります。この投稿では、Kibana ダッシュボードを使用して、動作の遅いクエリおよびインデックス作成操作をまとめます。さらに、Kibana は詳細に調査したい項目を見つけやすくします。
このソリューションを実装するには、スローログをモニタリングする 1 つの Amazon ES クラスターが必要です。ここでは、これをソース クラスター (またはドメイン) と呼びます。また、スローログを受信する Amazon ES クラスターも必要です。これはモニタリングクラスターと呼びます。テストを目的とする場合、これらを同じドメインにすることができます。稼働中のドメインを監視するには、2 つの異なるドメインを使用します。
この投稿では、ソリューションを実装するための以下の手順を紹介します。
- CloudWatch Logs にログを送信するようにソース Amazon ES ドメインを設定する。
- 対象の Elasticsearch インデックスにスローログ構成を設定する。
- 監視 Amazon ES ドメインにスローログを送信するように CloudWatch ログストリームを設定する。
- スローログメッセージを使いやすくするため、CloudWatch によって自動的に生成される Lambda 関数を修正する。
- スローログメッセ―ジをグラフ化し、確認するように Kibana ダッシュボードを設定する。
- ダッシュボードを使用して、共通の問題を診断し、解決する。
1.CloudWatch Logs にログを送信するようにソース Amazon ES ドメインを設定する
Amazon ES クラスター (ドメインとも呼ばれる) でスローログを有効にするには、Amazon Elasticsearch Service スローログの表示の手順に従ってください。
次に、CloudWatch コンソールに移動します。設定が完了すると、2 つのロググループが表示されます。デフォルトの命名規則を使用する場合、ロググループは、/aws/aes/<domain-name>/search-logs、および /aws/aes/<domain-name>/index-logs という名前になります。
Amazon ES が CloudWatch Logs へのログの送信を開始するまで、es-test-log-stream と言う名前のストリーム以外のストリームやイベントがロググループ内に表示されないことに注意してください。このログストリームは CloudWatch Logs へのアクセスをテストするためのみに使用され、その後は使用されません。
2 つのロググループ search-logs と index-logs の形式は似ていますが、同じではありません。これは、後で見る処理コードに関係します。
スローインデックスログのプログラム行の一例を以下に示します。最後のフィールドには、挿入されたデータ項目の最初の部分が含まれます。Elasticsearch のスローログインデックス設定の一部として含まれるデータ項目の文字数を設定できます。
一方、下記は search log のプログラム行の一例です。最後の行は実行されたクエリを示しています。
これで、Amazon ES に、ソースドメインによって作成されたスローログを CloudWatch Logs に送信するように指示されました。ただし、スキャンログを送信できるようにするには、もう 1 つ追加の設定として、対象のインデックスのスローログ作成をオンにする必要があります。次の手順でそれを行います。
2.対象の Elasticsearch インデックスにスローログ構成を設定する
この手順では、スローログに記録するインデックスとイベントを定義します。Elasticsearch reference で説明しているように、スローログはインデックスごとに有効になります。デフォルトでは、スローログはすべてのインデックスで無効になっています (-1に設定)。インデックス作成時にインデックステンプレートを使用して、スローログ設定を指定できます (各インデックスに常に同じ設定を適用する場合に便利です)。また、これらの設定は、インデックス作成後にいつでも動的に更新できます。インデックスごとに、どのようなクエリまたはインデックス作成操作を「遅い」とみなすかを定義できます。
次の Elasticsearch コマンドで、既存のインデックス (testmappingdex
) を更新して、インデックスと検索の両方のスローログ設定ですべてのクエリをトレースし、インデックス作成コマンドの最初の 255 文字を取り込むように設定します。このコマンドは、Kibana Dev Tools コンソールプラグインを使って発行するか (Kibana User Guide で説明) または CURL コマンドを使って発行することができます (Viewing Amazon Elasticsearch Service Slow Logs で説明)。
別のインデックス (testmappingdex2
) については、インデックス作成操作にのみ集中して、ログの量を減らし、関心のある領域に絞り込むことを目的とします。これには次のコマンドを使用します。このコマンドはまた、トレースレベルごとに異なる閾値を追加し、インデックス作成操作をログに記録する閾値となるトレースレベルを指定します。
ログレベルごとに別の閾値を設定して、特定のパフォーマンスカテゴリのすべてのログメッセージをすばやく特定することができます (トレースレベルが “info” のすべてのログメッセージなど)。 source
パラメータは、ログメッセージに配置するインデックス作成操作の入力文字数を指定するため、特定のインデックス作成操作ごとにコンテキストを取得できます。
特定の閾値をワークロードおよび SLA に合わせて変更し、実用的な情報を取得できるようにする必要があります。ロギングによりログ作成とログ処理の両方でシステム負荷が生じることを忘れないでください。閾値を低く設定すると、ほとんどすべての操作がログに記録され、これにより CloudWatch ログの負荷が上昇する可能性があります。
現在、スローログはソースドメインから CloudWatch Logs に流れています。次に、CloudWatch Logs から Amazon ES に戻る接続を設定する必要があります。
3.監視 Amazon ES ドメインにスローログを送信するように CloudWatch ログストリームを設定する
この手順では、CloudWatch Logs ログストリームを Lambda 関数に送信するようにログストリームサブスクリプションを設定します。Lambda 関数は Amazon ES にスローログを配信します。また、インデックス用のカスタムフィルターと検索スローログ用のカスタムフィルターも設定します。
Amazon CloudWatch コンソールで、[Logs] を選択します。ロググループの一覧で、前に使用した Amazon ES ドメインの「search-logs」で終わるロググループを選択します。次に、[Actions] を選択し、[Stream to Amazon Elasticsearch Service] を選択します。
次の画面で、[This Account] を選択します。[Amazon ES cluster] ドロップダウンリストで、リストから監視ドメインを選択します。これは、スローログの宛先です。その下で、使用する Lambda 関数の既存の IAMロールを選択するか、[Create new IAM Role] を選択し、デフォルトの定義を使用します。選択した IAMロールは、ターゲットの Amazon ES クラスターへの ESHttpPost 権限および logs:CreateLogGroup、CreateLogStream、および PutLogEvents 権限を与える必要があります。また、lambda.amazonaws.com との信頼関係も持つ必要があります。
選択した後、[Next] を選択します。
次の画面の [Log Format] で、[Common Log Format] を選択します。
[Subscription Filter Pattern] でサンプルパターンを以下に置き換えます。
[Test Pattern] を選択して、サンプルログの下で、[Show test results] を選択します。パターンが一致する場合、コンソールにはそのパターンが適用された最初の 50 行が表示されます。フィールドが、予測した列と合致することを確認してください。
一部のフィールドには不要な情報 (“took[131micros]” など) が含まれています。この不要な情報がなければ、Elasticsearch のメッセージはよりわかりやすくなります。次の手順ではこれを削除します。
[Next] を選択し、設定を見直して、もう一度 [Next] を選択します。 次の画面で、作成した Lambda 関数の名前をメモしておきます。名前は、“LogsToElasticsearch_” の後にターゲットクラスターが続く形になります。[Next] を選択し、次に [Start Streaming] を選択します。
CloudWatch Logs コンソールに戻ると、ロググループの [Subscriptions] 列の下にログのストリーミング先となる Lambda 関数の一覧を表示するエントリが作成されています。
ドメインの「index-logs」で終わるロググループでこのプロセスを繰り返し、次の変更を加えます。
-
- ストリーミングされたログの宛先として同じ Amazon ES クラスターを選択すると、以前に作成した Lambda 関数が自動的に再利用されます。2 つのログタイプは少し形式が異なるため、この投稿で示したように Lambda 関数を調整し、両方のタイプを認識して処理するよう設定する必要があります。
- ログの形式は少し異なるため、代わりに次のパターンを使用してください。
これで、Lambda 関数に送られるログストリームがいくつかの基本解析と共に作成されました。ただし前述の通り、一部のフィールドに関連付けられた不要な情報を取り除いておきます。
4.スローログメッセージを使いやすくするため、CloudWatch によって生成される Lambda 関数を修正する
この手順では、受信ログメッセージの形式をさらに整理するように Lambda 関数を変更します。
AWS Lambda コンソールを開きます。サービスにより自分用に作成された Lambda 関数を選択します。[Configuration] ページで、関数コードにスクロールダウンします。提供されたコードをよく見直します。
ログメッセージが投稿されるインデックス名がコードの transform(payload)
関数に作成されていることに注意してください。提供されたコードでは、インデックス名を cwl-YYYY.MM.DD
に設定します。これにより、この Lambda 関数で受信されたすべてのログメッセージが同じ Elasticsearch インデックスに置かれ、毎日新しいインデックスが作成されます。ログ解析などの頻繁に使用される可能性のある時系列については、毎日新しいインデックスを作成するとよいでしょう。ダッシュボードで最近の期間に注目している場合、読み取る直近のデータを比較的少量にすることができます。また、もう使用されていない古いデータをより簡単にアーカイブまたは削除できます。たとえば、Kibana はダッシュボードに対するこのアプローチを効率的に使用するように最適化されています。
ただし、さまざまな種類のドキュメント (インデックススローログからのメッセージや検索スローログからのメッセージなど) を Elasticsearch 6.0 と同じ ES クラスターに保存したい場合は、これらを別々のインデックスに保存する必要があります。検索スローログとインデックススローログを同じクラスターに保存しているため、インデックスごとに異なる名前を使用する必要があります。ここに示したサンプルコードでは、検索ログの名前が cwlslowsearch-YYYY.MM.DD
に、インデックスログの名前が cwlslowindex-YYYY.MM.DD
に変更されます。
コードの見直しが終わったら、transform(payload)
関数を次のコードで置き換えます。このコードにより、前の手順で説明した不要な情報が取り除かれ、使いやすいフィールド (ロググループ名から抽出されたソース Elasticsearch ドメイン名) が追加され、インデックス名が説明どおりにに変更されます。
ここで、更新された Lambda 関数を保存します。
ご利用のドメインの Amazon ES コンソールに戻り、[Indices] タブを選択します。しばらくすると、ソースドメインのインデックスに対してインデックス作成および検索操作を行っている場合、命名規則 cwlslowsearch-YYYY.MM.DD と cwlslowindex-YYYY.MM.DD に従った新しいインデックスが表示されます。Lambda 関数への更新の直前に作成された cwl-YYYY.MM.DD 名のインデックスを削除したい場合があります。
この時点では、スローログメッセージを作成するソースドメインが存在します。このドメインはスローログメッセージを CloudWatch Logs に送り、メッセージはそこから Lambda 関数に送られて処理されます。Lambda 関数は、スローログメッセージを ES クラスターに挿入します。最後の手順では、ログ情報をダッシュボードにまとめ、それを使用してログメッセージを確認します。
同じ監視ドメインにログを記録して、Amazon ES 環境のフェデレーテッドビューを実現したい複数のソースドメインがある場合は、各ドメインを別々の CloudWatch ロギンググループに設定してください。ドメイン情報はスローログメッセージに含まれていません。このため、デフォルトの命名規則が使用されたと仮定して、先行するコードがロググループ名を解析してドメインを抽出します。複数のドメインからのメッセージが同じロググループに集められている場合、正しいソースドメインを知るには、システムの構造を考えた上で、ログメッセージからインデックス名をたどらなければなりません。
一方、ドメインごとに別々のロググループを使用している場合は、本項で説明したのと同じ方法でドメインのロググループごとに作成した Lambda 関数を変更する必要があります。また、ここのコードに示した Amazon ES インデックス命名規則を変更したい場合があります。たとえば、重要なドメインのサブセットに異なる命名規則を使用して、ログのコレクション全体をより簡単に管理し、優先順位を付けることができます。
5.スローログメッセ―ジをグラフ化し、確認するように Kibana ダッシュボードを設定する
ここで結果を確認して、ダッシュボード上で視覚化します。この手順では、監視 ES クラスター上で Kibana を使用します。Kibana は、ご利用の Amazon ES サービスの一部としてプリインストールされています。
通常使用している方法により、監視ドメイン上の Kibana をブラウザーで開きます (たとえば、こちらの方法のいずれかを使用するか、AWS マネジメントコンソールリンクを使用します)。Kibana で、左のナビゲーションバーの [Management] を選択します。[Index Patterns] を選択します。
[Configure an Index Pattern] (または、[Create Index Pattern]) を選択します。[Index Pattern] の場合、「cwlslowindex-*」と入力します。次に、[Time Filter] ドロップダウンリストで [@timestamp] を選択し、さらに [Create] を選択します。
[Create Index Pattern] を選択して、別のインデックスパターンを追加します。今回は、「cwlslowsearch-*」と入力します。もう一度、[Time Filter] ドロップダウンリストで [@timestamp] を選択します。
視覚化データの作成
次に、それぞれのインデックスの視覚化データを作成します。
まず、スロー検索インデックスの場合、Kibana の左側のナビゲーションパネルで [visualize] を選択します。[+] (プラス記号) を選択して、新しい視覚化データを作成し、次に線グラフを選択します。[cwlslowsearch] インデックスパターンを選択します。
[Data] パネルで、次の手順を実行します。
- [Y-Axis] の下で:
- 最もパフォーマンスの低いクエリに注目するため、[Aggregation] では Max を選択します。
- [Field] では、[took_millis] を選択します。これに「Max_millis」というカスタムラベルを付けます。
- また [Y-Axis] で [Add Metrics] を選択します。[Y-Axis] のメトリックの種類を選択します。
- [Aggregation] では [Average] を選択し、[Field] では、[took_millis] を選択します。
- これに「Avg_millis」というカスタムラベルを付けます。これにより、最大クエリ数と平均クエリ数の差が表示されます。こうして、パフォーマンスが低いクエリが多いのか、外れ値のクエリが少ないのかなどがわかります。
- [X 軸] の下で:
- [Aggregation] では [Date Histogram] を選択し、[Field] では [@timestamp] を選択します。
- [Interval] では [Minute] を選択します。
- パネル上部の青色の三角形を選択して設定を適用します。
- グラフが、次の項に示すダッシュボードのスクリーンショットにあるものと同様であることを確認します。(ドメインが 1 つしかない場合、線は 1 本しか表示されません。)
- Kibana ページの上部で、[Save] を選択し、視覚化データに「slowsearchviz」などの名前を付けます。[Save] を選択します。
同じ手順に従って、cwlslowindex インデックスの視覚化データを作成し、「slowindexviz」などの名前を付けて保存します。
スローログダッシュボードの作成
次に、Kibana の左のナビゲーションバーで [Dashboard] を選択します。[+] (プラス記号) を選択して、新しいダッシュボードを追加します。上部のナビゲーションバーで [Add] を選択し、作成した 2 つの視覚化データを選択します。Kibana により、視覚化データがダッシュボードに追加されます。
上部のナビゲーションバーで [Save] を選択し、名前を付けます。再度 [Save] を選択して保存します。データを同じメトリック クラスターに集める複数のドメインがある場合 (今回の例の通り)、注目する 1 つのドメインに結果を絞り込むために、フィルター (スクリーンショット参照) を追加する必要があります。
次に示すダッシュボードでは、興味がある場合に見やすいよう、一組の円グラフと値 (最大ミリ秒数) を追加しました。
6.ダッシュボードを使用して、共通の問題を診断し、解決する
このようなダッシュボードは、さまざまな問題を見つけて修正するのに役立ちます。ここではよくある 3 つの問題を紹介します。いずれも情報を素早く入手できなければ対応が難しくなる問題です。
問題 1.この時々遅くなるクエリは何だろう?
この場合、ダッシュボードに注目すべき特定のデータポイントがあれば、その上にカーソルを合わせて値とタイムスタンプを表示します。この情報を元に対象のクエリを特定することができます。
外れ値 (動作の遅い検索) を見つけたとします。Kibana の左のナビゲーションバーで [Discover] を選択し、内側左のナビゲーションバーで [cwlslowsearch*] インデックスパターンを選択します。Kibana には、ページの右上で選択した期間のログエントリが表示されます。Kibana の検索機能を使用して、特定のエントリに絞り込み、実行中のクエリを含めたログエントリ全体を表示できます (次の例では、私が実行していた負荷生成スクリプトで生成された「すべて一致」のクエリ)。
問題 2.すべてのクエリが遅いのか、それとも一部のクエリだけだろうか?
ある状況で、平均クエリ応答時間の計算に基づいて、ドメインが報告された SLA を超えていました。次に示すようなグラフ (最大、平均および中間値を示す) を見て、中間応答数が SLA 内であることがわかりました。さらに、大半のクエリが優良な応答を取得しており、ここに示したピークのように、外れ値は少数でした。問題のクエリを詳しく調べると、すべての場合で問題となるのは同様の複雑なクエリであることがわかりました。根本の原因は、ユーザーから無効な入力を受け取ったときのアプリケーションエラーでした。
問題 3.不良なインデックス設定
別の状況では、一部のクエリで応答時間が遅くなっていました。Kibana で問題のセットを調査したところ、[Discover] パネルで、遅いクエリはすべてインデックス上で、また同じノード上で実行されていたことがわかりました。さらに調べると、この使用頻度の高いインデックスが (エラー発生時に) 1 つの共有インデックスを持つものとして定義され、負荷動作時にレプリカがなく、一度もリセットされることがなかったことが明らかになりました。インデックスにレプリカを追加することで、クエリの負荷をすべてのクラスターノードに分散し、クエリのパフォーマンスをすぐに期待どおりの値に戻すことができました。
結論
CloudWatch Logs を Amazon Elasticsearch Service に統合して利用することにより、スローログをより簡単に Elasticsearch 環境に戻すことができます。これで、今までご利用のものと同じツールでスローログを表示し、分析することができるようになりました。Kibana の機能を利用してスローログを表示し、調査することにより、Elasticsearch 環境をさらに詳細に管理し、分析することができます。ご活用ください!
- このブログで使用したコードはすべて、Apache 2.0 の下でライセンス許諾されています。
著者について
Veronika Megler は、アマゾン ウェブ サービスのコンサルタントです。 AWS の顧客と協力してデータベースプロジェクトに関する助言や技術支援を行い、AWS を使用する場面でソリューションの価値を向上するお手伝いをしています。