Elasticsearch・シャード数増加の対策方法

# 概要

ログ可視化のためにElasticsearch(以下、ESとする)を利用してKibanaでみるということをやっていたのですが、ある時Elasticsearchがタイムアウトしてログが見れなくなるということが発生しました。その原因がESのシャード数でした。この記事ではESの基本とタイムアウトの原因となったシャードとその対策について説明します。

![スクリーンショット 2019-10-19 20.10.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274080/3b60190b-7658-ad15-cc42-7e2bc1c483a7.png)


![スクリーンショット 2019-10-19 20.10.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274080/524eda1e-18f1-c000-7cf9-cf68df9ef4bf.png)


# Elasticsearchとは
OSSの分散型の検索・分析エンジンです。ElasticsearchにログをおくってKibanaで可視化したり、全文検索エンジンとして使ったりAPMとして使ったりと非常に幅広いユースケースに対応したサービスです。

![es-logo.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274080/da02ccd6-4740-cfdb-3f73-9d9ece001111.png)


https://www.elastic.co/jp/products/elasticsearch

# Elasticsearchの構成要素

### ノード
Elasticsearchの1プロセスに相当。同一サーバ内で複数のノードを起動することも可能。

### クラスタ
複数のノードを1つのElasticsearchとして動作させる事ができ、このノード群のことをクラスタと呼ぶ。
クラスタを構成することで大量のデータを複数のノードに分散して保持する事が出来ます。
また、可用性や検索性能の向上のためにクラスタ内でレプリカを持つこともできます。

![es-clister-node.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274080/73382474-7d6d-2eac-a403-6dbfa12c46fa.jpeg)

### インデックス
ドキュメントの集合で、Elasticsearchでは基本的にインデックス単位でデータを管理しています。
RDBMSでいうとデータベースにあたります。
インデックスがクラスタのノードに分散して保持されることで大量のデータを扱うことができます。
インデックスをノードに分散するための単位がシャードです。

### ドキュメント
Elasticsearchが扱うデータの最小単位。RDBMSの1レコードに相当。
Elasticsearchはスキーマフリーなため、各ドキュメントは異なる構造を持つ事ができます。

### タイプ
インデックスに登録するドキュメントを論理的に分類するための機能。
タイプを用いることでインデックスに様々な種類のドキュメントを保持しても容易に管理できます。

![es-index-type-document.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274080/6d683c14-d5d7-cbb5-035b-844b4e74a0f5.jpeg)

### シャード
**インデックスを小さな単位に分割したものをシャード**といいます。Elasticsearchはこのシャードをクラスタの各ノードに割り当てる事でデータを分散させている。このシャード数がデータを分散させる事ができる上限数です。

# 本題：Elasticsearchがタイムアウトしていた原因
概要で述べた、ESがタイムアウトする理由は上で説明した**シャード数の増加**でした。

JVMMemoryPressure
![スクリーンショット 2019-10-19 20.33.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274080/9e5a0fef-3939-7657-3307-057694ffa26c.png)

CPU使用率
![スクリーンショット 2019-10-19 20.34.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274080/4ec0c9cf-d794-6123-a1e8-e906a343a4d4.png)

上図のようにJVMメモリの負荷とCPU使用率が高騰しています。
ディスク容量については20GB中10GBと問題にはなってませんでした。**Elasticsearchはインデックスをファイルに保存し、検索のたびにファイルへのアクセスが発生します。ファイルへのアクセスを効率よく行うためにOSにも十分なメモリが用意するように公式で推奨**されています。シャード数が多いために使用しているメモリ量が推奨値よりも増え、検索の効率が悪化してタイムアウトが発生していたという事でした。

> 経験則では、ノードごとのシャード数は構成したヒープのGBあたり20未満に維持することが良いと言えます。

https://www.elastic.co/jp/blog/how-many-shards-should-i-have-in-my-elasticsearch-cluster

# 対策
上より、インデックス数の増加がタイムアウトの原因とわかったので、これを減らすことで問題を解決しようと思います。

インデックスを減らす方法

| 方法 | 内容 |
|:-----------|------------:|
| 不要なインデックスを削除       | 過去の不要なものからインデックスを削除することでそれに伴いシャード数を減らすします。|
| インデックスあたりのシャード数を小さくする | デフォルトでは1インデックスあたり5つのシャード数を生成する設定になっているのをノードの数も考慮しつつ小さくすることでシャード数の増加を抑える方法です。  |
| インデックス作成単位を統合する       | 例えば日付単位で作成していたインデックスを月単位で作成するようにすることで、作成されるインデックスの数を抑えることでシャード数の増加率も抑える方法です。   |
| ノード数の増加/ノードをより大きなインスタンスタイプにする| お金を使ってノードの数や性能をあげることで多量のインデックスが作成されても大丈夫なようにする方法です。 |

2つ目の方法のデメリットとして、インデックスあたりのシャード数を減らす事で分散する量が小さくなるのでパフォーマンスが劣る事です。
4つ目の方法について、これはコストがかかりますが、現状の設定を変えずに対応する事ができます。
今回は開発環境のElasticsearchに対して起こった問題だったため、インデックスを削除することで一時的にこの問題は解決しました。

# まとめ
以上でElasticsearchの基本から今回起きたElasticsearchがタイムアウトする原因とその対策について説明してきました。
Elasticsearchはノードを単位として複数のノードにデータを分散して保持することで高速な検索を可能にしていて、そのデータの分散の保持する単位がシャードでした。適切なメモリ領域を確保するためにインデックスの設定やノード数の増加・性能をあげることで効率の良い分析基盤を整える事ができます。




# 参考
https://www.elastic.co/guide/jp/elasticsearch/reference/current/gs-search-api.html
[Elasticsearchクラスターのシャード数はいくつに設定すべきか？](https://www.elastic.co/jp/blog/how-many-shards-should-i-have-in-my-elasticsearch-cluster)
[elastic search index template](https://www.elastic.co/guide/en/elasticsearch/reference/6.3/indices-templates.html)
[Reindexが登場!](https://www.elastic.co/jp/blog/reindex-is-coming)
[データ分析基盤構築入門](https://gihyo.jp/book/2017/978-4-7741-9218-5)