LINE Financialのサーバーサイドエンジニアの働き方

国兼周平氏:サーバーサイドエンジニアの国兼です。「LINE証券」の開発をしています。

去年の10月、ちょうど1年ほど前にLINEに入社しまして、先日ローンチしたLINE証券では、口座の管理・アカウントの管理を担当していました。その後は新商品の導入チームなどを経て、現在はDevOpsの環境整備をしています。広い範囲でいろんな業務をやらせてもらっています。

前職は独立系のSIerにいて、金融系と公共系の案件を多くやっていました。お堅い世界からLINEに入ってきたんですが、1年経ってだいぶ居心地良くなってきたかなというところです。

我々サーバーサイドエンジニアの主な役割ですが、おそらく想像されていることと大差ないかなと思います。

バックエンド処理。証券業務周りのバックの処理の設計・開発。その結果をフロントに渡すためのAPIの開発。それからサーバー基盤の設計・開発。ここはもっと低レイヤーな部分を担当するインフラのチームがいるので、そちらと協力しながら進めていくかたちです。それから業務要件の定義、企画・QA・運用の担当者のサポートなど、広い範囲の業務があります。

多国籍なチーム

我々のチームの雰囲気ですが、今はだいたい20名ぐらい所属しています。サーバーサイドのLINEエンジニアだけで20名ぐらいですね。

最近入って来た人が多くて新しい組織なので、私はちょうど1年ぐらいって話をしましたが、どちらかというとベテラン側に入ってしまっています。なので、毎月のように新しい人が入ってきて、どんどん雰囲気というか文化が変わっていくといいますか、今まさにLINE証券のサーバーサイドの開発文化が作られている状況です。

いろんな国の人がいます。割合でいうと中国の方が多いかなという感じがします。ちょうど半分ぐらいか、半分よりも少し少ないぐらいが日本人で、そのほかの国の人が半分以上いる感じです。いろいろな仕事を経験された方がいるので、インプットとしてはおもしろい情報がたくさん入ってきます。

あとは特徴的なのが、あまり上下関係のようなものはありません。みんな対等に議論する組織になっています。そうなると、どうしても喧嘩ではないですが、意見が合わなかったりして議論が膠着してしまう状態がたまにあるのですが、そういうときは金融サービスを担当している役員に入ってもらって即ジャッジしてもらい、あまりストップさせずに進めていく雰囲気でやっています。

当たり前ですが、いろいろなチームと連携してやっていくので、ある程度スムーズにコミュニケーションする能力が求められます。

ほかのチーム、例えばLINEの本体のチームはLINE証券だけの面倒を見ているわけではないので、ある程度私たちの要望に迅速に対応してもらうためには、急いでもらわなければならない理由をうまく説明できたり、スムーズに話を通すためには誰に話すのがいいのか、この話はややこしいのでSlackではなく直接会いに行って話す、などいろいろなやり方があります。そんな工夫をしながらスムーズに進めていく能力が求められるかなと思います。

LINE証券はすでにリリースしたので、これからは保守フェーズ、地味な仕事になるのではないかと心配される方もいらっしゃるかと思いますが、そんなことは全くなくて、これからどんどん新機能・新商品をリリースしていく予定になっています。

現在も常にいくつものプロジェクトが並行稼動しているので、けっこうてんやわんやしています。ですので、今からジョインしていただいてもぜんぜん遅くない。スタートアップな文化を体験できるかなと思っています。

LINE証券の技術スタック

技術スタックはこんな感じです。

特殊なものはあまりないのかなと思いますが、メインのモジュールはだいたいJavaベースの言語で開発する感じになっています。基盤周りやバッチ周りでは、たまにPythonやGolangを使うことはあります。

データベース周りだと、MySQL・Redis・Elasticsearch・Kafkaは、証券だけでなく、LINEではよく使われる構成だと思います。特殊な要件がなければ、だいたいこのような感じでやっていくことになるかと思います。

あとは、現在アプリケーションマイクロサービス化・Dockernizeを進めていまして、その関係で、一番下のConsul・Nomadなどの技術を使うことが増えてきています。

環境についてはここに書いてあるとおりですが、これも一般的なものかなと思います。

Verdaと言われているプライベートクラウド、比較的高度なものが社内でサービス化されてまして、これを開発で使うことができます。

ただ、本番の場合は、LINE Financialのサービスではインフラの物理的なアイソレーションが要求されるところがあるので、このVerdaを使うことができません。なので、我々は自分で便利なアプリケーション実行基盤を作っていく必要があります。その話をのちほど少しさせていただきたいと思います。

どんな人におすすめな職場?

こんな人におすすめということで、金融ってあまり開発に重きを置かないというか、技術的な部分を大事にしにくいイメージがあるかもしれませんが、そういったことは私たちの世界ではありません。金融の仕事が好きで技術的なことも好きであれば、両方を好きなだけできるので、ここはおすすめなポイントですね。

あとは、事業の立ち上げに関わりたい人がいたら、ぜひ来ていただけると楽しめるかなと思います。どんどん新しい事業・サービスが立ち上がっていきますので、退屈することはないと思います。

細かいことでは、「1分でも遅刻したらだめ、4回したらボーナスから1万円引きます」とか、そういう会社もあると聞きますが、そういうことは何も言われません。結果だけしっかり出せていれば問題ありません。ミーティングをすっぽかしたりして他の人に迷惑をかけるのはやめようとか、それぐらいです。

あとは、LINEのサービス自体が好きだと、多少の苦しいときも馬力が出やすいのかなと思います。

技術的な取り組み

ここからは、私が今やっている技術的なことについてお話しさせていただきたいと思います。

LINE証券はオンプレの基盤の上で動かすことが前提になっています。LINE Financialの場合、LINE全体で開発・共有されているVerdaという便利なプライベートクラウドを使うことができないので、LINE Financial独自の基盤を用意しています。

これから急速に拡大していく証券サービスは、機能でいうとたくさんの種類があるのですが、そういったものをマイクロサービス化して展開していくには、やはり便利なコンテナオーケストレーションシステムが必要だろうということで、現在急いで作っているところです。あまりこういったものを自分で作ろうという現場は多くないと思うので、貴重な体験かなと思っています。

Kubernetesの導入も検討したのですが、コードベースが大きすぎて中身が把握しずらそうだということと、選択的に機能を導入することが難しそうだということから見送りました。それでスモールスタートも可能な製品・ツールでいったいどんなものがあるかを調べた結果、HashiCorpという会社がやっているConsul・Nomad、 Lyftが中心で開発しているEnvoy 、これらのオープンソースのツールを使うのが良さそうだとなり、今進めているところです。

Consul・Nomadを使ったコンテナオーケストレーションというと、国内ではまだやっているところは多くないと思いますが、とても良いツールなので、私たちが盛り上げていけたら面白いのかなと思っています。

簡単に説明をすると、Consulというのは非常に便利なサービスディスカバリ機能を持っています。ディレクトリサービスのような感じで、DNSとWeb APIでサービスの居場所をほかのノードに展開していけるような機能を持つことができるんですね。

Nomadは、動的なコンテナのデプロイを支援するツールになっています。Envoyというのがサービスメッシュの制御に特化したプロキシサーバで、リバースプロキシを動的に設定変更できるといいますか、たくさんのEnvoyが存在する環境で設定を一括管理できるような機能をもっています。

これらを組み合わせていきます。

実現したいサービスルーティング

実現したい概要、こんなルーティングを実現したいという話なんですが、いちばん右の「Service-A1」などと書いてある部分がマイクロサービス化されたコンポーネントになります。

ApplicationとEnvoyをセットにして、Sidecarパターンと呼ばれていますが、Envoyを通信の入口・出口として定義していきます。

ある程度のサービスの塊をSystemと呼んでまして、いくつかのSystemを大きなクラスタの中に入れていきます。

システム間の通信を中継するコンポーネントとして、API Gatewayを用意します。これはルートの集約という役割ももちろんありますが、例えばあるサービスがgRPCでAPIを公開していたとしても、クライアントからはRESTで使いたいということが実はあったりします。そんなときに、ここでEnvoyのバックにApplicationを1つ入れてプロトコルの変換をしたりします。

あとは、あるSystemについては利用するのに認証が必要だということになると、認証機構をAPI Gatewayに入れてしまおうとか。そういった役割を持っています。ここが中継してSystem間の通信を可能にします。

クライアントからのリクエストを固定のエンドポイントで受けるために、Routerというノードを1つ置きます。ここより後ろはダイナミックな世界になってしまうので、どこに誰がいるかはわからないんですが、ここだけは固定です。

Envoy Control Planeという、Envoyの設定を一括管理するコンポーネントを置いて、これがConsul・Nomadと連携して、どこにどんなサービスがあるかを抽出して、各Envoyにルート情報を配布する仕組みになっています。Kubernetesとよく組み合わせて使われるIstioがやっていることに近いかなと思います。

実際にどうやってサービスの場所をチェックしているのか、ざっくり説明させていただきます。

Hostの中にはDocker Networkがあって、その中にTask Groupという、アプリケーションとSidecarをセットにした1つの塊をつくり、これを複数配置していきます。

複数配置されるので、当然ポートは重複させるわけにはいきませんから、ダイナミックポートでこれを公開することになります。ダイナミックポートで公開すると周りからはどこにいるのかすぐにはわからない状態になってしまうので、どのノードのどのポートでどのサービスが展開されているかを、それぞれのHostの中にインストールされているNomadとConsulのAgentが随時把握して、全体で共有されているConsul ClusterのServiceRegistryに登録します。これをEnvoy Control Planeが監視して、配布する設定情報を作り、それをほかのEnvoysに対して配布していきます。 EnvoyはxDSというプロトコルで設定情報をダイナミックに更新できるので、その仕組みを利用しています。

運用監視のための考慮

せっかくマイクロサービス化してDockernizeした以上、アプリケーション開発者に本来の業務以外の関心を持たせることはよろしくないので、運用監視など基盤周りの都合についてはすべてHostで解決しようという考え方でやっています。

例えばアプリケーション都合の内容で出したログ、これは基盤の運用に関する考慮はされていない状態なんですが、これに対しては加工が必要です。あとはどこに送るのかは、いろいろな種類があります。

ログはいったんjournaldで受けるような仕組みにしています。journaldで受けることによって、Dockerの標準出力経由で出してきたログと、systemd管理下のコンポーネントのログを1箇所に全部集約させることができます。

journaldだと加工が難しいのでいったんFluentdに送りまして、ここでプラグインを書いて、加工したりあちこち送ったりしています。同じようなことをTracingの情報についてもやっています。ですので、全部Hostでプロキシするようなイメージです。

サービスが動的に展開されるので、監視でPrometheusを使っていますと「exporterの場所をどうやってPrometheusに伝えるんだ?」みたいな話になります。Prometheusは、Consulのサービスディスカバリを使ってどこに何がいるかを自分で把握する機能もあります。

それを使うのも1つの手なのですが、Prometheusの管理についてはLINE全体をサポートするDevOpsチームにお願いしていて、証券の都合に関しては証券側で吸収したほうがいいので、それぞれのHostが自分の中で動いているサービスのexporterを代表して中継する仕組みにしています。

これがNomadのデプロイ画面です。

今回はデプロイをキックするところの大部分はAnsibleを使っています。NomadのジョブをCLIから起動するAnsibleのPlaybookを用意しておいて、AWXといわれるAnsible Towerのオープンソース版のツールを使ってキックする仕組みを作っています。

バッチスケジューラ「Airflow」を以前から使っているので、バッチはこちらからNomadのAPIで起動します。 サービスのデプロイはAnsibleから、バッチジョブの起動はAirflowからということで役割を2つに分けて、NomadのCLI/APIを実行して起動します。

「一つひとつ落として、healthyになるまで待っている。healthyになったら次を進めていく」というローリングアップデートがスタンダードですが、「先行して何台かデプロイして、これらがhealthyになったら切り替える」みたいな、ブルーグリーン・デプロイみたいなことも簡単にできます。

サーバーサイドエンジニアはインフラ寄りな仕事をすることもあるので、このあたりももし興味ある方がいらっしゃいましたら懇親会で話しかけていただければと思います。深い話ができたら私もうれしいです。よろしくお願いします。

(会場拍手)