LINEデリマでのElasticsearchの運用と監視の話

司会者:よろしくお願いいたします。みなさん拍手でお願いいたします。

渡邊紘太朗氏(以下、渡邊):では「LINEデリマでのElasticsearchの運用と監視の話」というタイトルで発表を始めさせていただきます。よろしくお願いします。では始めに、簡単に自己紹介をさせていただきます。開発3センター開発支援室という部署に所属しています、渡邊紘太朗といいます。

2016年の4月に弊社へ転職してきたんですが、それまではアプリケーションエンジニアをしていて、転職を機にサーバーサイドのエンジニアからインフラエンジニアに転身をしました。

現在は今回紹介するLINEデリマを始めとしたLINE LIVE、LINEポイント、LINEギフト、LINEマンガ、Clova、これらのサービスの開発支援の担当を行っています。ここに記載されているサービスは開発3センターの中でみているサービスの一部なんですが、ほとんどのサービスが検索エンジンとしてElasticsearchを利用しています。

では次に本日のアジェンダですが、まずはじめにLINEデリマというサービスについて説明させていただきます。そのあとにElasticsearchの運用について、監視について、今後の展望について。最後に質問で終了したいと思います。

LINEデリマ、まだサービスがリリースされてから日が浅いサービスなので、LINEデリマで利用しているElasticsearchの運用と監視について、ポイントを押さえながら時系列で説明することでLINEデリマの生い立ちを理解していただく、ということをゴールに設定して話を進めていきたいと思っています。

まず始めにLINEデリマについて説明します。

LINEデリマは、2017年の7月26日にリリースされた、LINEと夢の街創造委員会株式会社が提携をして展開している、フードデリバリーサービスになります。現在はLINEアプリ内からこのLINEデリマのページに飛ぶことができます。

またLINE公式アカウントとして@limedelimaというアカウントがあり、こちらで割引情報などのお得な情報を配信しているので興味のあるかたはぜひ登録してみてください。LINEデリマではElasticsearchを検索エンジンとして利用しております。

勝手な想像ですが、この後の懇親会もLINEデリマで注文した商品が来るものだと思っております。

スタッフ:違います。

(会場笑)

渡邊:とのことです。

LINEデリマの全体像

こちらがLINEデリマの検索部分における全体像になります。

LINEデリマはSPAとして実装されていて、トップページにアクセスするとAPIサーバーに対してリクエストを行っております。APIサーバーはElasticsearchクラスタに対してリクエストを行い、結果を返しています。このAPIサーバーからElasticsearchへのリクエストに関してはLBなどを経由してはいません。

次に、データのインデクシングについてですが、LINEデリマはマスターデータのために2つのバッチサーバーが稼働しています。1つめは夢の街創造委員会が管理する商品データ、店舗データ、地域データといったデータを社内のDBにシンクするためのバッチサーバーです。

2つめは、そのシンクしたデータを社内のElasticsearchにインデクシングするためのバッチサーバーになります。インデクシング用のバッチサーバーはこれらのインデックスに対して数分おきにインデクシングを実行しているというような感じになっています。

では次に、リリース時のElasticsearchのクラスタについて解説していきます。

リリース当初は3台の物理サーバーでクラスタを構築していました。このなかで、マスターノードが1台、データノードが2台として稼働していました。Elasticsearchを利用された方がいるのであれば、これを見て問題に気づくかもしれないのですが、ここからはこのクラスタを改善していく話になります。

さらにその他の構成要素です。

LINEデリマはJavaで書かれたアプリケーションなので、JavaのクライアントとしてTranspoetClientを利用しています。地域データであるblock、商品データであるitem、店舗データであるshop、の3つがインデックスとして存在しています。

また、ダッシュボードとしてはサードパーティのcerebroを利用していまして、動的な設定値の変更はこのダッシュボード上から行うようになっています。

それではここまでの情報を踏まえて、本題であるElasticsearchの運用について説明していきたいと思います。

これまでのLINEデリマのトピックを大きく分けると3つあります。1つめは、リリース日に某ビジネス番組でプレスリリースの様子が報道されて、そのときに対応した内容になります。2つめは、AdminページからElasticsearchを利用させて欲しいというような依頼があり、その対応を行った話になります。

そして3つめが、某バラエティ番組でサービスの紹介が行われることになり、そのためにElasticsearchのパフォーマンス・チューニングを行った話になります。

LINEデリマにおけるElasticsearchの運用

ではまず、プレスリリース時の対応についてです。サービスのリリース日である7月26日にプレスリリース配信とプレスイベントが行われて、そのプレスイベントの様子が報道されました。この放送の影響で用意していたサーバー数では耐えきれないリクエスト数があり、Elasticsearchのリソースが枯渇して、リクエストをリジェクトしてしまうようになってしまいました。

このときにElasticsearchが受けたリクエストは、1台あたり秒間約4,000リクエストになります。

急遽2台のサーバーをクラスタに追加したんですが、弊社ではverdaと呼ばれるOpenStack製のプライベートクラウドを利用しているので、即座に用意してデータを2台増やすことができました。

この結果、クラスタは次のような構成になりました。

リリース時のクラスタにデータノードが2台追加される構成になっています。この状態でもマスターノードは1台のみで稼働している状態です。この構成で当日は事なきを得ました。

翌日からクラスタの改善に着手しました。まず、先ほどもみてわかるように一番の問題がマスターノードが1台しか存在していないというところで、もしそのマスターノード1台がダウンしてしまった場合に、クラスタとしての構成が失われてしまって、インデックスの作成などが行えなくなってしまうので、早急にこれらの改善を行わなければならないと判断しました。

また、増設にあたってはマスターノードをクラスタの管理のみに集中させたかったので、マスターノードとしてのみ稼働するノードを増やすことにしました。

Elasticsearchのクライアントの設定にもよるんですが、検索フロー上、マスターノードに検索リクエストを行った場合はデータノードから検索結果をフェッチするように動作すると思うので、クライアントであるAPIサーバーがデータのほうにのみリクエストを行うようにアプリケーションの改修も行いました(注:この動作についてはライブラリのオプションを有効化することで回避することも可能)。

検証を行った結果、Elasticsearchはマスターノードのみで稼働させた場合にほとんど負荷がかからない状態となっているので、先ほど説明した社内のプライベートクラウド上でVMを3台用意しました。

また、先ほどのシャードの数の話がありましたが、検証を行った結果、1ノードが2シャードを持つ状態がもっともパフォーマンスが上がったので、プライマリーシャードをデータノード数、レプリカシャード数を1つで、1ノードが2つのシャードを持つ状態にチューニングを行いました。

改善後のクラスタ

この結果、クラスタは次のような構成になりました。

こちらが改善後のクラスタになります。先ほどもお伝えしたとおり、3台のVMマシンがマスターノードとして稼働して、データノード5台を管理するかたちになっています。

また、クライアントであるAPIサーバーは5台のデータノードにのみリクエストを行うようになっています。実際の作業内容に関しては、作業自体はマスターノードを事前にセットアップしておいて、当日マスターノードを起動してクラスタに追加、そして既存のマスターノードをデータノードに変更する、というようなものです。全体の作業時間は20分程度で完了しました。

最初にお伝えしているとおり、数分ごとにバッチがElasticsearchに対してインデクシングを行っているんですが、データ量も少なかったので、今回はバッチも停めずに稼働させた状態で作業を行いました。

ですが、作業が増える反面、バッチを停めてリバランスやアロケーションといったシャードの移動を停めた状態に設定してシャードの整合性を保った状態で作業を行ったほうが、高速にリカバリーされかつ安全かと思います。

今回の作業ではとくに問題にはならなかったんですが、通常時に5Mbpsほどのトラフィックがシャードのフィードなどによって20Mbpsになっていたため、もし通信量が多いような環境だと問題になるかと思います。

AdminページからElasticsearchを利用できるように

では次に2つめのトピックとして、サービスで利用しているデータノードに影響を与えないようにAdminページからElasticsearchを利用したいというような要望が挙がりました。

この要望に対応するために新たにクラスタを構築するのは管理コストなどの問題があると思ったので、今回は既存のクラスタをサービスとAdminの2つの区画に分けるということで対応を行うことにしました。以降、この区画のことはゾーンというように呼称します。

今回追加したのは先ほども申しあげたとおりサービスとAdminの2つのゾーンになります。設定自体はelasticsearch.ymlセットファイルに、こちらに記載されている設定を追加してサーバーをリスタートさせるというようなことになります。

こちらの設定を行ったあとのクラスタの構成が次の図になっています。

バッチのゾーンでも、最低限冗長化を構成するために2台の物理サーバーで基本のクラスタに追加を行っております。こちらの構成でAPIサーバーからはサービス用のゾーンに対して、AdminサーバーからはAdmin用のゾーンのサーバーに対してリクエストを行うような構成になっています。

ではゾーンを追加したことによりどのような状態になるのかを説明したいと思います。クラスタは各ゾーンには分かれてはいるものの、インデックスは共通していて、管理は同じマスターノードが行っています。

設定を追加したことによって、Elasticsearchはゾーンごとにインデックスが完全な状態になろうとするため、事前にレプリカ数を増やしておいてからリバランシングを実施させる必要があります。

ここでいう完全な状態のインデックスとは、例えばプライマリーシャードが5個ある状態だった場合に、新たなゾーンでもこの5個のシャードを配置するようにElasticsearchがシャードの移動を行うというようなものになります。

リバランスが完了したあと各ゾーンのサーバーがなんらかの原因によりダウンした場合は、同じゾーンでシャードの移動が発生します。

今回はデータノードに影響を与えずに、Admin用のElasticsearchを追加したいというような依頼だったのですが、ゾーンを分けることによって検索フローが同じゾーン内に閉じるので、この要件を満たすこともできました。

先ほどの図であったとおり、APIサーバーが投げたリクエストはサービス用のゾーン内にのみ検索が行われ、Adminで投げた、Adminサーバーが投げたリクエストはAdminのゾーン内のみで検索が行われるということだとなります。

これで、今回の、サービスに影響を与えないElasticsearchクラスタを構築することができました。