チュートリアル:一方向のクロスクラスター複製に基づく災害復旧

一方向のクロスクラスター複製に基づいて、2つのクラスター間でフェイルオーバーとフェイルバックを行う方法を学びます。また、双方向の災害復旧を訪れて、人間の介入なしに自動的にフェイルオーバーとフェイルバックを行うデータストリームの複製を設定することもできます。

  • clusterAからclusterBへの一方向のクロスクラスター複製の設定。
  • フェイルオーバー - clusterAがオフラインになると、clusterBはフォロワーインデックスを通常のインデックスに「昇格」させて書き込み操作を許可する必要があります。すべての取り込みはclusterBにリダイレクトされる必要があり、これはクライアント(Logstash、Beats、Elastic Agentsなど)によって制御されます。
  • フェイルバック - clusterAがオンラインに戻ると、フォロワーの役割を引き受け、clusterBからリーダーインデックスを複製します。

一方向のクロスクラスター複製のフェイルオーバーとフェイルバック

クロスクラスター複製は、ユーザー生成インデックスのみを複製する機能を提供します。クロスクラスター複製は、システム生成インデックスやスナップショット設定を複製するために設計されておらず、クラスター間でILMやSLMポリシーを複製することはできません。クロスクラスター複製の制限事項について詳しく学びましょう。

前提条件

このチュートリアルを完了する前に、2つのクラスターを接続し、フォロワーインデックスを構成するためにクロスクラスター複製を設定してください。

このチュートリアルでは、kibana_sample_data_ecommerceclusterAからclusterBに複製されます。

Python

  1. resp = client.cluster.put_settings(
  2. persistent={
  3. "cluster": {
  4. "remote": {
  5. "clusterA": {
  6. "mode": "proxy",
  7. "skip_unavailable": "true",
  8. "server_name": "clustera.es.region-a.gcp.elastic-cloud.com",
  9. "proxy_socket_connections": "18",
  10. "proxy_address": "clustera.es.region-a.gcp.elastic-cloud.com:9400"
  11. }
  12. }
  13. }
  14. },
  15. )
  16. print(resp)

Ruby

  1. response = client.cluster.put_settings(
  2. body: {
  3. persistent: {
  4. cluster: {
  5. remote: {
  6. "clusterA": {
  7. mode: 'proxy',
  8. skip_unavailable: 'true',
  9. server_name: 'clustera.es.region-a.gcp.elastic-cloud.com',
  10. proxy_socket_connections: '18',
  11. proxy_address: 'clustera.es.region-a.gcp.elastic-cloud.com:9400'
  12. }
  13. }
  14. }
  15. }
  16. }
  17. )
  18. puts response

Js

  1. const response = await client.cluster.putSettings({
  2. persistent: {
  3. cluster: {
  4. remote: {
  5. clusterA: {
  6. mode: "proxy",
  7. skip_unavailable: "true",
  8. server_name: "clustera.es.region-a.gcp.elastic-cloud.com",
  9. proxy_socket_connections: "18",
  10. proxy_address: "clustera.es.region-a.gcp.elastic-cloud.com:9400",
  11. },
  12. },
  13. },
  14. },
  15. });
  16. console.log(response);

Console

  1. ### クラスターBでの設定 ###
  2. PUT _cluster/settings
  3. {
  4. "persistent": {
  5. "cluster": {
  6. "remote": {
  7. "clusterA": {
  8. "mode": "proxy",
  9. "skip_unavailable": "true",
  10. "server_name": "clustera.es.region-a.gcp.elastic-cloud.com",
  11. "proxy_socket_connections": "18",
  12. "proxy_address": "clustera.es.region-a.gcp.elastic-cloud.com:9400"
  13. }
  14. }
  15. }
  16. }
  17. }

Python

  1. resp = client.ccr.follow(
  2. index="kibana_sample_data_ecommerce2",
  3. wait_for_active_shards="1",
  4. remote_cluster="clusterA",
  5. leader_index="kibana_sample_data_ecommerce",
  6. )
  7. print(resp)

Js

  1. const response = await client.ccr.follow({
  2. index: "kibana_sample_data_ecommerce2",
  3. wait_for_active_shards: 1,
  4. remote_cluster: "clusterA",
  5. leader_index: "kibana_sample_data_ecommerce",
  6. });
  7. console.log(response);

Console

  1. ### クラスターBでの設定 ###
  2. PUT /kibana_sample_data_ecommerce2/_ccr/follow?wait_for_active_shards=1
  3. {
  4. "remote_cluster": "clusterA",
  5. "leader_index": "kibana_sample_data_ecommerce"
  6. }

書き込み(取り込みや更新など)は、リーダーインデックスでのみ行う必要があります。フォロワーインデックスは読み取り専用であり、書き込みを拒否します。

クラスターAがダウンしたときのフェイルオーバー

  • 1. フォロワーインデックスをclusterBから通常のインデックスに昇格させて、書き込みを受け入れるようにします。これは次の手順で実行できます:
    • まず、フォロワーインデックスのインデクシングを一時停止します。
    • 次に、フォロワーインデックスを閉じます。
    • リーダーインデックスのフォローを解除します。
    • 最後に、フォロワーインデックスを開きます(この時点で通常のインデックスです)。

Python

  1. resp = client.ccr.pause_follow(
  2. index="kibana_sample_data_ecommerce2",
  3. )
  4. print(resp)
  5. resp1 = client.indices.close(
  6. index="kibana_sample_data_ecommerce2",
  7. )
  8. print(resp1)
  9. resp2 = client.ccr.unfollow(
  10. index="kibana_sample_data_ecommerce2",
  11. )
  12. print(resp2)
  13. resp3 = client.indices.open(
  14. index="kibana_sample_data_ecommerce2",
  15. )
  16. print(resp3)

Ruby

  1. response = client.ccr.pause_follow(
  2. index: 'kibana_sample_data_ecommerce2'
  3. )
  4. puts response
  5. response = client.indices.close(
  6. index: 'kibana_sample_data_ecommerce2'
  7. )
  8. puts response
  9. response = client.ccr.unfollow(
  10. index: 'kibana_sample_data_ecommerce2'
  11. )
  12. puts response
  13. response = client.indices.open(
  14. index: 'kibana_sample_data_ecommerce2'
  15. )
  16. puts response

Js

  1. const response = await client.ccr.pauseFollow({
  2. index: "kibana_sample_data_ecommerce2",
  3. });
  4. console.log(response);
  5. const response1 = await client.indices.close({
  6. index: "kibana_sample_data_ecommerce2",
  7. });
  8. console.log(response1);
  9. const response2 = await client.ccr.unfollow({
  10. index: "kibana_sample_data_ecommerce2",
  11. });
  12. console.log(response2);
  13. const response3 = await client.indices.open({
  14. index: "kibana_sample_data_ecommerce2",
  15. });
  16. console.log(response3);

Console

  1. ### クラスターBでの設定 ###
  2. POST /kibana_sample_data_ecommerce2/_ccr/pause_follow
  3. POST /kibana_sample_data_ecommerce2/_close
  4. POST /kibana_sample_data_ecommerce2/_ccr/unfollow
  5. POST /kibana_sample_data_ecommerce2/_open
  • 2. クライアント側(Logstash、Beats、Elastic Agent)で、kibana_sample_data_ecommerce2の取り込みを手動で再有効化し、clusterBにトラフィックをリダイレクトします。この間、すべての検索トラフィックをclusterBクラスターにリダイレクトする必要があります。このインデックスにドキュメントを取り込むことでこれをシミュレートできます。このインデックスが現在書き込み可能であることに気付くはずです。

Python

  1. resp = client.index(
  2. index="kibana_sample_data_ecommerce2",
  3. document={
  4. "user": "kimchy"
  5. },
  6. )
  7. print(resp)

Ruby

  1. response = client.index(
  2. index: 'kibana_sample_data_ecommerce2',
  3. body: {
  4. user: 'kimchy'
  5. }
  6. )
  7. puts response

Js

  1. const response = await client.index({
  2. index: "kibana_sample_data_ecommerce2",
  3. document: {
  4. user: "kimchy",
  5. },
  6. });
  7. console.log(response);

Console

  1. ### クラスターBでの設定 ###
  2. POST kibana_sample_data_ecommerce2/_doc/
  3. {
  4. "user": "kimchy"
  5. }

クラスターAが復旧したときのフェイルバック

  1. - 1*.* リモートクラスター`````clusterB``````````clusterA`````に設定します。
  2. #### Python
  3. ``````python
  4. resp = client.cluster.put_settings(
  5. persistent={
  6. "cluster": {
  7. "remote": {
  8. "clusterB": {
  9. "mode": "proxy",
  10. "skip_unavailable": "true",
  11. "server_name": "clusterb.es.region-b.gcp.elastic-cloud.com",
  12. "proxy_socket_connections": "18",
  13. "proxy_address": "clusterb.es.region-b.gcp.elastic-cloud.com:9400"
  14. }
  15. }
  16. }
  17. },
  18. )
  19. print(resp)
  20. `

Ruby

  1. response = client.cluster.put_settings(
  2. body: {
  3. persistent: {
  4. cluster: {
  5. remote: {
  6. "clusterB": {
  7. mode: 'proxy',
  8. skip_unavailable: 'true',
  9. server_name: 'clusterb.es.region-b.gcp.elastic-cloud.com',
  10. proxy_socket_connections: '18',
  11. proxy_address: 'clusterb.es.region-b.gcp.elastic-cloud.com:9400'
  12. }
  13. }
  14. }
  15. }
  16. }
  17. )
  18. puts response

Js

  1. const response = await client.cluster.putSettings({
  2. persistent: {
  3. cluster: {
  4. remote: {
  5. clusterB: {
  6. mode: "proxy",
  7. skip_unavailable: "true",
  8. server_name: "clusterb.es.region-b.gcp.elastic-cloud.com",
  9. proxy_socket_connections: "18",
  10. proxy_address: "clusterb.es.region-b.gcp.elastic-cloud.com:9400",
  11. },
  12. },
  13. },
  14. },
  15. });
  16. console.log(response);

Console

  1. ### クラスターAでの設定 ###
  2. PUT _cluster/settings
  3. {
  4. "persistent": {
  5. "cluster": {
  6. "remote": {
  7. "clusterB": {
  8. "mode": "proxy",
  9. "skip_unavailable": "true",
  10. "server_name": "clusterb.es.region-b.gcp.elastic-cloud.com",
  11. "proxy_socket_connections": "18",
  12. "proxy_address": "clusterb.es.region-b.gcp.elastic-cloud.com:9400"
  13. }
  14. }
  15. }
  16. }
  17. }
  • 2. 既存のデータは、インデックスをフォロワーに変更する前に破棄する必要があります。clusterAのインデックスを削除する前に、clusterBに最新のデータが利用可能であることを確認してください。

Python

  1. resp = client.indices.delete(
  2. index="kibana_sample_data_ecommerce",
  3. )
  4. print(resp)

Ruby

  1. response = client.indices.delete(
  2. index: 'kibana_sample_data_ecommerce'
  3. )
  4. puts response

Js

  1. const response = await client.indices.delete({
  2. index: "kibana_sample_data_ecommerce",
  3. });
  4. console.log(response);

Console

  1. ### クラスターAでの設定 ###
  2. DELETE kibana_sample_data_ecommerce
  • 3. clusterAにフォロワーインデックスを作成し、clusterBのリーダーインデックスをフォローします。

Python

  1. resp = client.ccr.follow(
  2. index="kibana_sample_data_ecommerce",
  3. wait_for_active_shards="1",
  4. remote_cluster="clusterB",
  5. leader_index="kibana_sample_data_ecommerce2",
  6. )
  7. print(resp)

Js

  1. const response = await client.ccr.follow({
  2. index: "kibana_sample_data_ecommerce",
  3. wait_for_active_shards: 1,
  4. remote_cluster: "clusterB",
  5. leader_index: "kibana_sample_data_ecommerce2",
  6. });
  7. console.log(response);

Console

  1. ### クラスターAでの設定 ###
  2. PUT /kibana_sample_data_ecommerce/_ccr/follow?wait_for_active_shards=1
  3. {
  4. "remote_cluster": "clusterB",
  5. "leader_index": "kibana_sample_data_ecommerce2"
  6. }
  • 4. フォロワークラスターのインデックスには、現在更新されたドキュメントが含まれています。

Python

  1. resp = client.search(
  2. index="kibana_sample_data_ecommerce",
  3. q="kimchy",
  4. )
  5. print(resp)

Ruby

  1. response = client.search(
  2. index: 'kibana_sample_data_ecommerce',
  3. q: 'kimchy'
  4. )
  5. puts response

Js

  1. const response = await client.search({
  2. index: "kibana_sample_data_ecommerce",
  3. q: "kimchy",
  4. });
  5. console.log(response);

Console

  1. ### クラスターAでの設定 ###
  2. GET kibana_sample_data_ecommerce/_search?q=kimchy

ソフト削除がフォロワーに複製される前にマージされると、リーダーの履歴が不完全なため、次のプロセスは失敗します。詳細については、index.soft_deletes.retention_lease.periodを参照してください。