Amazon OpenSearch Service クラスターにおける高い CPU 使用率をトラブルシューティングするにはどうすればよいですか?

最終更新日: 2021 年 8 月 5 日

Amazon OpenSearch Service (Amazon Elasticsearch Service の後継サービス) クラスターで、データノードが高い CPU 使用率を示しています。これを解決するにはどうすればよいですか?

簡単な説明

OpenSearch Service がタスクを実行するのに十分なリソースを必ず有しているようにするために、CPU 使用率を維持することがベストプラクティスです。一貫して高い CPU 使用率で実行するクラスターは、クラスターのパフォーマンスを低下させる可能性があります。クラスターが過負荷になると、OpenSearch Service は応答を停止し、タイムアウトリクエストが発生します。

クラスターにおける高い CPU 使用率をトラブルシューティングするには、次のアプローチを検討してください。

  • nodes hot threads API を使用します。(詳細については、Elasticsearch ウェブサイトの Nodes hot threads API をご参照ください。)
  • write 操作または bulk API スレッドプールを確認します。(詳細については、Elasticsearch ウェブサイトの Bulk API をご参照ください。)
  • search スレッドプールを確認します。(詳細については、Elasticsearch ウェブサイトの Thread pools を参照してください。)
  • Apache Lucene merge スレッドプールを確認します。(詳細については、Elasticsearch ウェブサイトの Merge を参照してください。)

解決方法

nodes hot threads API を使用する

OpenSearch Service クラスターに CPU スパイクが絶えず存在する場合は、nodes hot threads API を使用します。nodes hot threads API はタスクマネージャーとして機能し、クラスターで実行されている、リソースを大量に使用するすべてのスレッドの内訳を示します。

nodes hot threads API の出力例を次に示します。

GET _nodes/hot_threads

100.0% (131ms out of 500ms) cpu usage by thread 
'opensearch[xxx][search][T#62]' 10/10 snapshots sharing following 10 
elements sun.misc.Unsafe.park(Native Method) 
java.util.concurrent.locks.LockSupport.park(LockSupport.java:175) 
java.util.concurrent.LinkedTransferQueue.awaitMatch(LinkedTransferQueue.java:737)
 
java.util.concurrent.LinkedTransferQueue.xfer(LinkedTransferQueue.java:647)
 
java.util.concurrent.LinkedTransferQueue.take(LinkedTransferQueue.java:1269)
 
org.opensearch.common.util.concurrent.SizeBlockingQueue.take(SizeBlockingQueue.java:162)
 
java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1067)
 
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127)
 
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
java.lang.Thread.run(Thread.java:745)
注: nodes hot threads 出力には、各ノードの情報が一覧表示されます。出力の長さは、OpenSearch Service クラスターで実行されているノードの数によって異なります。

さらに、cat nodes API を使用して、リソース使用率の現在の内訳を表示します。次のコマンドを使用して、CPU 使用率が最も高いノードのサブセットを絞り込むことができます。

GET _cat/nodes?v&s=cpu:desc

出力の最後の列には、ノード名が表示されます。詳細については、Elasticsearch ウェブサイトの cat nodes API をご参照ください。

その後、関連するノード名を hot threads API に渡します。

GET _nodes/<node-name>/hot_threads

詳細については、Elasticsearch ウェブサイトの hot threads API をご参照ください。

nodes hot threads 出力は次のようになります。

<percentage> of cpu usage by thread 'opensearch[<nodeName>][<thread-name>]

スレッド名は、どの OpenSearch Service プロセスが高い CPU を消費しているかを示します。

write オペレーションまたは bulk API スレッドプールを確認する

OpenSearch Service における 429 エラーは、クラスターが処理している一括インデックス作成リクエストが多すぎることを示している可能性があります。クラスターに CPU スパイクが絶えず存在する場合、OpenSearch Service は一括インデックス作成リクエストを拒否します。

write スレッドプールは、Bulk API オペレーションを含むインデックス作成リクエストを処理します。クラスターが過度に多くの一括インデックス作成リクエストを処理しているかどうかを確認するには、Amazon CloudWatch で IndexingRate メトリクスを確認します。

クラスターが過度に多くの一括インデックス作成リクエストを処理している場合は、次のアプローチを検討してください。

  • クラスターでの一括リクエストの数を減らします。
  • 各一括リクエストのサイズを小さくして、ノードがそれらをより効率的に処理できるようにします。
  • OpenSearch Service クラスターにデータをプッシュするために Logstash が使用されている場合は、バッチサイズまたはワーカーの数を減らします。
  • クラスターの取り込み速度が遅くなる場合は、クラスターを (水平または垂直方向に) スケールします。クラスターをスケールアップするには、OpenSearch Service が受信リクエストを適切に処理できるように、ノード数とインスタンスタイプを増やします。

検索スレッドプールを確認する

CPU の使用率が高い search スレッドプールは、検索クエリが OpenSearch Service クラスターに過度な負荷をかけていることを示します。クラスターは、長時間実行される 1 つのクエリによって過負荷になる可能性があります。クラスターによって実行されるクエリの増加は、search スレッドプールにも影響する可能性があります。

1 つのクエリで CPU 使用率が増加しているかどうかを確認するには、task management API を使用します。以下はその例です。

GET _tasks?actions=*search&detailed

task management API は、クラスターで実行されているすべてのアクティブな検索クエリを取得します。詳細については、Elasticsearch ウェブサイトの Task management API をご参照ください。

この出力例を次に示します。

{
  "nodes": {
    "U4M_p_x2Rg6YqLujeInPOw": {
      "name": "U4M_p_x",
      "roles": [
        "data",
        "ingest"
      ],
      "tasks": {
        "U4M_p_x2Rg6YqLujeInPOw:53506997": {
          "node": "U4M_p_x2Rg6YqLujeInPOw",
          "id": 53506997,
          "type": "transport",
          "action": "indices:data/read/search",
          "description": """indices[*], types[], search_type[QUERY_THEN_FETCH], source[{"size":10000,"query":{"match_all":{"boost":1.0}}}]""",
          "start_time_in_millis": 1541423217801,
          "running_time_in_nanos": 1549433628,
          "cancellable": true,
          "headers": {}
        }
      }
    }
  }
}

[description] (説明) フィールドを確認して、実行されている特定のクエリを確認します。[running_time_in_nanos] フィールドは、これまでにクエリが実行された時間を示します。CPU 使用率を低減するには、高い CPU を消費している検索クエリをキャンセルします。task management API は、_cancel 呼び出しもサポートしています。

注: 特定のタスクをキャンセルするには、出力からタスク ID を記録してください。この例では、タスク ID は「U4M_p_x2Rg6YqLujeInPOw:53506997」です。

task management POST 呼び出しの例を次に示します。

POST _tasks/U4M_p_x2Rg6YqLujeInPOw:53506997/_cancel

Task Management POST コールは、タスクを「キャンセル」としてマークし、依存する AWS リソースをすべて解放します。クラスターで複数のクエリを実行している場合は、POST コールを使用してクエリを 1 つずつキャンセルします。クラスターが通常の状態に戻るまで、各クエリをキャンセルします。また、CPU スパイクが高くなるのを防ぐために、クエリ本文に適切なタイムアウト値を設定することもベストプラクティスです。(詳細については、Elasticsearch ウェブサイトの Request body search parameters をご参照ください。) アクティブなクエリの数が減ったかどうかを確認するには、Amazon CloudWatch で SearchRate メトリクスを確認します。

注: OpenSearch Service クラスターでアクティブな検索クエリをすべて同時にキャンセルすると、クライアントアプリケーション側でエラーが発生する可能性があります。

Apache Lucene merge スレッドプールを確認する

OpenSearch Service は Apache Lucene を使用して、クラスター上のドキュメントのインデックス作成と検索を行います。Apache Lucene は、merge オペレーションを実行して、各シャードに必要なセグメントの有効数を減らし、削除されたドキュメントを削除します。このプロセスは、シャードに新しいセグメントが作成されるたびに実行されます。

Apache Lucene merge スレッドオペレーションが CPU 使用率に影響を及ぼしているのを確認した場合は、OpenSearch Service クラスターインデックスの refresh_interval 設定を引き上げます。refresh_interval 設定を大きくすると、クラスターのセグメント作成が遅くなります。

: インデックスを UltraWarm ストレージに移行するクラスターは、CPU 使用率を増加させる可能性があります。UltraWarm 移行には、通常、force merge API オペレーションが含まれます。これは CPU に負荷をかける可能性があります。

UltraWarm 移行を確認するには、次のコマンドを使用します。

GET _ultrawarm/migration/_status?v