「LINE DEVELOPER DAY 2019」レポート

DAY-1、時系列データベース‘Flash’とはLBaaS実現への

LINE⁠株⁠は11月20日と21日の2日間、東京・お台場の「グランドニッコー東京 台場」で、同社が運営するサービスや技術領域でのチャレンジ、今後の取り組みなどを紹介する技術カンファレンス「LINE DEVELOPER DAY 2019」を開催しました。

画像

今年で6回めを迎える同イベントですが、今回は初の試みとして2日間にわたっての開催です。初日は「Engineering」をテーマに技術関連の話題が、2日めは「Production」をテーマにプロダクト開発に関する実践的な話題が各種セッションで紹介されました。本稿では、その中から、初日に開催されたXuanhuy Do氏と早川侑太朗氏によるセッションの模様をお届けします。

事前に登録しておくことで、顔認証でも受付が行えるようになっていた
事前に登録しておくことで、顔認証でも受付が行えるようになっていた 事前に登録しておくことで、顔認証でも受付が行えるようになっていた

「LINEが開発した時系列データベース‘Flash’の紹介」by Xuanhuy Do氏

LINEのObservability Infrastructureチームのエンジニアマネージャを担当しているXuanhuy Do氏より、⁠LINEが開発した時系列データベース⁠Flash⁠の紹介」というテーマでセッションが行われました。

Xuanhuy Do氏
Xuanhuy Do氏

Observabilityとは、アウトプットと推測という意味で、アプリからのアウトプットによってその状態を調べることができるというものです。Xuanhuy Do氏が所属するObservability Infrastructureチームの役割は、開発サービスの健康状態を保つことです。

膨大なメトリクスをさばくプラットフォーム

同チームでは、現在3つのインフラを提供しています。1つめは、メトリクス収集です。マシンのCPUやメモリの状況を、数字で表せるアラートやグラフとして提供しています。2つめはログです。アプリ内で発生したエラーなどをアラートとして届けたり、可視化したりするための基盤の提供です。3つめは、分散トレーシングです。こちらは別の機会があったときに、紹介していただけるとのこと。

アプリケーションのメトリクスは重要で、外すことができないものです。アプリがユーザに安定的に提供できているか、あるいはレイテンシが満足できるものなのか。こうしたものは、メトリクスがなければ判断できません。

現在同チームがさばいているメトリクスの数は、2016年から比較すると今年は20倍に増えており、来年はさらに5倍に増える見込みです。そのおもな理由としてはビジネスの成長やマイクロサービスの増加などが挙げられます。

メトリクスをグラフ化
メトリクスをグラフ化

LINEのメトリクスプラットフォームでは、自社で開発したエージェントをサーバにインストールします。そのエージェントがホストのメトリクスをプッシュし、データ収集サーバがメトリクスストレージに格納し、それをユーザがグラフのUIやアラート設定に使用します。このメトリクスストレージに使われているのが、同チームが開発した「Flash」です。

メトリクスプラットフォームの概要
メトリクスプラットフォームの概要

ストレージを2つのマイクロサービスに分ける

同チームが作ってきたメトリクスストレージの歴史は、LINEのメッセンジャーが作られる前にさかのぼります。2011年にMySQLで作られましたが、データの圧縮に不向きなところやレイテンシなどさまざまな問題を抱えるようになってきたことから、2017年には新たなストレージに変更しています。このときに採用したのがOpenTSDBです。OpenTSDBのメリットは、サーバを追加すればするほど書き込みがスケールするところです。しかし、読み込みはそれに比例しません。Facebookの「Beringei」やNetflixの「Atlas」など、いくつかのオープンソースも試してみたものの、読み込みは速いが書き込みが遅かったり、安定性に欠けていたりといった問題がありました。そうしたことから、ストレージを自分たちで作ることにしたそうです。

「Flash」を作る際には、3つの要件を満たす必要がありました。1つめは、いずれのプロトコルであってもユーザが使えるようにすること。2つめは、スケールアウト性能が高く、低レイテンシであること。3つめは、低コストでメンテナンス性が高いことでした。

これらを実現するために、同チームはまずメトリクスストレージを2つのマイクロサービスに分けました。1つは、テキストデータを格納するためのサービス、もう1つは数値を格納するサービスです。

メトリクスプラットフォームでは、CPUのモニタリングなどを行います。CPUのモニタリングデータには、ラベル({"HOST"="Host1"}{"Zone"="JP"}など)と、時間ごとの値であるデータポイント(⁠⁠12:00,0.5」など)が含まれています。

CPUのモニタリングデータ例
CPUのモニタリングデータ例
格納するポイント
格納するポイント

この2つを別々のストレージに格納することで、テキストデータであるラベルと、数値データであるデータポイントそれぞれに合わせて最適化ができるようにしています。

ストレージのアーキテクチャ
ストレージのアーキテクチャ

また、読み込み/書き込みの両方の性能を確保するために、データポイントのストレージをさらに2つに分け、直近28時間以内のデータポイントをインメモリのストレージに、28時間を経過したデータポイントを永続型のストレージに移すことにしています。

データベースを自ら開発したといっても、すべてを1から作り上げたわけではありません。車輪の再発明にならないように、自作しなくてもよい部分に関しては既存のサービスを利用しています。たとえば、ラベル用のストレージには「Elasticsearch」を採用し、永続型のストレージには「Cassandra」が選ばれています。

データベースの作成には5年かかると言われていますが、プロジェクトがスタートしたのは2018年末で、2019年には早くもリリースされて、現在すでに本番稼働中です。しかし、プロトタイプ自体は2ヵ月でできたものの、その後実際に本番環境にリリースするまでには1年間という時間がかけられています。簡単にできるものは短時間で完成しますが、本当にベストのものを作るには時間が必要になります。

今後は、メトリクスの数も増えていくため、パフォーマンスや信頼性をより高めていくと語り、セッションを締めくくりました。

「LINEの独自LBaaSを支えるソフトウェアエンジニアリング」by 早川侑太朗氏

LINE ネットワーク開発チーム インフラエンジニアの早川侑太朗氏より、⁠LINEの独自LBaaSを支えるソフトウェアエンジニアリング」というテーマでセッションが行われました。

早川侑太朗氏
早川侑太朗氏

「Verda」は、LINEのプライベートクラウドのコンポーネントの1つで、2016年頃より社内で運用されている、OpenStackベースのクラウドサービスです。LINE本体をはじめとして、多くのサービスがVerdaの上で運用されています。

同社内では、従来のインフラから「Verda」への移行が進んでいます。現在は、1,400のハイパーバイザ、3万5000のVMを収容するなど、大規模なプラットフォームとなっています。昨年は1年間で2万のVMが新たに作られるなど、その利用範囲も急激に拡大しています。

LINEのプライベートクラウドを支える完全自社開発のLBaaS

現在「Verda」で提供されているサービスは多岐にわたります。コンピューティングやネットワーキングなど基本的なインフラリソースを提供することに加えて、K8SやKafkaなどマネージのミドルウェア、最近ではFaaSなども乗せて運用されています。

同社が開発しているロードバランサは、これらの中でもコンピューティングやネットワーキング、ストレージと並ぶIaaS群の1つです。

「Verda」の概要
「Verda」の概要

「Verda」におけるLBaaSの役割は、LINEの各種サービスに対してスケーラブルで耐障害性の高いサービスを提供することです。デベロッパは、LBaaSが提供する抽象化により、あたかもロードバランサがそのサービス専用のものであるかのように運用できるようになっています。

実際には、全サーバ共通のロードバランサクラスタが用意されており、そこからリソースを切り出して使う形になっています。早川氏の所属するチームでは、この共通クラスタや、デベロッパに対するAPIサーバなどの開発や運用を行っています。

LBaaSの概要
LBaaSの概要

多様なサービスを提供しているLINEですが、そのためロードバランサも1つの汎用性の高いものを提供するだけでは広範なニーズに対応できません。そこで同社では、ロードバランササービスの中でも2種類のサービスを提供しています。

1つは、L7LB(Layer7 Load Balancer)と呼ばれているものです。こちらは、Webサービスなどでお馴染みのいわゆるリバースプロキシです。httpのパスやヘッダの内容をもとに、アプリのリクエスト単位で負荷分散をしていきます。

もう1つは、L4LB(Layer4 Load Balancer)です。こちらはアプリよりさらに下のレイヤの、IPアドレスやポート番号といった情報をもとに、TCPのコネクションレベルで負荷分散を行います。

この2つは、社内に持つユースケースで棲み分けが行われています。L7LBは、L4LBと比較してリッチな機能が備わっています。一般的なWebアプリでは、こちらを使うことでほとんどのユースケースに対応できます。

しかし、LINE本体のメッセージングサービスや動画配信、メディア配信といったパフォーマンスが求められるものでは、L7LBではオーバーヘッドが大きくなってしまいます。そのため、よりシンプルで高速なL4LBが好まれる傾向にあります。一般の人が目にするところで使用されている例としては、テキストメッセージやビデオ、アイコンに使われるイメージなどがあります。また、⁠LINE BLOG』『LINE Clova』といった、一部サービスでも利用されています。

「Verda」の利用範囲は広がってきており、それに伴いロードバランサのユーザ数も年々増えていくと予想されています。

このように、LINEの中でもかなり重要な位置を占めているロードバランサですが、既製品を購入してそのまま運用しているというわけではありません。ロードバランササービス自体を自社開発しています。デベロッパがロードバランササービスにアクセスするためのAPIサーバや、L7LB、L4LBのサービスも含めて、すべて自社で独自開発して運用されているのです。中でもL4LBでは、実際のユーザのトラフィックを処理するData Planeと呼ばれるところから、ほぼスクラッチで開発されています。

既製ロードバランス製品の問題─⁠─運用コスト、スケーラビリティ、アベイラビリティ

なぜ既製品を使わずに、自社開発を行っているのでしょうか? これについては、LINEが既製品のアプライアンスを運用していく中で直面してきたさまざまな問題から、最終的に自社開発を決断したという背景があります。その問題とは、運用面のコストとスケーラビリティの問題、アベイラビリティの問題です。

「Verda」のロードバランサができる2016年以前は、既製品でサービスが提供されていました。そのときは、1+1と呼ばれるロードバランサを2台使い、アクティブスタンバイで動かす方式がとられていました。多くのユーザはL4LBを使い、必要に応じてL7LBが提供されるといった運用が行われていました。

サービス規模が小さいうちは問題ありませんでしたが、サービス規模が拡大していくにつれてさまざまな問題が起きるようになってきました。1つは運用コストの問題です。当時のロードバランサは、CLIベースで人がマニュアルで操作することが前提になっており、オートメーションが非常に難しい状態でした。オペレータの手が空いていなかったときは、デベロッパがロードバランサの利用申請を出してから1〜2日経って、ようやくリクエストが処理されるという形になっていました。これらはオペレータとデベロッパの双方にとって、ストレスが高いものとなっていました。

社内でロードバランサの需要が高まっていくにつれて、こうしたオペレーションの問題は無視できなくなってきたのです。スケーラビリティとアベイラビリティにも問題を抱えており、その根幹にあったのはセッションテーブルの枯渇問題です。これらは、L4LBの実装方法に起因していました。

L4LBを実装する方法は数多くありますが、その中でも今現在どのサーバにどのクライアントが接続しているのかという対応関係を、TCPのコネクション1つごとにセッションテーブルと呼ばれるデータ構造に記憶していく方式があります。当時採用された方式はこちらでしたが、同時接続しているクライアントの数があまりにも増えてしまうと、セッションテーブルの容量が枯渇し、それ以上新しいコネクションを受け付けられなくなってしまうという弱点があります。同時に接続できるクライアントの数が、セッションテーブルによって制限されてしまうということです。

また、セッションテーブルのメモリ容量を意図的に枯渇させることができるTCP SYN FloodというDOS攻撃があります。この攻撃を受けると、セッションテーブルがサービスにとってまったく意味のない情報で埋め尽くされてしまいます。その影響は、ロードバランサに登録されているすべてのバックエンドサーバにおよぶため、非常に広範囲で障害が発生してしまいます。

スケーラビリティ、アベイラビリティの問題
スケーラビリティ、アベイラビリティの問題

多層のロードバランサアーキクチャ

そこで、ロードバランサ設計の根本的な見なおしが行われ、新たに3つの要件が設定されました。1つめは、デベロッパとオペレータの両方のオペレーションコストを減らすことです。従来までの手動ベースのものではなく、APIドリブンで、人の手を介さずに、ユーザがロードバランサを必要なときにすぐに手に入れられるようにする必要があります。

2つめは、サービスの拡大や突発的なトラフィックの増加に応じて、しっかりスケールできるということです。もともとあったセッションテーブルの枯渇問題への対処のほか、必要に応じて容易にロードバランサの数を増やせるようにします。

3つめは、アベイラビリティに関するもので、スケーラビリティに関する要件と同じですが、容易にロードバランサの数を増やして冗長化できることに加え、障害時にその影響の範囲を可能な限り小さくすることです。

こうしたロードバランサを考えるうえで参考になったのは、GoogleやFacebookといった大手のロードバランサの設定でした。2010年から2016年にかけて、大手企業が論文やブログでロードバランサに関する発表を数多く行いました。それらには、すでに自社開発のロードバランサが使用されており、それに至った経緯や5年以上の運用経験から得た知見が盛り込まれていました。リサーチの結果、こうした大手企業も当時LINEが抱えていたのと共通した問題を持ち、独自開発に至った経緯があることがわかりました。

その結果採用されたのは、大手でも事例の多い多層のロードバランサアーキクチャでした。これは、サーバをL7LBやL4LBで負荷分散して、そのL7LBをL4LBで負荷分散するという、複数のロードバランサを多段でつなげるような構成になっています。

多層構造のロードバランサアーキテクチャ
多層構造のロードバランサアーキテクチャ

ロードバランサクラスタの各種コンポーネントを束ねるコントローラは、シンプルなPythonのWebアプリとして実装されています。おもな役割は、APIでデベロッパからのリクエストを受け、ロードバランサの作成・削除・設定といったオペレーションを自動で行うことです。これらは、⁠Verda」の専属UIチームが開発したもので、直感的に操作が行えるようになっています。

ロードバランサのコントローラ画面
ロードバランサのコントローラ画面

自動テストとCI/CDでサービス性能を維持

ロードバランサによってパフォーマンスを出すことも重要ですが、それをいかに維持するかということも重要な要素です。高いパフォーマンスは、L4LBのユーザが期待するサービスの一部であり価値でもあります。新機能開発でコードに変更が行われたときに、パフォーマンスが低下したという事象に、いち早く気が付けるようにしておく必要があります。

これらは、自動テストやCI/CDでコードの品質を担保していくことで、継続的にパフォーマンスの計測も行っていかなくてはならないということでもあります。そこで取り組んだのが、パフォーマンステストの自動化です。

個人の開発者がそれぞれパフォーマンスをテストし、その結果をアップロードするというやり方もできますが、実験環境やちょっとしたパラメータの違いなどが生じて、結果どうしを平等に比較できないことがあります。

それを避けるために、共通のテストベッドを用意したほか、開発フローに乗せることができるようにGitHubから自動的にCI/CDのプラットフォームを介してテストがトリガされるようにしています。こうしたしかけによって、継続的なテストを行うことが可能となっています。

PullRequestをトリガにパフォーマンステストが自動で行われるしくみ
PullRequestをトリガにパフォーマンステストが自動で行われるしくみ

蘇るセッションテーブルの枯渇問題

続いて、デベロッパからの要請で機能追加を行った事例の紹介が行われました。L4LBをステートレス化することで、過去の運用で問題になっていたセッションテーブルの枯渇問題は解決できましたが、ステートレス化することで新たな問題も生じています。それは、サーバのグレースフルシャットダウンができなくなるという問題です。また、フェールオーバーも難しくなります。その問題の原因は、ステートレスのL4LBの実装にあります。

パケットに書かれているクライアントとサーバの識別情報(5tuple)をもとにHash表を引き、転送先のサーバが決定されるというアルゴリズムでした。この方法では、パケットに書かれている情報から計算のみで転送先を決定できます。そのため、どのクライアントがどのサーバにつながっているのかといった情報をロードバランサに記録しておく必要がなく、ステートレス化を実現していました。

L4ロードバランサのステートレス化に起因する問題
L4ロードバランサのステートレス化に起因する問題

サーバ管理者がアプリをアップデートするために、一部のサーバをシャットダウンするとHash表を更新する必要があります。このとき、停止するサーバへのコネクションは来ないようにしたうえで、すでに接続されているクライアントは接続が終了するまで待ってシャットダウンしますが(グレースフルシャットダウン⁠⁠、ステートレスのロードバランサではこうしたことはできません。また、Hash表を更新したときに、他サーバの既存のセッションが切れてしまう可能性があります。これがフェールオーバーが難しいという問題です。

それらの問題に対処するために、セッションキャッシングと呼ばれる手法が採用されています。これは、Hashで求めた転送先を、セッションキャッシュと呼ばれるキャッシュに随時保存していくという方法です。

ユーザからパケットが来たとき、セッションキャッシュを検索してヒットすれば、そのアドレスに転送します。キャッシュミスの場合は、通常のHash表で転送先サーバを決定し、その結果をキャッシュに記録していきます。

これにより、サーバがサービスアウトしたり障害が発生してHash表が更新されたりした場合でも、情報が残ったままの状態になります。セッションキャッシュのサーバが生きているうちは、どのサーバとどのクライアントがつながっているのかという情報がロードバランサ上に残っています。そのため、セッションが切れてしまうという事態を防ぐことができるのです。

セッションキャッシング
セッションキャッシング

しかし、このセッションキャッシングは、過去に問題になっていたセッションテーブルの枯渇問題と同様の問題を抱えています。同時接続しているクライアントの数が増えると、セッションキャッシュの容量が圧迫されていきます。さらに、TCP SYN Flood攻撃を受けると、意図的に枯渇が誘発されます。

つまり、ロードバランサをステートレスにすると、セッションテーブルの枯渇問題は解決されるものの、グレースフルシャットダウンやフェールオーバーができなくなります。しかし、セッションキャッシングを用いた実装にしてしまうと、TCP SYN Floodといった攻撃に弱くなってしまうのです。

こうした問題を解決するために選択した方法が、ステートフルとステートレスを状況に応じて使い分けるというハイブリット的な手法です。通常時はセッションキャッシュを用いたステートフルなモードでロードバランサを動作させますが、TCP SYN Flood攻撃を受けると、一定時間ステートレスなモードにフォールバックします。これにより、グレースフルシャットダウンやフェールオーバーがやりやすいステートフルな実装を使いつつ、他者からの攻撃からも強いロードバランサを実現しています。

これらは3ヵ月ほどかけて実装され、現在も稼働中です。この機能をリクエストしていたメディアプラットフォームのチームは、検証を終えて「Verda」にサービスを移行しています。個々のアプリの要求に応じて必要な機能を実装していくことにより、柔軟にLINEのサービスに特化したロードバランサの開発を目指していく予定です。

詳細なレポートや資料、動画はLINE Engineering Blogで公開される予定です。ぜひこちらもご覧いただき、会場の雰囲気や盛り上がりを体感してみてください。

おすすめ記事

記事・ニュース一覧