Elasticsearchのトラブルシューティング

Elasticsearchのトラブルシューティングには、以下の情報をご利用ください。

Railsコンソールでの設定

Railsコンソールセッションの開始を参照してください。

属性の一覧

利用可能なすべての属性を一覧表示します:

  1. Rails コンソール (sudo gitlab-rails console) を開きます。
  2. 以下のコマンドを実行します:
ApplicationSetting.last.attributes

出力には、elasticsearch_indexingelasticsearch_urlelasticsearch_replicaselasticsearch_pause_indexingなど、Elasticsearch インテグレーションで利用可能なすべての設定がコンテナとして含まれています。

属性の設定

Elasticsearchインテグレーションを設定するには、以下のようなコマンドを実行します:

ApplicationSetting.last.update(elasticsearch_url: '<your ES URL and port>')

#or

ApplicationSetting.last.update(elasticsearch_indexing: false)

属性の取得

ElasticsearchインテグレーションやRailsコンソールで設定がされているかどうかを確認するには、以下のようなコマンドを実行します:

Gitlab::CurrentSettings.elasticsearch_url

#or

Gitlab::CurrentSettings.elasticsearch_indexing

パスワードの変更

Elasticsearchのパスワードを変更するには、以下のコマンドを実行してください:

es_url = Gitlab::CurrentSettings.current_application_settings

# Confirm the current Elasticsearch URL
es_url.elasticsearch_url

# Set the Elasticsearch URL
es_url.elasticsearch_url = "http://<username>:<password>@your.es.host:<port>"

# Save the change
es_url.save!

ログの表示

Elasticsearch インテグレーションのイシューを特定するための最も貴重なツールのひとつがログです。このインテグレーションに最も関連するログは以下の通りです:

  1. sidekiq.log - すべてのインデックス作成は Sidekiq で行われるため、Elasticsearch インテグレーションに関連するログの多くはこのファイルにあります。
  2. elasticsearch.log - このファイルには、検索、インデックス作成、マイグレーションに関する有用な診断情報を含む、Elasticsearch固有のログが追加で送信されます。

ここでは、よくある落とし穴とその克服方法について説明します。

よくある用語

  • Lucene:Javaで書かれた全文検索ライブラリ。
  • Near real time(NRT): 文書にインデックスをつけてから検索可能になるまでのわずかな待ち時間のこと。
  • クラスター:すべてのデータを保持し、インデックス作成と検索機能を提供するために連携する1つまたは複数のノードの集合体。
  • ノード:クラスターの一部として動作する単一のサーバー。
  • Index[インデックス]:インデックス:ある程度似た特徴を持つ文書の集まり。
  • Document (ドキュメント):インデックスを作成できる情報の基本単位。
  • シャード:完全に機能する、インデックスの独立した下位区分。各シャードは実際には Lucene インデックスです。
  • レプリカ:インデックスを複製するフェイルオーバー機構。

GitLabインスタンスがElasticsearchを使っていることを確認するには?

それにはいくつかの方法があります:

  • 検索を実行すると、検索結果ページの右上にAdvanced search is enabledと表示されます。これは、検索対象の現在のプロジェクト/名前空間が Elasticsearch を使用しているかどうかを常に正しく識別しています。

  • Admin AreaのSettings > Advanced Searchから、Advanced Searchの設定がチェックされていることを確認してください。

    必要に応じて、Railsコンソールからも同じ設定を取得できます:

     ::Gitlab::CurrentSettings.elasticsearch_search?         # Whether or not searches will use Elasticsearch
     ::Gitlab::CurrentSettings.elasticsearch_indexing?       # Whether or not content will be indexed in Elasticsearch
     ::Gitlab::CurrentSettings.elasticsearch_limit_indexing? # Whether or not Elasticsearch is limited only to certain projects/namespaces
    
  • Railsコンソールにアクセスして以下のコマンドを実行し、検索がElasticsearchを使用していることを確認します:

     u = User.find_by_email('email_of_user_doing_search')
     s = SearchService.new(u, {:search => 'search_term'})
     pp s.search_objects.class

    最後のコマンドの出力が重要です。最後のコマンドの出力が重要です:

    • ActiveRecord::Relationと表示された場合は、Elasticsearchを使用していません
    • Kaminari::PaginatableArrayElasticsearch を使っています
  • Elasticsearchが特定の名前空間に限定されていて、特定のプロジェクトや名前空間でElasticsearchが使われているかどうかを知る必要がある場合は、Railsコンソールを使うことができます:

     ::Gitlab::CurrentSettings.search_using_elasticsearch?(scope: Namespace.find_by_full_path("/my-namespace"))
     ::Gitlab::CurrentSettings.search_using_elasticsearch?(scope: Project.find_by_full_path("/my-namespace/my-project"))
    

インデックスのトラブルシューティング

インデックスのトラブルシューティングは厄介です。GitLabのサポートかElasticsearchの管理者に相談するのが早いでしょう。

まず始めに、空のインデックスを作成することにイシューがあるかどうかを判断するのが一番です。もしそうであれば、Elasticsearch側でgitlab-production (GitLabインデックスの名前)が存在するかどうかを確認してください。存在する場合は、Elasticsearch側で手動で削除し、recreate_index Rakeタスクから再作成を試みてください。

それでもイシューが発生する場合は、Elasticsearchインスタンスで手動でインデックスを作成してみてください。インデックスが作成できるかどうかをテストしたいので、インデックスの詳細はここでは重要ではありません。もしインデックスが

  • インデックスが作成できない場合は、Elasticsearchの管理者に相談してください。
  • GitLab サポートに連絡してください。

空のインデックスの作成がイシューでない場合、次のステップはプロジェクトのインデックス作成中にエラーが発生していないかチェックすることです。エラーが発生する場合は、インデックスの作成に原因があります:

  • GitLab側で。それらを修正する必要があります。GitLabサポートに連絡してください。
  • Elasticsearchインスタンス自体の問題。エラーが文書化されていて、修正方法があるかどうかを確認してください。もしそうでなければ、Elasticsearchの管理者に相談してください。

インデックス作成プロセスでエラーが発生しない場合は、インデックスが作成されたプロジェクトのステータスを確認してください。これは以下のRakeタスクで行うことができます:

If:

  • すべてが100%で表示されている場合、GitLabサポートにエスカレーションしてください。バグやイシューの可能性があります。
  • 100%でないものが表示されている場合は、そのプロジェクトのインデックスを再作成してください。これを行うには、sudo gitlab-rake gitlab:elastic:index_projects ID_FROM=<project ID> ID_TO=<project ID>.

プロジェクトのインデックスを再作成すると、次のようになります:

  • GitLab側のエラーが表示された場合は、GitLabサポートに連絡してください。
  • Elasticsearch のエラー、またはエラーが全く表示されない場合は、Elasticsearch 管理者に連絡してインスタンスを確認してください。

GitLabをアップデートしたのに何も見つかりません。

GitLabは継続的にインデックス作成戦略のアップデートを行い、Elasticsearchの新しいバージョンをサポートすることを目指しています。インデックスが変更された場合、GitLabをアップデートした後にインデックスを再作成する必要があるかもしれません。

すべてのリポジトリにインデックスを作成しましたが、UIで検索語がヒットしません。

すべてのデータベース・データをインデックス化したことを確認してください。

UI検索で結果(ヒット)がない場合は、Railsコンソール(sudo gitlab-rails console)で同じ結果が表示されているか確認してください:

u = User.find_by_username('your-username')
s = SearchService.new(u, {:search => 'search_term', :scope => 'blobs'})
pp s.search_objects.to_a

それ以外の場合は、Elasticsearch Search API経由でElasticsearch側にデータが表示されているか確認してください:

curl --request GET <elasticsearch_server_ip>:9200/gitlab-production/_search?q=<search_term>

より複雑な Elasticsearch API 呼び出しも可能です。

もし結果が

note
上記の手順は、ネームスペースのサブセットのインデックスのみを作成するシナリオには使用しないでください。

特定のタイプのデータを検索する方法についてはElasticsearch のインデックススコープを参照してください。

すべてのリポジトリにインデックスを作成しましたが、Elasticsearch のサーバを切り替えたら何も見つからなくなりました。

データベース、リポジトリ、Wikiのインデックスを再作成するために、すべてのRakeタスクを再実行する必要があります。

インデックス作成処理に非常に時間がかかっています。

GitLab インスタンスに存在するデータが多ければ多いほど、インデックス作成処理に時間がかかります。

インデックスが作成されていないプロジェクトがいくつかありますが、どれなのかわかりません。

sudo gitlab-rake gitlab:elastic:projects_not_indexed を実行すると、インデックスが作成されていないプロジェクトを表示できます。

コードをプッシュしても Elasticsearch インデックスに新しいデータは追加されません。

note
これは GitLab 13.2 で修正され、それ以上のバージョンでは Rake タスクは利用できません。

Blobの最初のインデックス作成を行う際、プロジェクトがインデックス作成を終えるまで全てのプロジェクトをロックします。プロセス中のエラーによって、1つまたは複数のプロジェクトがロックされたままになることがあります。ロックを解除するには、以下を実行します:

sudo gitlab-rake gitlab:elastic:clear_locked_projects

でインデックス作成に失敗しました。error: elastic: Error 429 (Too Many Requests)

ElasticCommitIndexerWorker Sidekiqワーカーがインデックス作成中にこのエラーで失敗する場合、通常、Elasticsearchがインデックス作成リクエストの同時処理についていけないことを意味します。アドレスは以下のように変更してください:

インデックス作成が非常に遅いか、rejected execution of coordinating operation メッセージで失敗します。

Elasticsearch ノードによってバルクリクエストが拒否されるのは、負荷と利用可能なメモリ不足が原因である可能性があります。Elasticsearchクラスターがシステム要件を満たし、バルクオペレーションを実行するのに十分なリソースがあることを確認してください。エラー“429 (Too Many Requests)” も参照してください。

でインデックス作成に失敗しました。strict_dynamic_mapping_exception

メジャーアップグレードを行う前にすべての高度な検索マイグレーションが終了していない場合、インデックス作成に失敗することがあります。大規模なSidekiqバックログがこのエラーを伴う可能性があります。インデックスの失敗を修正するには、データベース、リポジトリ、Wikiのインデックスを再作成する必要があります。

  1. Sidekiqが追いつくようにインデックス作成を一時停止してください:

    sudo gitlab-rake gitlab:elastic:pause_indexing
    
  2. インデックスをゼロから再作成します。
  3. インデックスの作成を再開します:

    sudo gitlab-rake gitlab:elastic:resume_indexing
    

インデックス再作成の最終手段

何らかの理由でデータがインデックス化されずキューにない場合や、インデックスが何らかの理由でマイグレーションを進められない状態になっている場合があります。ログを見ることによって問題の根本的な原因のトラブルシューティングを試みるのが常に最善です。

最後の手段として、インデックスを一から作り直すことができます。小規模なGitLabインストールでは、インデックスの再作成はいくつかのイシューを解決する手っ取り早い方法です。しかし、大規模なGitLabインストールでは、この方法はとても時間がかかるかもしれません。インデックスの作成が完了するまで、インデックスは正しい検索結果を表示しません。インデックス作成が実行されている間は、Elasticsearchを有効にして検索するチェックボックスをオフにしておくとよいでしょう。

上記の注意事項を読んで、先に進みたいと確信したのであれば、以下のRakeタスクを実行して、インデックス全体をゼロから作り直すべきです。

Linux package (Omnibus)
# WARNING: DO NOT RUN THIS UNTIL YOU READ THE DESCRIPTION ABOVE
sudo gitlab-rake gitlab:elastic:index
Self-compiled (source)
# WARNING: DO NOT RUN THIS UNTIL YOU READ THE DESCRIPTION ABOVE
cd /home/git/gitlab
sudo -u git -H bundle exec rake gitlab:elastic:index

パフォーマンスのトラブルシューティング

Elasticsearch のパフォーマンスに関するトラブルシューティングは困難です。できるチューニングは山ほどありますが、その大半は熟練したElasticsearch管理者の手に委ねられます。

一般的には

  • ElasticsearchサーバーがGitLabと同じノードで動作していないこと。
  • Elasticsearch サーバーに十分な RAM と CPU コアがあること。
  • そのシャーディングが使用されています

ここでもう少し詳しく説明すると、ElasticsearchがGitLabと同じサーバーで動いている場合、リソースの競合が発生する可能性が非常に高くなります。理想的には、十分なリソースを必要とするElasticsearchは(LogstashやKibanaと組み合わせて)独自のサーバーで実行されるべきです。

Elasticsearch に関しては RAM が重要なリソースです。Elasticsearch 自身が推奨しています:

  • 非本番インスタンスでは最低8GBのRAMが必要です。
  • 本番インスタンスでは最低16 GBのRAM。
  • 理想的には64GBのRAM。

CPUは最低2コアを推奨していますが、一般的なセットアップでは最大8コアを使用するとしています。サーバスペックの詳細についてはElasticsearchハードウェアガイドをご覧ください。

さらに、シャーディングも重要です。シャーディングは Elasticsearch の Core です。インデックスの水平スケーリングを可能にし、大量のデータを扱う場合に役立ちます。

GitLabのインデックス作成方法では、膨大な量のドキュメントがインデックスされます。シャーディングを使用することで、各シャードがLuceneインデックスになるため、Elasticsearchのデータ検索を高速化することができます。

シャーディングを使用していない場合、本番環境でElasticsearchを使い始めるとイシューにぶつかる可能性が高いです。

シャードが1つしかないインデックスにはスケールファクターがなく、ある程度の頻度で呼び出されるとイシューが発生する可能性が高いです。キャパシティプランニングについてはElasticsearchのドキュメントを参照してください。

シャーディングが使用されているかどうかを判断する最も簡単な方法は、Elasticsearch Health APIの出力を確認することです:

  • 赤はクラスターがダウンしていることを意味します。
  • 黄色はシャーディング/レプリケーションがない状態で稼働していることを意味します。
  • 緑色は健全な状態(アップ、シャーディング、レプリケーション)を意味します。

本番環境では常に緑色であるべきです。

これらのステップを踏むと、マージやキャッシュなど、より複雑なチェックが必要になります。これらは複雑になる可能性があり、習得するのに時間がかかるので、さらに詳しく調べる必要がある場合はElasticsearchのエキスパートにエスカレーション/ペアになってもらうのがベストです。

GitLabのサポートに連絡するのは構いませんが、熟練したElasticsearchの管理者の方が経験が豊富でしょう。

マイグレーションに関するイシュー

Elasticsearch マイグレーションについてお読みください。

マイグレーションが停止し、elasticsearch.log ファイルにエラーが含まれている場合、バグやイシューの可能性があります。マイグレーションを再試行しても成功しない場合は、GitLabサポートにエスカレーションしてください。

Can't specify parent if no parent field has been configured エラー

GitLab 8.12より前にElasticsearchを有効にし、インデックスを再構築していない場合、様々なケースで例外が発生します:

Elasticsearch::Transport::Transport::Errors::BadRequest([400] {
    "error": {
        "root_cause": [{
            "type": "illegal_argument_exception",
            "reason": "Can't specify parent if no parent field has been configured"
        }],
        "type": "illegal_argument_exception",
        "reason": "Can't specify parent if no parent field has been configured"
    },
    "status": 400
}):

これはGitLab 8.12でインデックスのマッピングを変更したためで、古いインデックスは削除し、再度ゼロから構築する必要があります。詳細はアップデートガイドをご覧ください。

Elasticsearch::Transport::Transport::Errors::BadRequest

この例外が発生した場合(上記のケースと同じですが、実際のメッセージは異なります)、Elasticsearchのバージョンが正しいかどうか、その他の要件を満たしているかどうかを確認してください。sudo gitlab-rake gitlab:check コマンドで自動的に確認する簡単な方法もあります。

Elasticsearch::Transport::Transport::Errors::RequestEntityTooLarge

[413] {"Message":"Request size exceeded 10485760 bytes"}

この例外は、Elasticsearchクラスタが特定のサイズ(この場合は10MiB)以上のリクエストを拒否するように設定されている場合に発生します。これはelasticsearch.ymlhttp.max_content_length の設定に相当します。 より大きなサイズに設定し、Elasticsearch クラスタを再起動してください。

AWSでは、基礎となるインスタンスのサイズに基づいて、HTTPリクエストのペイロードの最大サイズにネットワーク制限があります。最大バルクリクエストサイズを10MiBより小さい値に設定してください。

Faraday::TimeoutError (execution expired) プロキシ使用時のエラー

カスタムgitlab_rails['env'] 環境変数no_proxy に Elasticsearch ホストの IP アドレスを設定します。

シングルノードの Elasticsearch クラスタのステータスがyellow からgreen に変わりません。

シングルノードのElasticsearch クラスタの場合、機能的なクラスタの健全性ステータスは黄色です(緑になることはありません)。プライマリシャードは割り当てられていますが、Elasticsearch がレプリカを割り当てることができるノードが他にないため、レプリカを割り当てることができないためです。これはAmazon OpenSearchサービスを使用している場合にも当てはまります。

caution
レプリカの数を設定することは0 お勧めしません(GitLab Elasticsearchインテグレーションメニューでは許可されていません) 00 Elasticsearchノードをさらに追加する(合計で1つ以上のElasticsearchを追加する)予定がある場合、レプリカの数を.Doより大きい整数値に設定する必要が 0あります。 これを行わないと、冗長性が欠如します(1つのノードを失うとインデックスが破損します)。

シングルノードのElasticsearchクラスタにグリーンステータスが必要な場合は、前の段落で説明したリスクを理解した上で、以下のクエリを実行してレプリカ数を0 に設定してください(クラスターはシャードレプリカを作成しようとしなくなります):

curl --request PUT localhost:9200/gitlab-production/_settings --header 'Content-Type: application/json' \
     --data '{
       "index" : {
         "number_of_replicas" : 0
       }
     }'

health check timeout: no Elasticsearch node available Sidekiqでエラーが発生しました。

Sidekiqでインデックス作成中にhealth check timeout: no Elasticsearch node available エラーが発生した場合:

Gitlab::Elastic::Indexer::Error: time="2020-01-23T09:13:00Z" level=fatal msg="health check timeout: no Elasticsearch node available"

Elasticsearch Integration Menuの“URL “フィールドの値の一部として、http:// またはhttps:// を使用していない可能性があります。私たちが使用しているGo用ElasticsearchクライアントはURLを有効なものとして受け入れるためにプレフィックスを必要とするため、このフィールドにhttp:// またはhttps:// のいずれかを使用していることを確認してください。URLのフォーマットを修正したら、(専用のRakeタスクを使って)インデックスを削除し、インスタンスのコンテンツを再インデックスします。

私のElasticsearchクラスターにはプラグインがありますが、インテグレーションがうまくいきません。

サードパーティプラグインの中には、クラスターにバグを引き起こすものや、何らかの理由でインテグレーションと互換性がないものがあります。プラグインが問題を引き起こしている可能性を排除するために、プラグインを無効にしてみてください。

Elasticsearchcode_analyzer は全てのコードケースを考慮しているわけではありません。

code_analyzer パターンとフィルタの設定は改善のため評価中です。パターンとフィルタの設定によって期待した検索結果を返さないエッジケースのほとんどを修正しました。

code_analyzer パターンとフィルタの改善はエピック 3621 で検討されています。

バイナリファイルによっては名前で検索できない場合があります。

GitLab 13.9では、バイナリファイル名がインデックスされるように変更されました。しかし、全てのプロジェクトのデータを一からインデックス化しないと、GitLab 13.9リリース以降に追加・更新されたバイナリファイルしか検索できません。

高度な検索では非公開プロジェクトをどのように扱いますか?

高度な検索では、すべてのプロジェクトを同じ Elasticsearch インデックスに保存しますが、検索結果はユーザーが閲覧できるものだけを表示します。高度な検索は、検索時にユーザーがアクセスできないプロジェクトをフィルタリングすることで、アプリケーション内のすべての権限チェックを優遇します。

AWS Elasticsearch または OpenSearch できめ細かいアクセス制御を使用する場合のロールマッピング

IAM ロールや OpenSearch Dashboards で作成したロールを使ってきめ細かいアクセス制御を行う場合、以下のようなエラーが発生することがあります:

{"error":{"root_cause":[{"type":"security_exception","reason":"no permissions for [indices:data/write/bulk] and User [name=arn:aws:iam::xxx:role/INSERT_ROLE_NAME_HERE, backend_roles=[arn:aws:iam::xxx:role/INSERT_ROLE_NAME_HERE], requestedTenant=null]"}],"type":"security_exception","reason":"no permissions for [indices:data/write/bulk] and User [name=arn:aws:iam::xxx:role/INSERT_ROLE_NAME_HERE, backend_roles=[arn:aws:iam::xxx:role/INSERT_ROLE_NAME_HERE], requestedTenant=null]"},"status":403}

これを解決するには、Kibanaでロールをユーザーにマッピングする必要があります。

Elasticsearch ワーカーが Sidekiq にオーバーロードします。

Elasticsearch が GitLab に接続できなくなる場合があります:

  • Elasticsearch のパスワードが片方だけで更新されている (Unauthorized [401] ... unable to authenticate user エラー)。
  • ファイアウォールまたはネットワークのイシューにより接続性が損なわれています (Failed to open TCP connection to <ip>:9200 エラー)。

これらのエラーはgitlab-rails/elasticsearch.logに記録されます。エラーを取得するには、jq を使用してください:

$ jq --raw-output 'select(.severity == "ERROR") | [.error_class, .error_message] | @tsv' \
    gitlab-rails/elasticsearch.log |
  sort | uniq -c

Elastic Elasticsearch は前のジョブが失敗した場合に頻繁にインデックスを再作成しようとするため、ワーカーとSidekiq ジョブはより頻繁に現れる可能性があります。Sidekiqログのワーカーをカウントするには、fast-stats またはjq を使用できます:

$ fast-stats --print-fields=count,score sidekiq/current
WORKER                            COUNT   SCORE
ElasticIndexBulkCronWorker          234  123456
ElasticIndexInitialBulkCronWorker   345   12345
Some::OtherWorker                    12     123
...

$ jq '.class' sidekiq/current | sort | uniq -c | sort -nr
 234 "ElasticIndexInitialBulkCronWorker"
 345 "ElasticIndexBulkCronWorker"
  12 "Some::OtherWorker"
...

この場合、負荷の高いGitLabノードでfree -m 、予想外に高いbuff/cache

Couldn't load task status インデックス再作成時のエラー

再インデックス時にCouldn't load task status エラーが発生することがあります。Elasticsearch ホストでもsliceId must be greater than 0 but was [-1] エラーが表示されるかもしれません。回避策として、インデックスを一から作成し直すか、GitLab 16.3にアップグレードすることを検討してください。

詳しくはイシュー422938をご覧ください。