ElasticseharchのEC2 Discovery Pluginでクラスタ組むのが捗るはなし


こんばんはー

今回、ElasticsearchのクラスタをAWS上に組む際に便利なブラグインを使ってみたいと思いますー
その名も「EC2 Discovery Plugin」☆彡

調べているとAWS Cloud Pluginの使い方を書いている人は結構いるのですが、5系から提供されているEC2 Discovery Pluginはあんまいないのかなーって思いました。
なので、EC2 Discovery Pluginについてつらつら書きたいと思います( ﾟДﾟ)ゞﾋﾞｼｯ

# そもそもEC2 Discovery Pluginは何が便利なん？

Elasticsearchのデフォルトで用意されているZen Discoveryを利用してクラスタを組む際は、Unicastでホスト名やIPアドレス指定で組みます。
ただ、クラウド上の運用を考えるとUnicastはつらい。。
そこで、EC2 Discovery Pluginを使うとSecurityGroupを元にクラスタが組まれるのですー(dﾟωﾟd)ｵｩｲｪｰ
※[Multicast Discovery plugin](https://www.elastic.co/guide/en/elasticsearch/plugins/2.4/discovery-multicast.html)というのもあったのですが、5系から廃止されました

早速ですが、構成の説明したら実装方法を説明したいと思いますー

# インスタンス構成

* InstanceType:t2.medium
* OS:Amazon Linux AMI release 2017.03
* Node: 3台
* ClusterName: es-cluster

# こんな感じの流れで書いちゃいますー

0. AWS準備

1. Install Oracle JDK 1.8

2. Install Elasticsearch

3. Install Kibana（1台のみ）

4. Install X-pack Elasticsearch & kibana(1台のみ)

5. Install EC2 Discovery Plugin

6. 動作確認

# AWS準備

## SecurityGroup

ElasticsearchをインストールするインスタンスにアタッチするSecurityGroupです。
ソースは、環境に合わせて設定してください。

|  Type  | Protocol | Port | Source |       Description         |
|:-------|---------:|:----:|:------:|:-------------------------:|
| Custom |   TCP    | 9200 |   xx   |Elasticsearchアクセスポート| 
| Custom |   TCP    | 9300 |   xx   |ノード間のコミュニケーションポート|
| Custom |   TCP    | 5601 |   xx   |KibanaのHTTP用ポート|
| Custom |   TCP    |  22  |   xx   |SSH用ポート|

## IAM Role

以下のPolicyを作成し、インスタンスにアタッチしているIAM RoleにPolicyをアタッチしてください。

```bash
{
    "Statement": [
        {
            "Action": [
                "ec2:DescribeInstances"
            ],
            "Effect": "Allow",
            "Resource": [
                "*"
            ]
        }
    ],
    "Version": "2012-10-17"
}
```

## AWS Configure

サーバにログインしたらAWS Configureの実行をします。
Access KeyとSecret keyは利用しないため、何も入力しません。

```bash
$ aws configure
AWS Access Key ID [None]:
AWS Secret Access Key [None]:
Default region name [None]: ap-northeast-1
Default output format [None]: json
```

下準備が終わったので、ここからElasticsearch周りを進めたいと思いますー

# Install Oracle JDK 1.8

```bash
$ java -version
java version "1.7.0_141"
OpenJDK Runtime Environment (amzn-2.6.10.1.73.amzn1-x86_64 u141-b02)
OpenJDK 64-Bit Server VM (build 24.141-b02, mixed mode)

### Install Java1.8
$ sudo yum -y install java-1.8.0-openjdk-devel

### alternativesコマンドでJavaのバージョンを切り替える
$ sudo alternatives --config java

There are 2 programs which provide 'java'.

  Selection    Command
-----------------------------------------------
*+ 1           /usr/lib/jvm/jre-1.7.0-openjdk.x86_64/bin/java
   2           /usr/lib/jvm/jre-1.8.0-openjdk.x86_64/bin/java

Enter to keep the current selection[+], or type selection number: 2

### バージョン確認
$ java -version
openjdk version "1.8.0_141"
OpenJDK Runtime Environment (build 1.8.0_141-b16)
OpenJDK 64-Bit Server VM (build 25.141-b16, mixed mode)
```

# Install Elasticsearch

Elasticsearch5.5.1を入れちゃいたいと思いますー

[Install Elasticsearch](https://www.elastic.co/guide/en/elasticsearch/reference/current/setup.html)

```bash
### PGP Keyをダウンロード＆インストール
$ sudo rpm --import https://artifacts.elastic.co/GPG-KEY-elasticsearch

### リポジトリの登録
$ sudo vim /etc/yum.repos.d/elastic.repo
[elasticsearch-5.x]
name=Elasticsearch repository for 5.x packages
baseurl=https://artifacts.elastic.co/packages/5.x/yum
gpgcheck=1
gpgkey=https://artifacts.elastic.co/GPG-KEY-elasticsearch
enabled=1
autorefresh=1
type=rpm-md

### Elasticsearchインストール
$ sudo yum -y install elasticsearch

### サービス起動登録
$ sudo chkconfig --add elasticsearch

### 確認
$ sudo chkconfig --list | grep elasticsearch
elasticsearch   0:off   1:off   2:on    3:on    4:on    5:on    6:off

### elasticsearch.yml設定変更
$ sudo vim /etc/elasticsearch/elasticsearch.yml
+ cluster.name: es-cluster
+ network.host: 0.0.0.0
+ http.port: 9200

### サービス起動
$ sudo service elasticsearch start
Starting elasticsearch:                                    [  OK  ]

### 起動確認
$ curl http://localhost:9200
{
  "name" : "fDpNQ4m",
  "cluster_name" : "es",
  "cluster_uuid" : "mayxoDENThSmrUltkXyRWg",
  "version" : {
    "number" : "5.5.1",
    "build_hash" : "19c13d0",
    "build_date" : "2017-07-18T20:44:24.823Z",
    "build_snapshot" : false,
    "lucene_version" : "6.6.0"
  },
  "tagline" : "You Know, for Search"
}

```

# Install Kibana

モニタリングしたいのでKibana5.5.1をインストールします。

```bash
### Install Kibana
$ sudo yum install -y kibana
### サービス登録
$ sudo chkconfig --add kibana
$ chkconfig --list | grep kibana
kibana          0:off   1:off   2:on    3:on    4:on    5:on    6:off
### Kibana設定
$ sudo vim /etc/kibana/kibana.yml
+ server.host: 0.0.0.0
+ elasticsearch.url: "http://ES_IP_ADDR"
### サービス停止状態のままにしておきます（X-Pack入れたあとに設定変更後に起動します）
$ service kibana status
kibana is not running
```

# Install X-Pack on Elasticsearch 

Elasticsearchのノード状態などをモニタリングしたいため、X-Pack5.5をインストールします。

[Install X-Pack on Elasticsearch](https://www.elastic.co/guide/en/elasticsearch/reference/5.5/installing-xpack-es.html)

```bash
$ sudo /usr/share/elasticsearch/bin/elasticsearch-plugin install x-pack
-> Downloading x-pack from elastic
[=================================================] 100%  
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@     WARNING: plugin requires additional permissions     @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
* java.io.FilePermission \\.\pipe\* read,write
* java.lang.RuntimePermission accessClassInPackage.com.sun.activation.registries
* java.lang.RuntimePermission getClassLoader
* java.lang.RuntimePermission setContextClassLoader
* java.lang.RuntimePermission setFactory
* java.security.SecurityPermission createPolicy.JavaPolicy
* java.security.SecurityPermission getPolicy
* java.security.SecurityPermission putProviderProperty.BC
* java.security.SecurityPermission setPolicy
* java.util.PropertyPermission * read,write
* java.util.PropertyPermission sun.nio.ch.bugLevel write
* javax.net.ssl.SSLPermission setHostnameVerifier
See http://docs.oracle.com/javase/8/docs/technotes/guides/security/permissions.html
for descriptions of what these permissions allow and the associated risks.

Continue with installation? [y/N]y
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@        WARNING: plugin forks a native controller        @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
This plugin launches a native controller that is not subject to the Java
security manager nor to system call filters.

Continue with installation? [y/N]y
-> Installed x-pack
```

動作確認するのですが、Securityが有効になったため、エラーが返ってきます。
なので、今回は、Securityを無効にします。
（モニタリング用途で使いたいだけなので―）

ちなみに、X-Packについては、クラスメソッドさんが詳しく書いてますー
[クラスメソッド：Elastic Stack X-Pack](http://dev.classmethod.jp/server-side/elasticsearch/elastic-stack-x-pack-install/)

## X-Pack Security無効化

無効化することで、レスポンスが返ってきます。

```bash
### Security無効化
$ vim /etc/elasticsearch/elasticsearch.yml
+ xpack.security.enabled: false

### 動作確認
$ curl -u elastic http://localhost:9200
{
  "name" : "fDpNQ4m",
  "cluster_name" : "es",
  "cluster_uuid" : "mayxoDENThSmrUltkXyRWg",
  "version" : {
    "number" : "5.5.1",
    "build_hash" : "19c13d0",
    "build_date" : "2017-07-18T20:44:24.823Z",
    "build_snapshot" : false,
    "lucene_version" : "6.6.0"
  },
  "tagline" : "You Know, for Search"
}

### 再起動
$ service kibana restart
kibana stopped.
kibana started
```

# Install X-Pack on Kibana

KibanaのX-Pack5.5もインストールします。

[Install X-Pack on Kibana](https://www.elastic.co/guide/en/kibana/5.5/installing-xpack-kb.html)

```bash
$ sudo /usr/share/kibana/bin/kibana-plugin install x-pack
Attempting to transfer from x-pack
Attempting to transfer from https://artifacts.elastic.co/downloads/kibana-plugins/x-pack/x-pack-5.5.1.zip
Transferring 119276972 bytes....................
Transfer complete
Retrieving metadata from plugin archive
Extracting plugin archive
Extraction complete
```

# Install EC2 Discovery Plugin

ここからEC2 Discovery Pluginをインストールします。
やっとここまできましたね！

```bash
$ sudo /usr/share/elasticsearch/bin/elasticsearch-plugin install discovery-ec2
-> Downloading discovery-ec2 from elastic
[=================================================] 100%  
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@     WARNING: plugin requires additional permissions     @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
* java.lang.RuntimePermission accessDeclaredMembers
* java.lang.RuntimePermission getClassLoader
See http://docs.oracle.com/javase/8/docs/technotes/guides/security/permissions.html
for descriptions of what these permissions allow and the associated risks.

Continue with installation? [y/N]y
-> Installed discovery-ec2
```

Elasticsearch.ymlに設定します。

```bash
$ sudo vim /etc/elasticsearch/elasticsearch.yml
cluster.name: es-cluster
discovery.zen.hosts_provider: ec2
discovery.ec2.groups: "SECURITY_GROUP_NAME" or "SECURITY_GROUP_ID"
discovery.ec2.availability_zones: [ "ap-northeast-1a", "ap-northeast-1c" ]
cloud.aws.region: ap-northeast-1

### サービス再起動
service elasticsearch restart

### クラスタ状態確認
$ curl http://localhost:9200/_cluster/health?pretty
{
  "cluster_name" : "es-cluster",
  "status" : "green",
  "timed_out" : false,
  "number_of_nodes" : 1,
  "number_of_data_nodes" : 1,
  "active_primary_shards" : 0,
  "active_shards" : 0,
  "relocating_shards" : 0,
  "initializing_shards" : 0,
  "unassigned_shards" : 0,
  "delayed_unassigned_shards" : 0,
  "number_of_pending_tasks" : 0,
  "number_of_in_flight_fetch" : 0,
  "task_max_waiting_in_queue_millis" : 0,
  "active_shards_percent_as_number" : 100.0
}
```

## 2台目＆3台目いくよ！！

2台目も上記と同じで設定を実施しますので割愛しちゃいますm(_ _)m
SecurityGroupは、1台目と同じのを使ってください。
また、ElasticsearchのX-Packは、3台すべてに入れてください。
Kibanaは、インストールしないです。

もろもろ設定して、Elasticsearchを再起動するとログにクラスタが組み込まれたことがわかります。

## クラスタに組み込まれているかをログから確認

```bash
### Master側のログ
[20xx-xx-xxxx:xx:xx][INFO ][o.e.c.s.ClusterService   ] [fDpNQ4m] added {{gdRR6r1}{gdRR6r17T5iaGPmaO9wgTA}{6l3QNArhSkyBVu08jTfwYQ}{IP_ADDR}{IP_ADDR:9300},}, reason: zen-disco-receive(from master [master {dKgmQfLLg}{IP_ADDR}{IP_ADDR:9300} committed version [15]])

### Node側のログでマスタを検出したことがわかる
$ tail -f /var/log/elasticsearch/es.log
[20xx-xx-xxxx:xx:xx][INFO ][o.e.c.s.ClusterService   ] [gdRR6r1] detected_master {dKgmQfL}{dKgmQfLASM-35x0X0ulSXg}{XE4jgXEzQwqgkSfRypgoLg}{IP_ADDR}{IP_ADDR:9300}, added {{fDpNQ4m}{fDpNQ4mrRR2vN7wiTVjfIg}{aqPbmbhbTkm1X40gH1tylw}{IP_ADDR}{IP_ADDR:9300},{dKgmQfL}{dKgmQfLASM-35x0X0ulSXg}{XE4jgXEzQwqgkSfRypgoLg}{IP_ADDR}{IP_ADDR:9300},}, reason: zen-disco-receive(from master [master {dKgmQfL}{dKgmQfLASM-35x0X0ulSXg}{XE4jgXEzQwqgkSfRypgoLg}{IP_ADDR}{IP_ADDR:9300} committed version [15]])
```

# Kibanaのモニタリングで確認するよ

Kibana [http://KIBANA_IP_ADDR:5601] にアクセスします。

「Monitoring」をクリックし、ElasticsearchにNodeが3台あることがわかりますね。
ステータス：Green

![kibana01.png](https://qiita-image-store.s3.amazonaws.com/0/152721/0740b5c8-39ba-1394-a1db-c07d9e2362dd.png)

「Nodes」をクリックし、Nodeの状態を確認できます。

![kibana02.png](https://qiita-image-store.s3.amazonaws.com/0/152721/98e461c2-80d2-705a-9018-e0a99c1969ef.png)

無事にクラスタを組むことができましたヽ(＊ﾟдﾟ)ノ

## 補足#01

AWS Configureの設定とIAM Roleにポリシーをアタッチしないと以下のエラーがでます。
ちなみに、作成したクラスタ名でログが作成されちゃいます。

```bash
$ sudo /var/log/elasticsearch/es-cluster.log
[20xx-xx-xxxx:xx:xx][INFO ][o.e.d.e.AwsEc2UnicastHostsProvider] [node_id] Exception while retrieving instance list from AWS API: Unable to execute HTTP request: connect timed out
```

## 補足#02

既に存在しているNodeIDのAMIから起動すると、NodeIDがかぶっているためクラスタに組み込むことができないです。。
その際のログが以下です。

```bash
###　AMIから起動したノード
$ tail -f /var/log/elasticsearch/es.log
[20xx-xx-xxxx:xx:xx][INFO ][o.e.d.z.ZenDiscovery     ] [gdRR6r1] failed to send join request to master [{fDpNQ4m}{fDpNQ4mrRR2vN7wiTVjfIg}{eHfV5HLkRrKo8_FXfgyHDA}{IP_ADDR}{IP_ADDR:9300}{ml.enabled=true}], reason [RemoteTransportException[[fDpNQ4m][IP_ADDR:9300][internal:discovery/zen/join]]; nested: IllegalArgumentException[can't add node {gdRR6r1}{gdRR6r17T5iaGPmaO9wgTA}{hzzXQXB8TM-xQVn9Uj8e2A}{IP_ADDR}{IP_ADDR:9300}{ml.enabled=true}, found existing node {gdRR6r1}{gdRR6r17T5iaGPmaO9wgTA}{9pWjYpL5Tq23yIte7WzMiw}{IP_ADDR}{IP_ADDR:9300}{ml.enabled=true} with the same id but is a different node instance]; ]
```

# さいごに

EC2 Discovery Pluginいかがでしたか？
簡単にクラスタを組むことができたんじゃないかなと思います。

ただ、個人的には、運用を考えると自動復旧できる構成にする必要があると思ってます。
今の状態だとElasticsearchのクラスタ化する時にNodeIDがかぶっちゃうので、AMIからの自動復旧がむずかしい状態です。
なので、Elasticsearchをインストールする前のAMIからプロビジョニングして、クラスタに組み込む必要があるかなと。
（Elasticsearchインストール時にNodeIDが振られる）

うーん。。NodeIDを変更する方法が他にあればいいのですが、誰か知っている人いたら教えてくださいm(_ _)m

てことで、今回は、ElasticsearchのプラグインのEC2 Discovery Pluginについて書かせて頂きました。
ありがとうございましたー

# 追記

GCEを利用した場合の記事も書きましたので、参考になれば幸いです。
[GCPの環境でGCE discovery pluginを使ってみた！](https://qiita.com/micci184/items/a728d96c4c01a813c1d7)