ノードが離脱したときの割り当ての遅延

ノードが意図的またはその他の理由でクラスターを離脱すると、マスターは次のように反応します:

  • ノード上のプライマリを置き換えるために、レプリカシャードをプライマリに昇格させます。
  • 不足しているレプリカを置き換えるためにレプリカシャードを割り当てます(十分なノードがあると仮定します)。
  • 残りのノードにシャードを均等に再バランスします。

これらのアクションは、すべてのシャードができるだけ早く完全にレプリケートされることを保証することによって、データ損失からクラスターを保護することを目的としています。

ノードレベルとクラスターレベルの両方で同時回復を制限しているにもかかわらず、ノードレベルおよびクラスターレベルで、この「シャードシャッフル」は、欠落しているノードがすぐに戻る可能性がある場合には、クラスターに不必要な負荷をかける可能性があります。このシナリオを想像してください:

  • ノード5がネットワーク接続を失います。
  • マスターはノード5にあった各プライマリのためにレプリカシャードをプライマリに昇格させます。
  • マスターはクラスター内の他のノードに新しいレプリカを割り当てます。
  • 各新しいレプリカは、ネットワークを介してプライマリシャードの完全なコピーを作成します。
  • クラスターを再バランスするために、より多くのシャードが異なるノードに移動します。
  • ノード5は数分後に戻ります。
  • マスターはノード5にシャードを割り当ててクラスターを再バランスします。

もしマスターが数分待っていたら、欠落しているシャードは最小限のネットワークトラフィックでノード5に再割り当てされていたでしょう。このプロセスは、フラッシュされたアイドルシャード(インデックスリクエストを受け取っていないシャード)に対してはさらに迅速です。

ノードが離脱したために未割り当てとなったレプリカシャードの割り当ては、index.unassigned.node_left.delayed_timeoutの動的設定で遅延させることができ、デフォルトは1mです。

この設定は、ライブインデックス(またはすべてのインデックス)で更新できます:

Python

  1. resp = client.indices.put_settings(
  2. index="_all",
  3. settings={
  4. "settings": {
  5. "index.unassigned.node_left.delayed_timeout": "5m"
  6. }
  7. },
  8. )
  9. print(resp)

Ruby

  1. response = client.indices.put_settings(
  2. index: '_all',
  3. body: {
  4. settings: {
  5. 'index.unassigned.node_left.delayed_timeout' => '5m'
  6. }
  7. }
  8. )
  9. puts response

Js

  1. const response = await client.indices.putSettings({
  2. index: "_all",
  3. settings: {
  4. settings: {
  5. "index.unassigned.node_left.delayed_timeout": "5m",
  6. },
  7. },
  8. });
  9. console.log(response);

コンソール

  1. PUT _all/_settings
  2. {
  3. "settings": {
  4. "index.unassigned.node_left.delayed_timeout": "5m"
  5. }
  6. }

遅延割り当てが有効になっている場合、上記のシナリオは次のように変わります:

  • ノード5がネットワーク接続を失います。
  • マスターはノード5にあった各プライマリのためにレプリカシャードをプライマリに昇格させます。
  • マスターは未割り当てシャードの割り当てが遅延したことと、その期間を記録します。
  • 未割り当てのレプリカシャードがあるため、クラスターは黄色のままです。
  • ノード5は数分後に戻り、timeoutが期限切れになる前に戻ります。
  • 欠落しているレプリカはノード5に再割り当てされます(同期フラッシュされたシャードはほぼ即座に回復します)。

この設定は、レプリカをプライマリに昇格させることには影響せず、以前に割り当てられていないレプリカの割り当てにも影響しません。特に、遅延割り当てはクラスターの完全な再起動後には発効しません。また、マスターのフェイルオーバー状況では、経過した遅延時間は忘れられます(つまり、初期の遅延にリセットされます)。

シャード移動のキャンセル

遅延割り当てがタイムアウトすると、マスターは欠落しているシャードを別のノードに割り当て、回復を開始します。欠落しているノードがクラスターに再参加し、そのシャードがプライマリと同じsync-idを持っている場合、シャードの移動はキャンセルされ、同期されたシャードが回復に使用されます。

この理由から、デフォルトのtimeoutはわずか1分に設定されています:シャードの移動が始まった場合でも、同期されたシャードを優先して回復をキャンセルするのは安価です。

遅延した未割り当てシャードの監視

このタイムアウト設定によって割り当てが遅延したシャードの数は、クラスターのヘルスAPIで確認できます:

Python

  1. resp = client.cluster.health()
  2. print(resp)

Ruby

  1. response = client.cluster.health
  2. puts response

Js

  1. const response = await client.cluster.health();
  2. console.log(response);

コンソール

  1. GET _cluster/health
このリクエストはdelayed_unassigned_shardsの値を返します。

ノードを永久に削除する

ノードが戻らない場合、Elasticsearchに欠落しているシャードを即座に割り当てさせたい場合は、タイムアウトをゼロに更新するだけです:

Python

  1. resp = client.indices.put_settings(
  2. index="_all",
  3. settings={
  4. "settings": {
  5. "index.unassigned.node_left.delayed_timeout": "0"
  6. }
  7. },
  8. )
  9. print(resp)

Ruby

  1. response = client.indices.put_settings(
  2. index: '_all',
  3. body: {
  4. settings: {
  5. 'index.unassigned.node_left.delayed_timeout' => '0'
  6. }
  7. }
  8. )
  9. puts response

Js

  1. const response = await client.indices.putSettings({
  2. index: "_all",
  3. settings: {
  4. settings: {
  5. "index.unassigned.node_left.delayed_timeout": "0",
  6. },
  7. },
  8. });
  9. console.log(response);

コンソール

  1. PUT _all/_settings
  2. {
  3. "settings": {
  4. "index.unassigned.node_left.delayed_timeout": "0"
  5. }
  6. }

欠落しているシャードが回復を開始したら、すぐにタイムアウトをリセットできます。