Elasticsearch AWS で Multi-AZ 配置

検索パフォーマンスも考慮してAWSでマルチAZ配置する


AWSでは高可用性を高めるためにマルチAZの配置を推奨しています。サーバーをマルチZA配置にすることで、物理的に独立した複数のAZ (Availability Zone)にサーバーを稼働させることができるので、障害に強いシステムを構築できる素晴らしい仕組みです。

いいことずくめの仕組みなのですが、唯一の欠点はAZ間のレイテンシです。Elasticsearchは受け付けた検索要求をすべてのシャードへ問い合わせる仕組みのため、マルチAZ配置にするとAZ間の通信が発生してしまうので、どうしてもパフォーマンスが落ちてしまいます。

これを避けるには、1つのAZ内に配置されているElasticsearchのノードだけで完全なインデックス(シャード)を保持し、受け付けた検索要求は同じAZ内で検索を完結できるように構成する必要があります。それを実現するのが Shard Allocation Awareness です。

Shard Allocation Awareness

シャードの配置とかの話なので、なんとなく難しそうですが、Elasticsearchのオンラインリファレンスの Shard Allocation AwarenessForced Awareness あたりを見てもらうと、比較的簡単に設定できることがわかるかと思います。

以下の例では、東京リージョンの ap-northeast-1a と ap-northeast-1c を使って、それぞのAZごとにShard Allocation Awareness の設定をしています。node.zone に設定している値はわかりやすいようにAZの名前を設定していますが、任意の値で設定できます。

AZ: ap-northeast-1a の設定例:

node.zone: ap-northeast-1a
cluster.routing.allocation.awareness.attributes: zone
cluster.routing.allocation.awareness.force.zone.values: ap-northeast-1a,ap-northeast-1c

AZ: ap-northeast-1c の設定例:

node.zone: ap-northeast-1c
cluster.routing.allocation.awareness.attributes: zone
cluster.routing.allocation.awareness.force.zone.values: ap-northeast-1a,ap-northeast-1c

それでは、AZ内のノードを増やしたり減らしたりしてシャードの配置がどうなるか見てみましょう。

まずは、AZそれぞに1台づつノードを起動した例です。インデックスは5シャード1レプリカで構成しています。

[node.zone: ap-northeast-1a]
index shard prirep state node
twitter 0 p STARTED Node1
twitter 1 p STARTED Node1
twitter 2 p STARTED Node1
twitter 3 p STARTED Node1
twitter 4 p STARTED Node1
[node.zone: ap-northeast-1c]
index shard prirep state node
twitter 0 r STARTED Node2
twitter 1 r STARTED Node2
twitter 2 r STARTED Node2
twitter 3 r STARTED Node2
twitter 4 r STARTED Node2

1台づつだと特に変わったところはないですね。

次に、ap-northeast-1a のみ1台追加してみます。すると、以下のようにap-northeast-1c のシャードは何も再配置されずに、ap-northeast-1a 内のシャードのみ新しく起動したNode3に再配置されます。

[node.zone: ap-northeast-1a]
index shard prirep state node
twitter 0 p STARTED Node1
twitter 1 p STARTED Node1
twitter 2 p STARTED Node3
twitter 3 p STARTED Node3
twitter 4 p STARTED Node3
[node.zone: ap-northeast-1c]
index shard prirep state node
twitter 0 r STARTED Node2
twitter 1 r STARTED Node2
twitter 2 r STARTED Node2
twitter 3 r STARTED Node2
twitter 4 r STARTED Node2

この状態で、Node3を停止すると、今度はNode2のレプリカシャード2、3、4がプライマリに昇格して、Node1にそれぞれのレプリカが配置されます。

[node.zone: ap-northeast-1a]
index shard prirep state node
twitter 0 p STARTED Node1
twitter 1 p STARTED Node1
twitter 2 r STARTED Node1
twitter 3 r STARTED Node1
twitter 4 r STARTED Node1
[node.zone: ap-northeast-1c]
index shard prirep state node
twitter 0 r STARTED Node2
twitter 1 r STARTED Node2
twitter 2 p STARTED Node2
twitter 3 p STARTED Node2
twitter 4 p STARTED Node2

Shard Allocation Awareness を設定をすることで、ノードを増やしても減らしても、必ずそれぞれのAZには0〜4の5つのシャードから構成される完全なインデックスが保持されます。

2つのAZで、5シャード1レプリカのインデックスをスケールアウトする場合は、AZごとに最大5台の合計10台までスケールアウト可能です。

もし、レプリカを増やしてさらにスケールアウトしたい場合は、レプリカ数を奇数で増やす(1→3→5)ことでバランス良くスケールアウトすることができます。

検索リクエストについても、Automatic Preference When Searching / GETing に記載されているように、 cluster.routing.allocation.awareness.attributes で設定されている属性の値を利用して、自動的に検索リクエストを問い合わせるシャードが選択されるため、検索するときは特に意識することなく、AZ間の通信を発生させずに検索することができるようになります。

with AWS Cloud Plugin

Elasticsearch を AWSで稼働するときは、AWS Cloud Plugin を使用することが多いかと思いますが、これまで説明してきた内容をAWS Cloud Plugin で設定すると Shard Allocation Awareness で識別するAZ名を動的に設定してくれる便利な機能があるのでその設定例をご紹介します。

設定例:

cluster.routing.allocation.awareness.attributes: aws_availability_zone
cluster.routing.allocation.awareness.force.aws_availability_zone.values: ap-northeast-1a,ap-northeast-1c
cloud.node.auto_attributes: true

cloud.node.auto_attributes true に設定することで、静的に node.aws_availability_zone: ap-northeast-1a と設定しなくても、そのインスタンスが起動しているAZの識別名を自動的に設定してくれます。

それぞれのノードが aws_availability_zone の値に何が設定されているのか確認するには、次のコマンドを実行します。

確認コマンド:

curl localhost:9200/_nodes/transport?pretty

出力例:

{
“cluster_name” : “elasticsearch”,
“nodes” : {
“C0OFzvexSgej3ksqOYh9AQ” : {
“name” : “Nemesis”,
“transport_address” : “…”,
“host” : “…”,
“ip” : “…”,
“version” : “1.5.1”,
“build” : “…”,
“http_address” : “…”,
“attributes” : {
“aws_availability_zone” : “ap-northeast-1c”
},
“transport” : {
“bound_address” : “…”,
“publish_address” : “…”,
“profiles” : { }
}
},
“dG1Q3kZ2Q3CbTt18s-XciA” : {
“name” : “Hitman”,
“transport_address” : “…”,
“host” : “…”,
“ip” : “…”,
“version” : “1.5.1”,
“build” : “5e38401”,
“http_address” : “…”,
“attributes” : {
“aws_availability_zone” : “ap-northeast-1a”
},
“transport” : {
“bound_address” : “…”,
“publish_address” : “…”,
“profiles” : { }
}
}
}
}

まとめ

Shard Allocation Awareness を設定することで、マルチAZ配置でもAZ間の通信を発生させずに検索することができました。これで障害にも強くパフォーマンスの良いElasticsearchの環境が構築できますね。

Like what you read? Give Kunihiko Kido a round of applause.

From a quick cheer to a standing ovation, clap to show how much you enjoyed this story.