OpenSearchのスローログ設定時の注意点

    OpenSearchのスローログ設定時の注意点

    サムネ出典URL:https://aws.amazon.com/jp/architecture/icons/

    目次

      はじめに

      クラウドインテグレーション部の渡邊です。
      今回はAWS OpenSearchのスロークエリについて説明していきます。
      AWS OpenSearchが出力可能なログは以下4種類です。

      • インデックススローログ(ドキュメントの追加・削除・更新)
      • 検索スローログ(検索クエリ)
      • エラーログ(WARN, ERROR, FATAL, DEBUG の例外)
      • 監査ログ

      その中で検索スローログおよびインデックススローログ(以降、まとめてスローログと呼ぶ)や監査ログはAWS OpenSearchのログ設定に加え、OpenSearchDashboard側で追加の設定が必要になります。

      今回はスローログに絞って説明していきます。
      監査ログについては別の記事で紹介します。

      環境情報

      • OpenSearch 2.7
      • Amazon Linux 2023

      やってみた

      実施内容としては踏み台サーバであるEC2からOpenSearchにリクエストを送り、スローログのしきい値の設定を実施します。
      事前に、検索スローログおよびインデックススローログの有効化をAmazon OpenSearchで設定済みです。

      202310_opensearch_slow_logs_01

      スローログはしきい値を設定しないとデフォルトのしきい値がdisable(-1)なのでスローログが出力されません。
      スローログのしきい値はインデックスに直接設定することもできますが、インデックステンプレートとして設定する方法でも各インデックスでスローログを出力することができます。
      インデックステンプレートとはインデックスの標準設定を定義するもので、新しく作成したインデックスの標準設定をカスタムすることができます。

      ※事前に以下環境変数を設定してください

      USERNAME=<マスターユーザ名>
      PASSWORD=<マスターユーザパスワード>
      ENDPOINT=<OpenSearchエンドポイント>

      インデックスを試しに作成してみます。

      $ curl -XPUT  -u "${USERNAME}:${PASSWORD}"  -H "Content-Type: application/json" "https://${ENDPOINT}:443/test/_doc/1" -d '{ "A JSON": "document" }'

      {"_index":"test","_id":"1","_version":1,"result":"created","_shards":{"total":2,"successful":1,"failed":0},"_seq_no":0,"_primary_term":1}

      インデックスの設定を確認するとスローログのしきい値が設定されていません。

      $ curl -XGET -u "${USERNAME}:${PASSWORD}"  -H "Content-Type: application/json" "https://${ENDPOINT}:443/test/_settings?pretty"
      {
      "test" : {
      "settings" : {
      "index" : {
      "creation_date" : "1693296376512",
      "number_of_shards" : "5",
      "number_of_replicas" : "1",
      "uuid" : "ojZbuyKdSmSL_eLai-iRWg",
      "version" : {
      "created" : "136287827"
      },
      "provided_name" : "test"
      }
      }
      }
      }

      まず、この状況でインデックステンプレートを設定してみます。

      $ curl -XPUT -u "${USERNAME}:${PASSWORD}"  -H "Content-Type: application/json"  "https://${ENDPOINT}/_index_template/slowlog-template" -d\
      '{
      "index_patterns": [
      "*"
      ],
      "template": {
      "settings": {
      "index": {
      "search": {
      "slowlog": {
      "level": "trace",
      "threshold": {
      "query": {
      "warn": "3s",
      "trace": "3s",
      "debug": "3s",
      "info": "3s"
      },
      "fetch": {
      "warn": "3s",
      "trace": "3s",
      "debug": "3s",
      "info": "3s"
      }
      }
      }
      },
      "indexing": {
      "slowlog": {
      "level": "trace",
      "threshold": {
      "index": {
      "warn": "3s",
      "trace": "3s",
      "debug": "3s",
      "info": "3s"
      }
      }
      }
      }
      }
      }
      }
      }'

      {"acknowledged":true}

      確認すると、インデックステンプレートが作成されております。

      $ curl -XGET -u "${USERNAME}:${PASSWORD}"  -H "Content-Type: application/json"  "https://${ENDPOINT}/_index_template/slowlog-template?pretty"
      {
      "index_templates" : [
      {
      "name" : "slowlog-template",
      "index_template" : {
      "index_patterns" : [
      "*"
      ],
      "template" : {
      "settings" : {
      "index" : {
      "indexing" : {
      "slowlog" : {
      "level" : "trace",
      "threshold" : {
      "index" : {
      "warn" : "3s",
      "trace" : "3s",
      "debug" : "3s",
      "info" : "3s"
      }
      }
      }
      },
      "search" : {
      "slowlog" : {
      "level" : "trace",
      "threshold" : {
      "fetch" : {
      "warn" : "3s",
      "trace" : "3s",
      "debug" : "3s",
      "info" : "3s"
      },
      "query" : {
      "warn" : "3s",
      "trace" : "3s",
      "debug" : "3s",
      "info" : "3s"
      }
      }
      }
      }
      }
      }
      },
      "composed_of" : [ ]
      }
      }
      ]
      }

      その上で再度先ほど作成したインデックスtestを確認してもインデックスの設定が変わっていません。

      既存のインデックスに対してはインデックステンプレートが反映されませんので注意してください。

      既存のインデックスに反映させるためには直接スローログを設定してください(以下では検索スローログのしきい値のみ設定)。

      $ curl -XPUT -u "${USERNAME}:${PASSWORD}" \
      -H "Content-Type: application/json" \
      "https://${ENDPOINT}:443/test/_settings" \
      -d '{
      "index.search.slowlog.threshold.query.warn": "3s",
      "index.search.slowlog.threshold.query.info": "3s",
      "index.search.slowlog.threshold.query.debug": "3s",
      "index.search.slowlog.threshold.query.trace": "3s",
      "index.search.slowlog.level": "trace"
      }'

      {"acknowledged":true}

      インデックスtestを確認してみると、しきい値が設定されています。

      $ curl -XGET -u "${USERNAME}:${PASSWORD}"  -H "Content-Type: application/json" "https://${ENDPOINT}:443/test/_settings?pretty"
      {
      "test" : {
      "settings" : {
      "index" : {
      "search" : {
      "slowlog" : {
      "level" : "trace",
      "threshold" : {
      "query" : {
      "warn" : "3s",
      "trace" : "3s",
      "debug" : "3s",
      "info" : "3s"
      }
      }
      }
      },
      "number_of_shards" : "5",
      "provided_name" : "test",
      "creation_date" : "1693296376512",
      "number_of_replicas" : "1",
      "uuid" : "ojZbuyKdSmSL_eLai-iRWg",
      "version" : {
      "created" : "136287827"
      }
      }
      }
      }
      }

      ただ、こちらを作成の都度やるのは面倒なので、インデックステンプレートの作成をおすすめします。

      新規インデックスを作って、インデックステンプレート通りに設定がされるか試してみます。

      $ curl -XPUT  -u "${USERNAME}:${PASSWORD}"  -H "Content-Type: application/json" "https://${ENDPOINT}:443/test2/_doc/1" -d '{ "A JSON": "document" }'
      {"_index":"test2","_id":"1","_version":1,"result":"created","_shards":{"total":2,"successful":1,"failed":0},"_seq_no":0,"_primary_term":1}

      $ curl -XGET -u "${USERNAME}:${PASSWORD}" -H "Content-Type: application/json" "https://${ENDPOINT}:443/test2/_settings?pretty"
      {
      "test2" : {
      "settings" : {
      "index" : {
      "search" : {
      "slowlog" : {
      "level" : "trace",
      "threshold" : {
      "fetch" : {
      "warn" : "3s",
      "trace" : "3s",
      "debug" : "3s",
      "info" : "3s"
      },
      "query" : {
      "warn" : "3s",
      "trace" : "3s",
      "debug" : "3s",
      "info" : "3s"
      }
      }
      }
      },
      "indexing" : {
      "slowlog" : {
      "level" : "trace",
      "threshold" : {
      "index" : {
      "warn" : "3s",
      "trace" : "3s",
      "debug" : "3s",
      "info" : "3s"
      }
      }
      }
      },
      "number_of_shards" : "5",
      "provided_name" : "test2",
      "creation_date" : "1693298195323",
      "number_of_replicas" : "1",
      "uuid" : "latFK9MrT0Ss6QiWznbBTg",
      "version" : {
      "created" : "136287827"
      }
      }
      }
      }
      }

      設定されていますね。

      最後にスローログ出力の動作確認として、処理の重い検索リクエストを行います。

      サンプルデータをOpenSearchDashboardに作成するため、今回はOpenSearch Dashboards APIというものを使います。
      OpenSearch Dashboards APIはOpenSearch Dashboardの詳細設定をCUI上で実施するために使用するAPIです。
      サンプルデータを作成する理由は、検索スローログを出力するためにデータ量が多いインデックスが必要だからです(もちろん自分でたくさんのデータをインデックスに投入してもOKです)。

      そのために、APIの認証情報を使用してリクエストを送る必要があるので、以下のコマンドでAPIの認証情報を取得します。

      $ curl -curl -k -X POST  "https://${ENDPOINT}:443/_dashboards/auth/login"  \
      -H "osd-xsrf: true" \
      -H "content-type:application/json" \
      -d "{\"username\":\"${USERNAME}\", \"password\":\"${PASSWORD}\"}" \
      -c auth.txt

      {"username":"watanabe","tenants":{"global_tenant":true,"watanabe":true},"roles":["security_manager","all_access"],"backendroles":[]}

      OpenSearchでサンプルデータを作成します。

      $ curl -k  -X POST  "https://${ENDPOINT}/_dashboards/api/sample_data/logs"  \
      -H "osd-xsrf:true" \
      -H "content-type:application/json" \
      -b auth.txt

      {"opensearchIndicesCreated":{"opensearch_dashboards_sample_data_logs":14074},"opensearchDashboardsSavedObjectsLoaded":13}

      処理の重い検索リクエストを行います。

      $ curl -u "${USERNAME}:${PASSWORD}" -H "Content-Type: application/json" https://${ENDPOINT}/opensearch_dashboards_sample_data_logs/_search -d\
      '{
      "query": {
      "script": {
      "script": "long total = 0;\n for (int i = 0; i < 100000; ++i) {total += i;\n} for (int i = 0; i < 100000; ++i) {total += i;\n} for (int i = 0; i < 100000; ++i) {total += i;\n} for (int i = 0; i < 100000; ++i) {total += i;\n} for (int i = 0; i < 100000; ++i) {total += i;\n} for (int i = 0; i < 100000; ++i) {total += i;\n} for (int i = 0; i < 100000; ++i) {total += i;\n} for (int i = 0; i < 100000; ++i) { total += i;\n} for (int i = 0; i < 100000; ++i) { total += i;\n}"
      }
      }
      }'

      {"took":12054,"timed_out":false,"_shards":{"total":1,"successful":1,"skipped":0,"failed":0},"hits":{"total":{"value":0,"relation":"eq"},"max_score":null,"hits":[]}}

      CloudWatchLogsの検索スローログ/aws/OpenSearchService/domains/<ドメイン名>/search-logs確認してみると・・・

      [2023-08-29T08:53:10,789][WARN ][index.search.slowlog.query] [5f89e3ec7c749a982790d6d3040ce489] [opensearch_dashboards_sample_data_logs][0] took[5.9s], took_millis[5917], total_hits[0 hits], stats[], search_type[QUERY_THEN_FETCH], total_shards[1], source[
      {
      "query": {
      "script": {
      "script": {
      "source": "long total = 0;\n for (int i = 0; i < 100000; ++i) {total += i;\n} for (int i = 0; i < 100000; ++i) {total += i;\n} for (int i = 0; i < 100000; ++i) {total += i;\n} for (int i = 0; i < 100000; ++i) {total += i;\n} for (int i = 0; i < 100000; ++i) {total += i;\n} for (int i = 0; i < 100000; ++i) {total += i;\n} for (int i = 0; i < 100000; ++i) {total += i;\n} for (int i = 0; i < 100000; ++i) { total += i;\n} for (int i = 0; i < 100000; ++i) { total += i;\n}",
      "lang": "painless"
      },
      "boost": 1
      }
      }
      }
      ], id[],

      出てました!

      まとめ

      • スローログを出力するためにしきい値の設定を追加で実施する必要がある
      • 各インデックスにスローログの設定を都度行うより、インデックステンプレートを設定しておくことでインデックスの設定が楽になる
      • 新規のインデックスはインデックステンプレートの設定値に基づいてインデックスが作成される
      • 既存のインデックスに対してはインデックステンプレートが反映されない

      【参考】

      CloudWatchLogs有効化

      スローログのしきい値のデフォルト

      Amazon OpenSearch Service AWS Black Belt Online Seminar

      Index templates

      OpenSearch Dashboards API