Amazon Web Services ブログ

Amazon OpenSearch Service のパフォーマンストラブル解決のためのファーストステップ

Amazon OpenSearch Service を運用していく中で、クラスター構成やインデックス設定がワークロードに適していないことでパフォーマンスの問題が生じることがあります。短期的にはクラスタのスケールといった対処も必要ですが、原因を精査することがその後の運用において重要です。本記事では、パフォーマンストラブルが起きた際に確認すべきポイントを、順を追って紹介していきます。各ポイントは質問の形式で記載されているので、質問への回答を作成しながら根本原因の調査や、対処を検討するための参考情報を整理することができます。

はじめに

Amazon OpenSearch Service (Amazon Elasticsearch Service の後継サービス) は、OSS である OpenSearch および Elasticsearch のクラスタを簡単に構築し、全文検索やログ基盤といったユースケースで用いられるサービスです。OpenSearch Service ではクラスタの設定としてノード数やノードのタイプ、インデックスの設定としてシャード数などを設定してワークロードごとに適した構成を柔軟に作ることが可能です。

ただし、そういったクラスタの構成やインデックス、シャードの設定が実際のワークロードに適していないものになっている場合、レイテンシーが増加したり、スロットリングやエラーが生じるといったトラブルが起きてしまう場合があります。サイジングに関するベストプラクティスは公開されていますが、それに則って構築を行っても現実的にはその通りに行かない場合があります。例えば突発的なワークロードの増大やアプリケーションの機能追加に伴うワークロードパターンの変更など、予想外のことが起きた場合には問題が生じてしまう可能性もあります。

そういった場合に対応としてノードのスケールアップやスケールアウトを行うことでトラブルが解決してしまうこともありますが、根本の問題を特定せずに行った場合はその対応が一時しのぎにしかならなかったり、コストが無駄にかかってしまったりといったようなことが起きてしまう危険があります。トラブルが起きた際には、問題を切り分け、根本的な問題の事象を特定しそこに適切にアプローチしていくことが重要になります。

本記事は、そういったパフォーマンスに関するトラブルが起きた際にどういった項目を確認して問題を切り分けていくのか、特定した問題に対してどのような対処を行えばいいのかについて質問形式でまとめたものになります。

本記事でのトラブルシュート全体の流れとしては以下のようになります。

  1. 調査に必要なメトリクスや設定情報を取得する。
  2. 得られた情報をもとに質問への回答を行う。
  3. メトリクスとともに、回答した結果や質問の補足事項から、問題の根本原因の仮説とそれに対する対策を立てる。
  4. 対策を実施し、問題が解消されるかを観察する。

3.については仮説をもとにさらに詳細な調査を行い、ボトルネックや問題発生の条件を深ぼる必要がある場合もあります。

トラブルシュートに必要な情報の収集

トラブルシュートを行うためには調査のための材料を集める必要があります。はじめに、現在の状況を確認し質問の項目に答えるための材料を集めるのに有用なメトリクスOpenSearch APIAmazon Command Line Interface (CLI) のコマンドを説明します。
本記事ではメトリクスの確認方法 として AWS のサービスを利用して簡単に確認する方法を紹介していますが、自前で構築した OpenSearch についてもメトリクスを取得する仕組みを用意いただき同じ項目を確認することで、同様の流れでトラブルシューティングを行うことができます。

Step 1. メトリクスの確認

AWS マネジメントコンソールの OpenSearch Service の画面にはいくつかのメトリクスについてすぐに確認ができるように用意がしてあります。これらのメトリクスを確認することで簡単にトラブルシューティングのポイントを把握することができるため、まずはマネージメントコンソール上のメトリクスを確認することからはじめます。

  • 左のナビゲーションペインからドメインを選び、表示された中から対象のドメインを選択し、 インスタンスのヘルスというタブから各ノードのリソース状況の確認を行います。
  • 以下の画面ではマスターノード、データノード、UltraWarm データノードに関する CPU 使用率や JVM メモリプレッシャーといった主だったメトリクスを可視化してくれます。
  • その他にもクラスタやデータノード、Amazon Elastic Block Store (EBS) ボリュームなどに関する各種メトリクスについては Amazon CloudWatch から確認できます。本記事ではいくつかのメトリクスについて確認を行いますが、詳細については Amazon CloudWatch を用いた OpenSearch クラスターメトリクスのモニタリングを参照してください。

Step 2. AWS CLI をつかったクラスタの設定値の取得

下記の AWS CLI のコマンドはドメインに関する設定情報を取得するためのものです。詳細はドキュメントを参照してください。DOMAIN-NAME を調べたい対象のドメイン名に変更して実行してください。

# OpenSearch Service のドメインの設定情報の取得
aws opensearch describe-domain-config --domain-name DOMAIN-NAME

Step 3. OpenSearch API を使ったノード/インデックスに関する情報の取得

OpenSearch API にはさまざまな値を取得するための API が用意されていますが、次のものはそれぞれ基本的なクラスタの情報をはじめ、現在のクラスタ内のノードやインデックスの状況を把握するための API になっています。

# ノードのスペック情報取得
GET _cat/nodes?v&full_id&h=ip,id,name,node.roles,heap.max,ram.max,version,jdk,disk.total,disk.used
# ノードのディスク使用率、シャード数のサマリ情報から、負荷に偏りが無いかを確認する
GET _cat/allocation?v
# インデックス一覧取得。インデックスのサイズが適切かを確認する。
GET _cat/indices?v
# シャード一覧取得。シャードが特定ノードに偏って配置されていないかを確認する。
GET _cat/shards?v

Amazon OpenSearch Serviceでは OpenSearch を GUI で操作したりデータを可視化するためのツールである OpenSearch Dashboards がはじめから使えるようにプリインストールされています。OpenSearch Dashboards のメニューからDev Tools を選ぶことで OpenSearch に API リクエストを直接送信することができます。

また次のように、curl コマンドを使ってローカルから API を呼び出すこともできます。下記は basic 認証を使っている場合のコマンド例になります。

# ノードのスペック情報取得
curl -XGET -u user:user-password domain-endpoint/_cat/nodes?v&full_id&h=ip,id,name,node.roles,heap.max,ram.max,version,jdk,disk.total,disk.used
# ノードのディスク使用率、シャード数のサマリ情報から、負荷に偏りが無いかを確認する
curl -XGET -u user:user-password domain-endpoint/_cat/allocation?v
# インデックス一覧取得。インデックスのサイズが適切かを確認する。
curl -XGET -u user:user-password domain-endpoint/_cat/indices?v
# シャード一覧取得。シャードが特定ノードに偏って配置されていないかを確認する。
curl -XGET -u user:user-password domain-endpoint/_cat/shards?v

ここで説明している API によって取得できる各種情報に関してはトラブルシューティングを行う上での基本的な情報になるため、ひとまず全て取得することをおすすめします。

トラブルシュートのための質問

ここまでトラブルシュートに関する質問に答えるための情報を集める方法について確認してきました。ここからはその情報を使って実際に問題を特定するための質問に回答していきます。以下の図は本記事でのトラブルシュートに関する質問回答のフローチャートになります。

1. クラスタヘルスや負荷の状況から問題を切り分ける

まずは、メトリクスや問題が起きているクエリの種類からおおまかな問題の切り分けを行います。

1.1. マネージメントコンソールから確認できるクラスタの各ノードのヘルスに異常なものがありますか?

  • ヘルスが赤色の場合、プライマリシャードの一部が未割り当てになっています。この場合、自動スナップショットの取得が失敗するため以下のように原因のシャードを確認して、_reindex api_shrink api を使ってシャード数を変更するなど対応を行ってください。または、対象のインデックスが不要な場合削除してください。
    • GET /_cluster/allocation/explain でシャードの割り当てが失敗した理由を確認してください。
    • JVMMemoryPressureCPUUtilization などのメトリクスを確認して負荷に対するリソースが不足していないか確認してください。
    • 詳細については赤のクラスター状態に関するドキュメントを確認してください。
  • ヘルスが黄色の場合、レプリカシャードの一部が未割り当てになっています。

1.2. マネージメントコンソールから確認したデータノードのメトリクスからリソース使用状況インデックス作成のレイテンシー検索のレイテンシーに偏りはありますか?

  • これらのメトリクスに偏りがみられる場合、特定のノードに負荷が偏っていることが伺えます。要因としては、シャードの偏りが懸念されます。後述の、2 : シャードに関する問題を確認する を確認してください。

1.3. 問題が起きているのはインデクシング(書き込み)処理ですか?検索クエリ(読み取り)処理ですか?

  • CPU 使用率が高騰しているなどのリソースのメトリクスに異常がある場合は、どのような処理が基の原因になっているかを特定する必要があります。主に、ThreadpoolSearchQueueThreadpoolWriteQueue を確認することでどちらのリクエストが原因で負荷が上昇しているかを判断します。

2. シャードに関する問題を確認する

メトリクスから負荷の偏りが確認できる場合、シャードに関する問題が起きていることが疑われます。次に示すようなチェック項目を確認して、実際にシャードに関する問題が起きているか確認します。
OpenSearch のインデックスやシャードの設定変更の方法の詳細については Patterns for updating Amazon OpenSearch Service index settings and mappings を参考にしていただくことをお勧めします。

2.1. GET _cat/allocation?v の結果について、ノード毎のシャード数に偏りがありますか?

  • 偏りがある場合、シャード数とノード数のバランスが悪いことが考えられます。ベストプラクティスにしたがってシャード数がノード数の倍数になるように設定してください。シャードの変更には_reindex api や _shrink api を用いることができます。
  • シャード数がノード数よりも少ない場合、特定のノードのみにシャードが配置されてしまい、ノード全体からみると負荷が偏る原因になることもあります。

2.2. GET _cat/shards?v の結果について、各インデックス毎のシャードの配置について特定のノードへの偏りがありますか?

  • クラスタ全体のシャードとしては偏りがなくても、特定のインデックスのシャードに偏りがある場合そのインデックスへのクエリが原因で問題を引き起こす場合があります。
  • 偏りがある場合にはシャード数とノード数のバランスが悪いことが考えられます。この場合にもベストプラクティスにしたがってシャード数がノード数の倍数になるように設定してください。

2.3. 必要のない、または使用していないインデックスが多数ありますか?

  • 必要のないインデックスが多数あるとそれらのインデックスに関するシャードが原因で、高頻度でリクエストされるインデックスのシャードに偏りが生まれてしまう可能性が高まります。そのため必要のないインデックスについては削除するか Close することが推奨されます。また、コールドストレージにアクセス頻度の低いインデックスを移行することも検討してください。

2.4. それぞれシャードの大きさは 10 GB – 30 GB (検索ワークロードの場合)または 30 GB – 50 GB (ログワークロードの場合)に収まっていますか?

  • 1 つのシャードの大きさは小さすぎても大きすぎても問題が起きる可能性があります。シャード数がデータノード数の倍数になるように気をつけながら、_shrink api や _reindex api を用いてシャード数を変更してそれぞれのシャードの大きさを適切なサイズになるように変更してください。

2.5. 1つのノード上のシャード数が多すぎませんか?

  • 1 つのノードのシャード数の上限はデフォルトで 1000 と設定されています。しかし、それ以下でもノードのヒープメモリに対してシャード数が多すぎる場合には問題が起きる場合があります。指標として 20 シャード毎にヒープメモリ 1GiB を割り当てることが推奨されていますが、一般的に OpenSearch のヒープメモリの最大値は32 GiB になっています。そのため、シャード数が 800 程度でも注意が必要になります。
  • シャード数が多すぎる場合は、_shrink api や _reindex api を用いてシャード数を変更します。

2.6 . クラスタ全体のシャード数が非常に多くありませんか?

  • 全体のシャード数自体が非常に多くなっている場合 (具体的には 8-9 万といった規模の場合)、_shirink api を使ったシャードのマージや _reindex api によるインデックスの設定の変更を検討してください。また多くのシャードが必要になる場合には、マスターノードのリソースメトリクスも併せて確認してスケールアップを行うことも検討してください。

3. インデクシングに関わる問題を確認する

インデクシングにまつわる問題が生じている場合は、スレッドプールやキューに関連するメトリクスの状況を確認して根本の問題がどこにあるのかを特定します。

3.1. ClusterIndexWritesBlocked を確認して、書き込み処理がブロックされていませんか?

  • このメトリクスが 1 になっている場合には書き込み処理のブロックが発生しています。
  • ブロックが発生している場合にはあわせて次のメトリクスを確認してください。FreeStorageSpace が 0 になっている、或いは JVMMemoryPressure が 90 % 以上になっている場合はリソースが不足している可能性があります。それぞれについて、クラスターのスケールを検討してください。

3.2. DiskQueueDepth を確認して、書き込み待ちが発生していませんか?

  • 書き込み待ちが発生している場合には WriteIOPSWriteThroughput を確認して、EBS の設定変更による IOPS や Throughput の改善、ノードのスケールを検討してください。

3.3. ThreadpoolWriteRejectedCoordinatingWriteRejectedPrimaryWriteRejectedReplicaWriteRejected を確認して、拒否されたインデクシングのリクエストがありませんか?

  • これらのメトリクスから拒否(スロットリング) されたインデクシングリクエストがないか確認をします。ある場合は、リクエストの数が設定されている上限を超過しているかメモリが不足している可能性があります。
  • あわせて ThreadpoolWriteQueue を確認して、キューの状況を確認してください。キューに入れられたタスクの数が増えすぎている場合は CPU のリソース不足が考えられます。この場合、データノードのスケールを検討してください。また、アプリケーション側の書き込みロジックを変更することも重要になる場合があります。
  • また、IndexingRate やリソースに関するメトリクスを確認してキューにタスクが保持されているタイミングやその原因を特定してください。

3.4. IndexingRateIndexingLatency の間に相関が見られますか?

  • IndexingRate に対して IndexingLatency が顕著に増加しているといったように、これら2つのメトリクスの動きに相関がない場合は、リソースの不足が考えられます。IOPS や CPU、メモリーなどのリソースに関するメトリクスを確認して、ボトルネックを特定してください。また、3.3 の結果と合わせてキューの状態とレイテンシの増加のタイミングの関係を確認してください。

4. 検索クエリに関わる問題を確認する

インデクシング処理の場合と同様に、クエリ処理の場合も読み取りにまつわるメトリクスを確認することで根本の原因としてなにが起きているのかを特定していきます。

4.1. ThreadpoolSearchRejected を確認して、拒否された検索リクエストがありませんか?

  • このメトリクスから拒否された検索スレッドプールのタスク数を確認できます。
  • 一時的に増加している場合は問題ありませんが、継続的に拒否されたタスクが存在する場合はあわせて ThreadpoolSearchQueue を確認してキューの状態を確認してください。キューに溜まってしまっているタスクの数が常に高い状態の場合は検索クエリの処理性能に問題があるため、リソース側のメトリクスも併せて確認しスケールを検討してください。もしくは、クエリ自体や Mapping を変更することで改善が見られる場合もあります。

4.2. SearchRateSearchLatency の間に相関が見られますか?

  • インデクシングの場合と同じように、この 2 つのメトリクスを確認してレイテンシーだけが著しく増加しているような場合には、リソースの不足が懸念されます。2 つのメトリクスの乖離がおきているタイミングのリソースメトリクスを確認してボトルネックを特定します。
  • また、4.1 の結果とあわせてリクエストの拒否やキューの状態についても同じタイミングで問題が起きていないか確認します。

5. リソースのメトリクスを確認する

上述の 2 – 4 の項目の質問から問題が起こっている原因の調査を行いました。その結果をもとに問題が生じているタイミングのリソースのメトリクスを確認することで、問題の原因のボトルネックになっている箇所を特定しスケールの検討の材料にします。

5.1. CPUUtilizationWarmCPUUtilizationMasterCPUUtilization

  • 各ノードタイプごとの CPU を確認します。使用率が 80 % 以上の状態が続く場合にはスケールを検討してください。

5.2. JVMMemoryPressureWarmJVMMemoryPressure, MasterJVMMemoryPressure

  • 各ノードタイプごとの Java ヒープ領域の使用量を確認します。使用量が 80 % 以上の状態が続く場合にはスケールを検討してください。

5.3. FreeStorageSpace

  • 各ノードタイプごとの空き容量です。そもそもストレージが不足している場合には、Cluster Block Exception を伴う 403 エラーが発生することがあります。こういった場合には、 メトリクスや GET _cat/allocation API の結果からクラスタ全体とノード毎のストレージが不足していないかを確認して、不要なインデックスの削除や適宜スケールを検討してください。

6. その他確認すべきこと

6.1. クラスタの設定を確認してください。OpenSearch のバージョンは最新のものになっていますか?

  • バージョンを更新することで内部で使用されている Lucene のバージョンも新しいものになります。それによってロジックや使われているアルゴリズムの改善が伴う場合、パフォーマンスの向上が見込めます。

6.2. クラスタの設定を確認してください。EBS のタイプは gp3 ですか?

  • ボリュームタイプが gp2 の場合と比べて gp3 では 1000 GiB 以下のボリュームの場合の IOPS のベースラインが高く設定されている関係で、小規模のデータでもより安定した性能をより低価格で達成できます。
  • また、gp2 にはバーストバランスという概念があり、バーストバランスが枯渇してしまった場合に性能低下が見られる可能性がありますが、gp3 の場合にはその懸念がありません。バーストバランスの状況については BurstBalance を確認してください。
  • 詳しくはドキュメントを参照してください。

6.3. ノードタイプに t2 インスタンスもしくは t3 インスタンスを利用していませんか?

  • t系 インスタンスは CPU クレジットを消費してベースラインを超えたパフォーマンスを発揮するバーストと呼ばれる機能を使用します。しかし、CPU クレジットが枯渇してしまった場合に性能が不安定になってしまいます。とくに、t2 インスタンスは本番環境での利用が非推奨となっています。t2 インスタンスでは CPU 余剰クレジットについての無制限モードがデフォルトでオフになっています。
  • t2 タイプのインスタンスを使用していてパフォーマンスの問題が発生している場合には、CPUCreditBalance を確認してください。CPU クレジットが枯渇している場合はインスタンスタイプの変更を検討してください。
  • また、t3.small は非常に小さなワークロードを想定した設定になっているため本番環境での使用は非推奨となっています。t3.medium についても小規模なワークロード向けのオプションになっているため注意が必要です。
  • また、 t 系のインスタンスでは bootstrap.memory_lock無効化されているため、JVM メモリもスワップの対象になってしまいます。これにより、パフォーマンスが安定しなくなる場合があります。詳細はドキュメントを参照してください。

最後に

本記事では、OpenSearch Service のトラブルについて、質問形式で根本の問題を特定するためのチェックポイントをまとめました。上記の確認項目に加えて、理想的にはアプリケーション側のログやメトリクスと付き合わせることで問題特定の精度を高めることも検討してください。また、OpenSearch へのデータ投入に logstashfluentd といったツールを使用している場合にはそちらがボトルネックになっていないか確認していただくことも重要です。
OpenSearch Service を構築する際にはノード数やインデックスのシャード数などの設定についてパフォーマンスやコスト最適といった観点でのベストプラクティスが紹介されています。最初に構築する際にはこちらを参考にしていただき、そもそも問題が起きにくいような構成を検討していただくことも重要になります。
実際にトラブルが起きてしまった際には、本記事の質問への回答を実施して問題の特定のための参考にしていただければ幸いです。

著者プロフィール

深見 修平(Shuhei Fukami)
アマゾン ウェブ サービス ジャパン合同会社 ソリューションアーキテクト
2021 年 4 月に AWS Japan に入社。現在はISV/SaaS テリトリーのお客様を中心にクラウド活用の技術支援を担当しています。好きな AWS のサービスは Amazon OpenSearch Serviceです。