Elasticsearch の Shard Allocation Awareness を試す

AWS の Multi-AZ な環境で Elasticsearch クラスタを組んだので、その時の記録を残しておきます。

EC2 インスタンスを複数使いクラスタを構築する場合、可用性向上を図る目的でクラスタに属するインスタンスを複数のアベイラビリティゾーン (AZ) に配置することがあります。しかし、AZ 間の通信は地理的に離れた DC 間の通信になるため、Elasticsearch の入ったインスタンスをそのまま双方の AZ に配置すると、DC 間での通信が発生することになり検索時のパフォーマンスの低下を招く可能性があります。また、片側の AZ で障害が発生した際に、検索結果に欠損が生じないよう、生き残ったノードで全ての shard が揃うように shard 配置が行われなくてはなりません。

Elasticsearch には Shard Allocation Awareness という機能があります。これを利用することで、クラスタを構成するノードをグループ分けし1つのグループ内で完全なインデックスを持つことが可能になります。また、検索リクエストは、リクエストを受け取ったノードが存在するグループ内で完結することが可能になります。

実際に Shard Allocation Awareness を利用してクラスタを構築し、 ap-northeast-1a と ap-northeast-1c の双方でゾーン分けを行った際にシャードの配置がどのように行われるかを確認してみました。

環境

まずはそのままクラスタを組んでみる

まずは特別な設定無しに、2つの AZ にまたがって Elasitcsearch クラスタを構築してみます。インデックスは 5 shards 1 replicas で設定してみました。

kopf で shard の配置を確認してみます。ホスト名のうち 1a, 1c はそれぞれ配置されている AZ 名を表しています。shard の番号を確認すると、1つの AZ 内では完全なインデックスを保持できてはいないことがわかります。例えば、shard [1] は 1c 側のインスタンスに2つ存在しており、1a 側には存在しないことがわかります。

この状態で 1c 上の Elasticsearch を停止させてみます。1a に存在するノードだけでは完全なインデックスを保持できてはいないため、Cluster Health は Red になってしまいます。

Shard Allocation Awareness を設定してみる

次に、Shard Allocation Awareness を有効にした上で、同様のインデックス設定で shard を配置してみます。elasticsearch.yml に次のような設定項目を書き込み、全ノードに反映させます。

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

cloud-aws プラグインを導入しているため、cloud.node.auto_attributestrue を設定することで、ノードがどのゾーンにいるのかを自動的に設定することが可能です。aws_availability_zoneap-northeast-1a または ap-northeast-1c のどちらかの文字列が設定されます。

先ほどと同様にインデックスを作成してみます。今度は shard [0] ~ [4] までが1つの AZ 上に揃っていることが確認できます。

1c 上の Elasticsearch を停止させてみると、残る 1a 側で全ての shard を保持できているため、Cluster Health は Red ではなく Yellow になりました。1a 側の shard が primary shard となっていることがわかります。

1c 側の Elasticsearch を立ち上げると、Cluster Health は Green に戻りました。先ほど 1a 側の shard が primary となったため、1c 側は replica として扱われています。

1a, 1c それぞれに検索リクエストを行ってみる

検索リクエストを連続して送信し、クラスタに負荷をかけてみます。まずは 1a 側のノードのうち1つに対してリクエストを送信してみます。

$ while true; do curl '10.0.194.85:9200/index/_search?q=*'; done

1a 側のノード3台だけ CPU 負荷が上がっていることが確認できます。

同様に、次は 1c 側のノードにリクエストを送信してみます。

$ while true; do curl '10.0.194.27:9200/index/_search?q=*'; done

今度は、1c 側のノード3台だけ CPU 負荷が上がっていることが確認できます。

Shard Allocation Awareness を有効にすることで、分割された shard が各ゾーン内で全て揃い、受け取った検索リクエストがゾーン内で完結することが確認できました。 AWS ではインスタンスを Multi-AZ な環境で配置することを推奨していますが、この機能を利用することによって Elasticsearch クラスタ組んだ際の可用性の向上と、検索時のパフォーマンス維持を両立することが可能になります。


comments powered by Disqus