Elasticsearch クラスタ管理トレーニング（起動、停止、再起動）

#### 背景
Elasticsearch を本格的に使い始めた頃は、クラスタが安定して動作せず、いつの間にか1ノードが落ちていたり、クラスタ全体のパフォーマンスが低下していたり、悩まされることも多いです。
復旧するために、ノードを再起動することもありますが、ノード起動時にはシャードのリバランシングが行われ、それに多くの時間を要してしまいます。
不用意にノードの再起動を行うと、クラスタの状態が安定するまでに時間を要してしまいます。
こういった仕組みを理解した上で、Elasticsearch クラスタ管理を行うため、Dockerで小規模なElasticsearchクラスタを用意し、手順を追ってトレーニングし、理解を深めたいと考えました。

#### 環境
Docker により、以下のコンテナような構成でコンテナを用意する。
- Elasticsearch node × 3
- Kibana node × 1 (こちらは必須ではありませんが、起動していれば curl の代わりに console 機能から各APIを実行することができます）

今回はこちらの記事の内容で構築しいたものを使いました。
https://qiita.com/blueskyarea/items/ebf219c413d0329ceb4f

```
$ curl -XGET -s "http://localhost:9200/_cluster/health" | python -m json.tool
{
    "active_primary_shards": 7,
    "active_shards": 14,
    "active_shards_percent_as_number": 100.0,
    "cluster_name": "es-docker-cluster",
    "delayed_unassigned_shards": 0,
    "initializing_shards": 0,
    "number_of_data_nodes": 3,
    "number_of_in_flight_fetch": 0,
    "number_of_nodes": 3,
    "number_of_pending_tasks": 0,
    "relocating_shards": 0,
    "status": "green",
    "task_max_waiting_in_queue_millis": 0,
    "timed_out": false,
    "unassigned_shards": 0
}
```

#### 実践
##### 停止前
<b>レプリカシャードのリバランシングを無効化する</b>
前述したようにノードを停止すると、シャードのリバランシングが行われ、それに多くの時間を要してしまいます。
レプリカシャードのリバランシングを無効化することで、リバランシングによる不要なデータの移動を行わないようにします。

```
curl -XPUT "http://localhost:9200/_cluster/settings" -H 'Content-Type: application/json' -d'{  "persistent": {    "cluster.routing.allocation.enable": "primaries"  }}'
```

成功すれば、以下のようなレスポンスが返ってくるはずです。

```
{"acknowledged":true,"persistent":{"cluster":{"routing":{"allocation":{"enable":"primaries"}}}},"transient":{}}
```

<b>synced flushを実行する</b>
synced flushを予め実行しておくことで、ノード起動時に発生するプライマリシャードとレプリカシャードの内容が同じであることの確認を高速化することができる（ようです）。

```
curl -XPOST "http://localhost:9200/_flush/synced"
```

成功すれば、以下のようなレスポンスが返ってくるはずです。
各 index に対して、failed が 0 であることを確認します。

```
{"_shards":{"total":12,"successful":12,"failed":0},".apm-custom-link":{"total":2,"successful":2,"failed":0},".kibana_task_manager_1":{"total":2,"successful":2,"failed":0},"my_index":{"total":2,"successful":2,"failed":0},".apm-agent-configuration":{"total":2,"successful":2,"failed":0},".kibana-event-log-7.8.1-000001":{"total":2,"successful":2,"failed":0},".kibana_1":{"total":2,"successful":2,"failed":0}}
```

<b>現 Master ノードを確認する</b>
Masterノードを先に停止すると、不要なMasterノードの選定処理が行われます。
停止する目的にも依りますが、Masterノードは最後に停止するようにした方が良いと思いますので、現Masterノードはどれであるかを予め確認しておきます。

```
$ curl -XGET "http://localhost:9200/_cat/nodes?v"
ip          heap.percent ram.percent cpu load_1m load_5m load_15m node.role master name
172.30.10.2           62          92   5    0.26    0.26     0.35 dilmrt    *      es02
172.30.10.3           20          90   5    0.26    0.26     0.35 dilmrt    -      es03
172.30.10.1           42          90   5    0.26    0.26     0.35 dilmrt    -      es01
```

##### 停止
docker の コンテナを停止することになるので、実際にサーバのメンテナンスすることのシミュレートにはなりませんが、停止の流れをつかむために入れました。
ここでは例えば、es03 を停止することとします。

```
docker stop es03
```

もし実際のサーバを対象にする場合は、systemctl で停止する流れになります。

```
systemctl stop elasticsearch
```

es03 が停止されたことを確認できました。

```
$ curl -XGET "http://localhost:9200/_cat/nodes?v"
ip          heap.percent ram.percent cpu load_1m load_5m load_15m node.role master name
172.30.10.1           18          82   5    0.27    0.68     0.95 dilmrt    -      es01
172.30.10.2           67          80   5    0.27    0.68     0.95 dilmrt    *      es02
```

必要に応じて、他のノードも順次停止していきます。
今回はクラスタの停止、起動の練習なので、メンテナンス的なことは何も行いませんが、実運用ではノードのメンテナンス（パッチの適用やハードウェアのメンテナンス）などを行います。

##### 起動
ノードメンテナンスが完了したら、elasticsearch サービスを起動していきます。
起動する順序としては、Master(Master-eligible) ノードを先に起動して、クラスタの形成を優先して行うようにします。
そうすることで、データ専用ノード上で余分なエラーログの発生を抑制することができます。

ここでは、1ノードのみ(es03)停止していましたので、それをまず起動してきます。

```
docker start es03
```

もし実際のサーバを対象にする場合は、以下のようなコマンドでスタートすることになります。

```
systemctl start elasticsearch
```

以下のように、es03 がクラスタに再参加されたことを確認できました。
(数分かかる場合があります）

```
$ curl -XGET "http://localhost:9200/_cat/nodes?v"
ip          heap.percent ram.percent cpu load_1m load_5m load_15m node.role master name
172.30.10.1           61          82  50    1.39    0.54     0.72 dilmrt    -      es01
172.30.10.3           57          79  50    1.39    0.54     0.72 dilmrt    -      es03
172.30.10.2           54          81  50    1.39    0.54     0.72 dilmrt    *      es02
```

##### 起動後の確認
以下のコマンドで、クラスタの状態を確認していきます。

```
$ curl -XGET "http://localhost:9200/_cluster/health"
```
以下のようにクラスタの状態が表示されます。
すべてのプライマリシャードの配置が完了するまでは、ステータス(status)は red になります。
すべてのプライマリシャードの配置が完了すると、ステータス(status)は yellow になります。

```
{
  "cluster_name" : "es-docker-cluster",
  "status" : "yellow",
  "timed_out" : false,
  "number_of_nodes" : 3,
  "number_of_data_nodes" : 3,
  "active_primary_shards" : 7,
  "active_shards" : 7,
  "relocating_shards" : 0,
  "initializing_shards" : 0,
  "unassigned_shards" : 7,
  "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" : 50.0
}
```

しかしながらこのままでは、ステータスは green に戻らないです。
レプリカシャードのバランシングを無効化しているためです。

<b>レプリカシャードのリバランシングを有効化する</b>

```
$ curl -XPUT "http://localhost:9200/_cluster/settings" -H 'Content-Type: application/json' -d'{  "persistent": {    "cluster.routing.allocation.enable": null  }}'
{"acknowledged":true,"persistent":{},"transient":{}}
```

ステータス(status)が green に戻ることが確認できました。
これで全てのレプリカシャードも余分なリバランスが行われることなく、正常に配置されていることになります。

```
$ curl -XGET "http://localhost:9200/_cluster/health"
{
  "cluster_name" : "es-docker-cluster",
  "status" : "green",
  "timed_out" : false,
  "number_of_nodes" : 3,
  "number_of_data_nodes" : 3,
  "active_primary_shards" : 7,
  "active_shards" : 14,
  "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
}
```

Elasticsearch クラスタの停止準備、停止、起動の操作を確認していきました。
「このタイミングでクラスタのステータスはどうなっているのだろう？」とか、実際に手順に沿って操作していると、気づくことが多いと思いますので、こういった簡易の形式でも実際に試してみると良いと思います。
練習用に実際にサーバを複数台用意するのはコストがかかりますが、コンテナを使う方法では1台のパソコンで十分に確認ができます。