チュートリアル:一方向のクロスクラスター複製に基づく災害復旧
一方向のクロスクラスター複製に基づいて、2つのクラスター間でフェイルオーバーとフェイルバックを行う方法を学びます。また、双方向の災害復旧を訪れて、人間の介入なしに自動的にフェイルオーバーとフェイルバックを行うデータストリームの複製を設定することもできます。
clusterA
からclusterB
への一方向のクロスクラスター複製の設定。- フェイルオーバー -
clusterA
がオフラインになると、clusterB
はフォロワーインデックスを通常のインデックスに「昇格」させて書き込み操作を許可する必要があります。すべての取り込みはclusterB
にリダイレクトされる必要があり、これはクライアント(Logstash、Beats、Elastic Agentsなど)によって制御されます。 - フェイルバック -
clusterA
がオンラインに戻ると、フォロワーの役割を引き受け、clusterB
からリーダーインデックスを複製します。
クロスクラスター複製は、ユーザー生成インデックスのみを複製する機能を提供します。クロスクラスター複製は、システム生成インデックスやスナップショット設定を複製するために設計されておらず、クラスター間でILMやSLMポリシーを複製することはできません。クロスクラスター複製の制限事項について詳しく学びましょう。
前提条件
このチュートリアルを完了する前に、2つのクラスターを接続し、フォロワーインデックスを構成するためにクロスクラスター複製を設定してください。
このチュートリアルでは、kibana_sample_data_ecommerce
がclusterA
からclusterB
に複製されます。
Python
resp = client.cluster.put_settings(
persistent={
"cluster": {
"remote": {
"clusterA": {
"mode": "proxy",
"skip_unavailable": "true",
"server_name": "clustera.es.region-a.gcp.elastic-cloud.com",
"proxy_socket_connections": "18",
"proxy_address": "clustera.es.region-a.gcp.elastic-cloud.com:9400"
}
}
}
},
)
print(resp)
Ruby
response = client.cluster.put_settings(
body: {
persistent: {
cluster: {
remote: {
"clusterA": {
mode: 'proxy',
skip_unavailable: 'true',
server_name: 'clustera.es.region-a.gcp.elastic-cloud.com',
proxy_socket_connections: '18',
proxy_address: 'clustera.es.region-a.gcp.elastic-cloud.com:9400'
}
}
}
}
}
)
puts response
Js
const response = await client.cluster.putSettings({
persistent: {
cluster: {
remote: {
clusterA: {
mode: "proxy",
skip_unavailable: "true",
server_name: "clustera.es.region-a.gcp.elastic-cloud.com",
proxy_socket_connections: "18",
proxy_address: "clustera.es.region-a.gcp.elastic-cloud.com:9400",
},
},
},
},
});
console.log(response);
Console
### クラスターBでの設定 ###
PUT _cluster/settings
{
"persistent": {
"cluster": {
"remote": {
"clusterA": {
"mode": "proxy",
"skip_unavailable": "true",
"server_name": "clustera.es.region-a.gcp.elastic-cloud.com",
"proxy_socket_connections": "18",
"proxy_address": "clustera.es.region-a.gcp.elastic-cloud.com:9400"
}
}
}
}
}
Python
resp = client.ccr.follow(
index="kibana_sample_data_ecommerce2",
wait_for_active_shards="1",
remote_cluster="clusterA",
leader_index="kibana_sample_data_ecommerce",
)
print(resp)
Js
const response = await client.ccr.follow({
index: "kibana_sample_data_ecommerce2",
wait_for_active_shards: 1,
remote_cluster: "clusterA",
leader_index: "kibana_sample_data_ecommerce",
});
console.log(response);
Console
### クラスターBでの設定 ###
PUT /kibana_sample_data_ecommerce2/_ccr/follow?wait_for_active_shards=1
{
"remote_cluster": "clusterA",
"leader_index": "kibana_sample_data_ecommerce"
}
書き込み(取り込みや更新など)は、リーダーインデックスでのみ行う必要があります。フォロワーインデックスは読み取り専用であり、書き込みを拒否します。
クラスターAがダウンしたときのフェイルオーバー
- 1. フォロワーインデックスを
clusterB
から通常のインデックスに昇格させて、書き込みを受け入れるようにします。これは次の手順で実行できます:- まず、フォロワーインデックスのインデクシングを一時停止します。
- 次に、フォロワーインデックスを閉じます。
- リーダーインデックスのフォローを解除します。
- 最後に、フォロワーインデックスを開きます(この時点で通常のインデックスです)。
Python
resp = client.ccr.pause_follow(
index="kibana_sample_data_ecommerce2",
)
print(resp)
resp1 = client.indices.close(
index="kibana_sample_data_ecommerce2",
)
print(resp1)
resp2 = client.ccr.unfollow(
index="kibana_sample_data_ecommerce2",
)
print(resp2)
resp3 = client.indices.open(
index="kibana_sample_data_ecommerce2",
)
print(resp3)
Ruby
response = client.ccr.pause_follow(
index: 'kibana_sample_data_ecommerce2'
)
puts response
response = client.indices.close(
index: 'kibana_sample_data_ecommerce2'
)
puts response
response = client.ccr.unfollow(
index: 'kibana_sample_data_ecommerce2'
)
puts response
response = client.indices.open(
index: 'kibana_sample_data_ecommerce2'
)
puts response
Js
const response = await client.ccr.pauseFollow({
index: "kibana_sample_data_ecommerce2",
});
console.log(response);
const response1 = await client.indices.close({
index: "kibana_sample_data_ecommerce2",
});
console.log(response1);
const response2 = await client.ccr.unfollow({
index: "kibana_sample_data_ecommerce2",
});
console.log(response2);
const response3 = await client.indices.open({
index: "kibana_sample_data_ecommerce2",
});
console.log(response3);
Console
### クラスターBでの設定 ###
POST /kibana_sample_data_ecommerce2/_ccr/pause_follow
POST /kibana_sample_data_ecommerce2/_close
POST /kibana_sample_data_ecommerce2/_ccr/unfollow
POST /kibana_sample_data_ecommerce2/_open
- 2. クライアント側(Logstash、Beats、Elastic Agent)で、
kibana_sample_data_ecommerce2
の取り込みを手動で再有効化し、clusterB
にトラフィックをリダイレクトします。この間、すべての検索トラフィックをclusterB
クラスターにリダイレクトする必要があります。このインデックスにドキュメントを取り込むことでこれをシミュレートできます。このインデックスが現在書き込み可能であることに気付くはずです。
Python
resp = client.index(
index="kibana_sample_data_ecommerce2",
document={
"user": "kimchy"
},
)
print(resp)
Ruby
response = client.index(
index: 'kibana_sample_data_ecommerce2',
body: {
user: 'kimchy'
}
)
puts response
Js
const response = await client.index({
index: "kibana_sample_data_ecommerce2",
document: {
user: "kimchy",
},
});
console.log(response);
Console
### クラスターBでの設定 ###
POST kibana_sample_data_ecommerce2/_doc/
{
"user": "kimchy"
}
クラスターAが復旧したときのフェイルバック
- 1*.* リモートクラスター`````clusterB`````を`````clusterA`````に設定します。
#### Python
``````python
resp = client.cluster.put_settings(
persistent={
"cluster": {
"remote": {
"clusterB": {
"mode": "proxy",
"skip_unavailable": "true",
"server_name": "clusterb.es.region-b.gcp.elastic-cloud.com",
"proxy_socket_connections": "18",
"proxy_address": "clusterb.es.region-b.gcp.elastic-cloud.com:9400"
}
}
}
},
)
print(resp)
`
Ruby
response = client.cluster.put_settings(
body: {
persistent: {
cluster: {
remote: {
"clusterB": {
mode: 'proxy',
skip_unavailable: 'true',
server_name: 'clusterb.es.region-b.gcp.elastic-cloud.com',
proxy_socket_connections: '18',
proxy_address: 'clusterb.es.region-b.gcp.elastic-cloud.com:9400'
}
}
}
}
}
)
puts response
Js
const response = await client.cluster.putSettings({
persistent: {
cluster: {
remote: {
clusterB: {
mode: "proxy",
skip_unavailable: "true",
server_name: "clusterb.es.region-b.gcp.elastic-cloud.com",
proxy_socket_connections: "18",
proxy_address: "clusterb.es.region-b.gcp.elastic-cloud.com:9400",
},
},
},
},
});
console.log(response);
Console
### クラスターAでの設定 ###
PUT _cluster/settings
{
"persistent": {
"cluster": {
"remote": {
"clusterB": {
"mode": "proxy",
"skip_unavailable": "true",
"server_name": "clusterb.es.region-b.gcp.elastic-cloud.com",
"proxy_socket_connections": "18",
"proxy_address": "clusterb.es.region-b.gcp.elastic-cloud.com:9400"
}
}
}
}
}
- 2. 既存のデータは、インデックスをフォロワーに変更する前に破棄する必要があります。
clusterA
のインデックスを削除する前に、clusterB
に最新のデータが利用可能であることを確認してください。
Python
resp = client.indices.delete(
index="kibana_sample_data_ecommerce",
)
print(resp)
Ruby
response = client.indices.delete(
index: 'kibana_sample_data_ecommerce'
)
puts response
Js
const response = await client.indices.delete({
index: "kibana_sample_data_ecommerce",
});
console.log(response);
Console
### クラスターAでの設定 ###
DELETE kibana_sample_data_ecommerce
- 3.
clusterA
にフォロワーインデックスを作成し、clusterB
のリーダーインデックスをフォローします。
Python
resp = client.ccr.follow(
index="kibana_sample_data_ecommerce",
wait_for_active_shards="1",
remote_cluster="clusterB",
leader_index="kibana_sample_data_ecommerce2",
)
print(resp)
Js
const response = await client.ccr.follow({
index: "kibana_sample_data_ecommerce",
wait_for_active_shards: 1,
remote_cluster: "clusterB",
leader_index: "kibana_sample_data_ecommerce2",
});
console.log(response);
Console
### クラスターAでの設定 ###
PUT /kibana_sample_data_ecommerce/_ccr/follow?wait_for_active_shards=1
{
"remote_cluster": "clusterB",
"leader_index": "kibana_sample_data_ecommerce2"
}
- 4. フォロワークラスターのインデックスには、現在更新されたドキュメントが含まれています。
Python
resp = client.search(
index="kibana_sample_data_ecommerce",
q="kimchy",
)
print(resp)
Ruby
response = client.search(
index: 'kibana_sample_data_ecommerce',
q: 'kimchy'
)
puts response
Js
const response = await client.search({
index: "kibana_sample_data_ecommerce",
q: "kimchy",
});
console.log(response);
Console
### クラスターAでの設定 ###
GET kibana_sample_data_ecommerce/_search?q=kimchy
ソフト削除がフォロワーに複製される前にマージされると、リーダーの履歴が不完全なため、次のプロセスは失敗します。詳細については、index.soft_deletes.retention_lease.periodを参照してください。