AWS Cloud Plugin for ElasticSearchを使う – AWSで始めるElasticSearch(3)

elasticsearch-logo

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

@smokeymonkeyです。 前回(Cluster機能を使う – AWSで始めるElasticSearch(2))、以下のように書きました。

Discoveryはデフォルトではマルチキャストを使ってmaster nodeを検索しに行くようです。
しかしAmazon Virtual Private Cloud FAQに
 Q: Amazon VPC は、マルチキャストまたはブロードキャストをサポートしますか?
 いいえ。
と記載されています...Amazon VPCではmulticast discoveryは使えません。

この記事について、以下のコメントを頂きました(Jun Ohtaniさん、ありがとうございます!)

comm

そこで今回は、AWS Cloud Plugin for ElasticSearchを使ってみたいと思います。

セットアップ

ElasticSearchがセットアップされた2台のEC2インスタンスを作成します。

ElasticSearchのインストール

最新のrpmパッケージを取得し、rpmコマンドにてインストールします。

$ wget https://download.elasticsearch.org/elasticsearch/elasticsearch/elasticsearch-0.90.5.noarch.rpm 
$ sudo rpm -ivh ./elasticsearch-0.90.5.noarch.rpm

AWS Cloud Plugin for ElasticSearchのインストール

pluginはElasticSearchのpluginコマンドにて行います。

$ sudo /usr/share/elasticsearch/bin/plugin -install elasticsearch/elasticsearch-cloud-aws/1.15.0
-> Installing elasticsearch/elasticsearch-cloud-aws/1.15.0...
Trying http://download.elasticsearch.org/elasticsearch/elasticsearch-cloud-aws/elasticsearch-cloud-aws-1.15.0.zip...
Downloading ..............DONE
Installed elasticsearch/elasticsearch-cloud-aws/1.15.0 into /usr/share/elasticsearch/plugins/cloud-aws

設定

両方のEC2インスタンスで、同様の設定を行います。elasticsearch.ymlを編集し設定します。

  • discovery.zen.ping.multicast.enabled ... マルチキャストの使用を設定します。VPCでは使用できないため明示的にfalseにします。
  • cloud.aws.region ... regionを指定します。
  • cloud:aws.access_key ... アクセスキーを指定します。
  • cloud:aws.secret_key ... シークレットキーを指定します。
  • discovery.type ... 探索タイプをEC2と指定します。
$ sudo vi /etc/elasticsearch/elasticsearch.yml 
discovery.zen.ping.multicast.enabled: false
cloud.aws.region: us-west-2
cloud:
    aws:
        access_key: アクセスキー
        secret_key: シークレットキー
discovery:
    type: ec2

設定ファイルの編集後はサービスの再起動が必要です。

$ sudo service elasticsearch restart

動作確認

それでは1台目のログを確認してみます。"new_master [host1]"と、自身がmasterになったことが分かります。

$ cat /var/log/elasticsearch/elasticsearch.log
[2013-11-05 02:52:10,158][INFO ][node                     ] [host1] initializing ...
[2013-11-05 02:52:10,176][INFO ][plugins                  ] [host1] loaded [cloud-aws], sites []
[2013-11-05 02:52:13,952][INFO ][node                     ] [host1] initialized
[2013-11-05 02:52:13,952][INFO ][node                     ] [host1] starting ...
[2013-11-05 02:52:14,130][INFO ][transport                ] [host1] bound_address {inet[/0:0:0:0:0:0:0:0:9300]}, publish_address {inet[/172.31.1.34:9300]}
[2013-11-05 02:52:18,053][INFO ][cluster.service          ] [host1] new_master [host1][EX3VkBZlSVuPbX0pQOVatg][inet[/172.31.1.34:9300]]{aws_availability_zone=us-west-2c}, reason: zen-disco-join (elected_as_master)
[2013-11-05 02:52:18,067][INFO ][discovery                ] [host1] elasticsearch/EX3VkBZlSVuPbX0pQOVatg
[2013-11-05 02:52:18,096][INFO ][http                     ] [host1] bound_address {inet[/0:0:0:0:0:0:0:0:9200]}, publish_address {inet[/172.31.1.34:9200]}
[2013-11-05 02:52:18,096][INFO ][node                     ] [host1] started
[2013-11-05 02:52:18,108][INFO ][gateway                  ] [host1] recovered [0] indices into cluster_state

次に2台目のログを確認します。"detected_master [host1]"と、1台目のEC2インスタンスが発見出来たことが分かります!

$ cat /var/log/elasticsearch/elasticsearch.log
[2013-11-05 02:53:03,428][INFO ][node                     ] [host2] version[0.90.5], pid[1893], build[c8714e8/2013-09-17T13:09:46Z]
[2013-11-05 02:53:03,429][INFO ][node                     ] [host2] initializing ...
[2013-11-05 02:53:03,447][INFO ][plugins                  ] [host2] loaded [cloud-aws], sites []
[2013-11-05 02:53:07,368][INFO ][node                     ] [host2] initialized
[2013-11-05 02:53:07,368][INFO ][node                     ] [host2] starting ...
[2013-11-05 02:53:07,542][INFO ][transport                ] [host2] bound_address {inet[/0:0:0:0:0:0:0:0:9300]}, publish_address {inet[/172.31.11.207:9300]}
[2013-11-05 02:53:11,709][INFO ][cluster.service          ] [host2] detected_master [host1][EX3VkBZlSVuPbX0pQOVatg][inet[/172.31.1.34:9300]]{aws_availability_zone=us-west-2c}, added {[host1][EX3VkBZlSVuPbX0pQOVatg][inet[/172.31.1.34:9300]]{aws_availability_zone=us-west-2c},}, reason: zen-disco-receive(from master [[host1][EX3VkBZlSVuPbX0pQOVatg][inet[/172.31.1.34:9300]]{aws_availability_zone=us-west-2c}])
[2013-11-05 02:53:11,755][INFO ][discovery                ] [host2] elasticsearch/I7DC0L93TcmB898xror2Cw
[2013-11-05 02:53:11,760][INFO ][http                     ] [host2] bound_address {inet[/0:0:0:0:0:0:0:0:9200]}, publish_address {inet[/172.31.11.207:9200]}
[2013-11-05 02:53:11,761][INFO ][node                     ] [host2] started

2台目がclusterにjoinした時の、1台目のログです。2台目(host2)がaddされたことが分かります。

$ cat /var/log/elasticsearch/elasticsearch.log
[2013-11-05 02:53:11,682][INFO ][cluster.service          ] [host1] added {[host2][I7DC0L93TcmB898xror2Cw][inet[/172.31.11.207:9300]],}, reason: zen-disco-receive(join from node[[host2][I7DC0L93TcmB898xror2Cw][inet[/172.31.11.207:9300]]])

仕組みを確認してみる

さて、このAWS Cloud Pluginですが、一体どんな仕組みで動作しているのでしょう。とても気になったので、tcpdumpでパケットキャプチャを取得し、動作を確認してみました。

まずサービス起動時、自身が所属しているAZを確認しています。今回使用していたus-west-2cを取得していることが分かります。

GET /latest/meta-data/placement/availability-zone HTTP/1.1
User-Agent: Java/1.6.0_24
Host: 169.254.169.254
Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
Connection: keep-alive

HTTP/1.0 200 OK
Content-Type: text/plain
Accept-Ranges: bytes
ETag: "1970001243"
Last-Modified: Tue, 05 Nov 2013 01:39:15 GMT
Content-Length: 10
Connection: keep-alive
Date: Tue, 05 Nov 2013 02:52:14 GMT
Server: EC2ws

us-west-2c

次にec2.regionname(今回はus-west-2).amazonaws.comにアクセスし、アクセスキーとシークレットキーを引数にして、同じAZ内のEC2インスタンスをXML形式にて取得しています。

POST / HTTP/1.1
Host: ec2.us-west-2.amazonaws.com
User-Agent: aws-sdk-java/1.3.32 Linux/3.4.62-53.42.amzn1.x86_64 OpenJDK_64-Bit_Server_VM/20.0-b12
Content-Type: application/x-www-form-urlencoded; charset=utf-8
Content-Length: 225
Connection: Keep-Alive

Action=DescribeInstances&SignatureMethod=HmacSHA256&AWSAccessKeyId=XXXXXXXXXX&SignatureVersion=2&Version=2012-12-01&Signature=XXXXXXXXXX&Timestamp=2013-11-05T02%3A52%3A14.190ZHTTP/1.1 200 OK
Content-Type: text/xml;charset=UTF-8
Transfer-Encoding: chunked
Date: Tue, 05 Nov 2013 02:52:13 GMT
Server: AmazonEC2

2000
<?xml version="1.0" encoding="UTF-8"?>
<DescribeInstancesResponse xmlns="http://ec2.amazonaws.com/doc/2012-12-01/">
    <requestId>4d98492f-9548-4164-992f-f4b2b3efe746</requestId>
    <reservationSet>
        <item>
            <reservationId>r-XXXXXXX</reservationId>
            <ownerId>1234567890</ownerId>
            <groupSet/>
            <instancesSet>
                <item>
                    <instanceId>i-584ad96c</instanceId>
-- 以下省略 -- 

次に発見出来たEC2インスタンスに対し、9300/tcpにて通信を行います。

これは1台目のサービスが起動し、2台目のサービスが停止している状態での動作です。対象EC2インスタンスでElasticSearchが起動していない場合は当然接続出来ませんので、以下の通りTCP RSTにて通信が終了しています。

cap1

では1台目のサービスが起動し、clusterのmasterとなっている状態で、2台目のサービスを起動した場合の動作を確認してみましょう。wiresharkのFollow TCP Streamで確認したところ、以下のように2台目(host2)から1台目(host1)に対し、unicastにて通信を行っています。これでmulticastが使えないVPCでもdiscoveryが出来ている理由が分かりました。

ES...t...............discovery/zen/unicast..............elasticsearch...host2...I7DC0L93TcmB898xror2Cw..........$T...6.
ES........................elasticsearch...host2...I7DC0L93TcmB898xror2Cw..........$T...6......host1...EX3VkBZlSVuPbX0pQOVatg......."..$T....aws_availability_zone..us-west-2c..6............"..$T.......6

ES...t...............discovery/zen/unicast..............elasticsearch...host2...I7DC0L93TcmB898xror2Cw..........$T...6.
ES........................elasticsearch...host2...I7DC0L93TcmB898xror2Cw..........$T...6.................$T...6......host1...EX3VkBZlSVuPbX0pQOVatg......."..$T....aws_availability_zone..us-west-2c..6............"..$T.......6

ES...t...............discovery/zen/unicast..............elasticsearch...host2...I7DC0L93TcmB898xror2Cw..........$T...6.
ES........................elasticsearch...host2...I7DC0L93TcmB898xror2Cw..........$T...6.................$T...6.................$T...6......host1...EX3VkBZlSVuPbX0pQOVatg......."..$T....aws_availability_zone..us-west-2c..6............"..$T.......6

まとめ

AWS Cloud Plugin for ElasticSearchを使うことで、設定ファイルにunicast設定でmaster nodeを記載しなくとも、自動的にmaster nodeを探索することが出来ました。これでScale Outにも容易に対応できます。