Elasticsearchの運用と課題

齋藤智之(以下、齋藤):ここまで、プロジェクトについてとElasticsearchにあるデータ量について見てきました。ここからは、Elasticsearchの運用に関して取り組んできたことや課題に思っている点についてご紹介します。まずはクラスター構成についてです。現在、3つのクラスターで運用しているとお話しました。どのようにクラスターが増えてきたのかを少しご紹介します。

初めは1ギガビット/秒のネットワークの上にクラスターが1つありました。データの規模の拡大に伴い、新しいサーバーを追加することになりまして、10ギガビット/秒のネットワークのサーバーを用意することができました。このときは、ネットワーク環境が1ギガと10ギガではっきり異なるということで、別のクラスターとして構築しました。

その後に、新たに大規模なログを購入したいというユーザーからのリクエストがありまして、サーバーのスペックとしては2つめのクラスターとほぼ同じものを用意できました。

ここで選択肢として、2つめのクラスターにノードを追加するか、別々のクラスターとして構築するかを検討しました。結果として、別々のクラスターとして構築しました。理由としては2つありました。1つめには、既存のデータとはデータの規模が大きく異なって、indexingの量ですとか、そういったワークロードが異なるものだったからです。2つめには、他のユーザーの利用の影響をあまり受けないのが望ましいという、ログの検索をするユーザー側の希望があったからです。

このようなかたちで、3つのクラスターを利用しています。

複数クラスターになった理由をまとめますと、ネットワーク環境によってまずクラスターを分割しました。将来的にマルチビジョンの対応をするときにもこのような分割が必要だろうと考えています。それからユーザーからの希望もありまして、Performance degradationや障害の影響範囲を狭めるために分割をしました。

このようにクラスターを分けて構築しますと、一つひとつのクラスターの管理は単純になるという利点があるのですが、クラスターの数が増えていくとどんどん管理コストが大きくなってしまうという問題があります。なので、今後は1つのクラスターの中のノード数を増やすことも検討しています。

一つひとつのクラスターが大きくなりますと、その分データが多様化してワークロードも多様化していきます。そういった環境の中でどのように運用するのがよいのか、ベストプラクティスを見つける必要があると考えています。

それから、ノードを追加していくなかでスペックの異なるマシンを追加する可能性もありますので、ヘテロジニアスクラスターの運用に関しても、いまあまり経験がないので、これもまた勉強が必要なところだなと感じています。

Index templateを自動生成

次のイシューです。Index templateというものをみなさん、利用したことがあるでしょうか。デイリーでIndexをローリングしているですとか、動的にindexが作られるような環境のときに、共通のindexの設定を適用するのに使うことができます。

具体的にはtemplateフィールドに指定したパターンにマッチするindexが作成されると設定が適用されるようになっています。indexレベルの設定では、indexシャードの数やレプリカの数などの設定やフィールドのタイプなどのマッピングの設定をすることができます。

ぼくたちのシステムでは、これらの設定をログデータの要求事項に合わせて変更できるようにしています。具体的に言いますと、ユーザーから指定されたプロパティーとProtobufメッセージスキーマを基に、index templateを自動生成するということをしています。

Protobufで提示されたメッセージのクラスには、各フィールドやそのタイプについてプログラマブルにトラヴァースすることができるようになっています。

Protobufのフィールドのタイプの基本的なものについては、Elasticsearchのフィールドタイプに対して自然な対応関係で変換することができます。この例で言いますと、Protobufにおけるストリングのフィールドは、Elasticsearchのタイプにおけるキーワードなどに変換されています。

また、ElasticsearchのIPフィールドタイプのような特別なタイプに関しては、Protobufのフィールドオプションを使って指定することができるようになっています。新しいindex作成のリクエストがユーザーから来たときに、毎回の作業でindex templateを作ると管理のコストがかかってきますので、このような自動化によってシステムの運営コストを下げる工夫をしています。

適切なシャード数、大きさを考える

次のイシューです。みなさんはどのようにシャードのサイズや数を決めているでしょうか。Elasticさんのブログで見ましても、最もよくある質問の1つとして「どのくらいのシャードの数がよいのか」ですとか、「どのくらいの大きさのシャードがよいのか」という質問が上がっています。

Elasticsearchを管理する側の視点で見ますと、シャードが小さすぎる場合、つまりシャードが多すぎる場合、シャードごとのリソースのオーバーヘッドがかかってしまうため、非効率な運用になってしまいます。

一方で、シャードが大きすぎる場合、つまりシャード数が少ない場合は、indexingのアクセスが集中してしまって、データの流入スピードにindexingが追いつかないということが起こりえます。なので、ちょうどよいシャードサイズを見つけなければいけません。

ぼくたちのシステムでは、シャードのサイズはログの送信者であるユーザーと相談しながら、いくつかのポリシーに則ってシャードのサイズを決めています。

まず、できるだけシャード数が少なくなるように設定を検討します。データの量が小さいindexの場合は、マンスリーでindexをローリングしてシャード数を1に設定しているものもあります。もしデータ量が多い場合には、indexingが分散されるようにシャード数を増やします。

例えば40台のオーダーがあった場合、シャード数20、レプリカ数を1に設定して、各ノードに1シャードが割り当たるような設定にしたりしています。

もしそれでもシャード当たりのデータ量が多い場合には、50GB/shardを目安にindex rolling periodを短くしています。一番短い時間帯ではアワリーでindexをローリングするものもあります。

このShard sizingのアプローチでは、システム管理者が設定を考える、相談しながら決めていく必要があって、運営コストがかかるという問題があります。システム利用者が増えるに従ってシャードの数も増えていくので、サイズの調整の負担が大きくなってきます。そこで、このShard sizingの解決策としまして、何か自動化できる方法はないかと現在、検討しています。

調べてみたところ、Rollover Index APIというものがElasticsearch 5.0から導入されていまして、これを使うことでindexをサイズベースでローリングすることができそうなので、ぜひこれからテストをしてみたいと考えています。

Indexing preformanceは2.2倍に

最後のイシューになります。Elasticsearchの1つのデータノードを使って、どのくらいのIndexingスピードが出るのか確認をするために実験を行いました。結果から言いますと、1秒当たり55,000ドキュメントをindexすることができまして、だいたいデフォルトの状態から2.2倍の改善が見られました。

データノードのマシンのスペックについて上にまとめてあります。Elasticsearchのバージョンは5.6.1を使っています。

Indexing performanceの改善に向けてやったことは3つありまして、1つめはauto-generated document idを使うこと。そしてprocessors設定を見直したこと。それから1台に載せて置くシャードの数を1から2に増やしたことです。

auto-generated document idを利用するとindexingを速くすることができます。

document idを指定した場合、index APIというのはドキュメントの追加もしくは更新を行うものなのですが、更新を行う場合は、既存のドキュメントの削除が必要になるのでドキュメントの存在をチェックする必要があり、コストがかかります。

一方で、document idを指定せずにauto-generated document idを利用する場合には、ドキュメントが(追加ではなく)更新される可能性がないと考えられますので、ドキュメントの存在チェックをスキップして、オプティマイズされたドキュメントの追加をすることができます。今回の実験では、こちらの設定を変えることで1.3倍のスピードアップが見られました。

次に、processorsという設定項目を見直しました。

Elasticsearchのサーバーのメトリクスを確認してみたところ、CPUノードが32で頭打ちになっているのが確認されました。また、ノードのOS APIで確認してみても、available_processorsが40あるのに対して、アロケートされているprocessors数が32になっていることがわかりました。

Elasticsearchでは、サーバーのprocessor数が自動検知されてスレッド数の設定などに反映されています。この自動検知の場合の上限が32と固定されていたことが、CPUロードが頭打ちになっていた理由でした。このprocessors設定を38に設定することでbulk requestの処理の並列度が高まり、1.3倍のスピードアップをすることができました。

ここまでの設定変更でindexing throttlingというのが発生しました。Elasticsearchのデフォルトの設定ですと、セグメントの数が増えすぎないようにindexingがスロットルされることがあります。今回の実験ではDiskの書き込みスピードが190メガバイトほど出ていて、Diskがボトルネックになっていることがわかりました。

右のグラフではセグメント数が増え続けていることを示していまして、セグメントのマージがindexingのスピードに追いついていないということを表しています。

Elasticsearchは並列して複数のマージを行っていますが、この並列しているマージがある閾値を超えたところでindexingがスロットリングされるような仕組みになっています。このindexスロットルを回避するにはいくつかの方法が考えられるのですが、今回の実験ではシャード数を1から2に増やすことにしました。これによってDiskが2つ使われることになって、ボトルネックを解消することができます。

この変更によって1.4倍くらいのスピードアップが見られました。この時点でCPU usageが60から80パーセント、Disk書き込みが2つのDiskともに125メガバイト/秒になっていました。

indexingパフォーマンスに関する実験のまとめです。設定の見直しをすることで、約2.2倍のスピードアップが見られました。現在の構成だと、CPUがボトルネックになりそうだということがわかりました。1データノードのパフォーマンスをさらに上げるにはindexパラメーターのチューニングなどをして、index time overheadをどうにか減らす必要があるなと感じました。

また、JBOD構成で12個のDiskを持つサーバーで実験を行いましたが、2つのDiskを使った時点でCPU使用率が80パーセント台になるということがあったため、マシンを効率よく使うためにindex構成の見直しなども必要であると感じました。

Elasticsearchのノードの増減について

以上、Elasticsearchに関するイシューについて見てきました。最後にまとめになります。

LINEの基幹サーバーのログの分析に、ぼくたちはElasticsearchを利用しています。ペタバイトスケールの分析環境を構築中です。現在、チームを拡大しているところでして、開発メンバーを採用中です。少しでもこのプロジェクトに興味を持っていただければ幸いです。以上になります。ご清聴ありがとうございました。

司会者:齋藤さん、ありがとうございました。では、Q&Aということで、ご質問のある方は挙手をいただければ私がマイクを持ってうかがいますので、よろしくお願いします。どなたかご質問ありますでしょうか?

質問者1:お話ありがとうございました。ノードの増減というのはけっこう激しかったりするのでしょうか。

齋藤:Elasticsearchのノードの増減?

質問者1:はい、そうです。

齋藤:そうですね、頻繁ではないです。そのデータの量に合わせてキャパシティーを超えて来そうだなというときに追加するというかんじですね。

質問者1:クラウドでやられているんですか?

齋藤:ではないですね。

質問者1:わかりました。ありがとうございます。

司会者:ほかに質問ある方、いらっしゃいますか?

質問者2:CPU使用率が今後はボトルネックになるかも、というのが1つあったと思うのですが、現段階でCPU使用率の負荷がかかっている内訳みたいなところは、例えばCPUのコア数が多ければコンテキストスイッチとかが上がったりと、そうでなければ単純JVMのユーザーの使用率が高いとか、どのへんがボトルネックになりそうかなということがあれば。

齋藤:そのへんは調査中になります。ElasticsearchのAPIの中でホットスレッヅなどで、どんなスレッドがいまCPUをどのくらい使っているかを見ることができるのですが、そういうのを見ますとセグメントのマージで使っている、コンカレントマシンスケジューラーというスレッドが出てくるとか、その程度の確認まではできるのですが、まだこれから調査するという感じになります。

質問者2:ありがとうございます。

ソフトコミットの設定について

質問者3:indexing処理と検索処理が一緒に走るElasticsearch環境を起こしているのですが、今回のセミナーの中ではindexingの処理の観点でいろいろチューニングしているようなのですが、一緒に走っている検索を、この間システムでなんかチューニングされたことはあるのでしょうか。

齋藤:今回示したのは実験環境なのでindexingのみになっていまして、実際に利用するときに関しましてもindexingの量はすごく多いのですが、基本的な用途はログの開発者のデバッグですとか、ユーザーの挙動を見たいですとか、そういうリクエストで、検索の要件はそういうことになっているので、そんなに頻繁ではなくて比較的短期間なものの検索を考えていまして。

まずは、いま大容量のログをElasticsearchに保存するというところにフォーカスしてやっています。検索はこれから、あまりに遅かったら使い物にならないので、そういったところでチューニングをする必要があるかなとは思っています。

質問者3:ありがとうございます。

質問者4:貴重なお話、ありがとうございました。2点質問があるのですが、indexの速度を検証された際にソフトコミットの設定はデフォルトの1秒のままだったでしょうか? それとも何か変更されていますでしょうか? もう1点、indexの際に作業されたのはリニアに1件ずつなのか、それともバルクである程度まとめてなのか。この2点を教えていただけますか。

齋藤:ソフトコミットに関しましては、デフォルトの設定を使っています。それから、indexingに関してはbulk indexingを利用しています。

質問者4:ありがとうございます。

質問者5:indexのスキーマを変えたいという要求があったときに、再インデックスはどうされている形ですか?

齋藤:基本的には時間でデイリーですとか、新しくどんどんindexができるので、その単位でどんどん更新されていくか、もしすぐにアップデートしたい場合には、いまのところマニュアルのオペレーションで消して作って。その場合、indexを消す必要があるのですが。リインデックスとかで自動で新しいデータの別のマッピングでやるということはしていないです。

質問者5:ありがとうございます。

司会者:ありがとうございます。本会終了後も懇親会でスピーカーと話す時間もございますので、そちらのほうで引き続きお話しいただければと思います。齋藤さん、ありがとうございました。

(会場拍手)