オンライン本人確認機能 (eKYC) に Lambda を採用した振り返り

Hiromichi Ema
Eureka Engineering
Published in
11 min readDec 21, 2020

はじめに

※ この記事は Eureka Advent Calendar 2020 の21日目の記事になります。

こんにちはエウレカでサーバーサイドエンジニアとして働いてる江間(@emahiro)です。普段は Pairs の開発や運用をメインにやりつつ、苛立つ手運用プロセスを(かなり強引に)改善したり、そういう謎運用を光の彼方に消し飛ばすためのあれこれを飯の種にしています。唐突ですが、好きなサーバレスは Google App Engine (GAE/Go) です。

このエントリでは、10月にリリースした Pairs におけるオンラインでの本人確認機能(以下 eKYC) の導入に際して Lambda をベースにしたフルサーバレスのサブシステム構築にチャレンジしたことを中心に、そもそもサーバーレスを選定した背景やエウレカで今後サーバーレスとどのように付き合っていくのか?という内容についてお話ししたいと思います。

TL;DR

  • eKYC の実装にあたって Lambda を導入しフルサーバレスでサブシステムを構築したこと。
  • エウレカでの今後のサーバーレススタック(Lambda メイン)の商用環境における利用についての展望(半分僕自身の希望)

そもそもオンライン本人確認 (eKYC) って何?

銀行や証券口座などの開設時に求められる本人確認をオンラインで完結させるプロセスのことを言います。各種ウォレットアプリをはじめとした金融系のサービス等ではオンボーディングで当たり前のように入ってくるようになっているプロセスでもあるので、目にしたことのある方も多いのではないでしょうか?(身分証明書と自分の顔をセットで撮影したりといったああいうやつです)

Fintech 領域ではお馴染みになりつつある eKYC ですが、年々利用者が増加しているマッチングアプリ業界においても、ユーザーのみなさんが安全かつ安心してサービスを利用できることの重要性が高まっており、より安全なプラットフォームにしていくことを目的に、Pairs でも従来の年齢確認に加えて、ユーザー本人の実在性を担保する eKYC を導入(※1)しました。

※1. https://eure.jp/press/20201008

なぜ Lambda を採用したのか?

主な理由は以下の3つです。

  1. モノリシックなアプリケーションに実装することによる開発生産性の低下への懸念がそもそもあったこと
  2. AWS のツールセットが揃ったこと
  3. Pairs においてサーバレスのプロダクションでの利用にチャレンジしたかったこと。

それぞれ詳しく説明します。

まずエウレカの現時点でのメインストリームは ECS です。Pairs はコンテナの上で Go のアプリケーションとして動いており、Lambda のプロダクション環境での利用実績はありませんでした。(※1)

Pairs はいくつかモジュールとしては分割されていつつも、ベースにあるのはモノリシックな Go のアプリケーションであり、モノリシックなアプリケーションならではの開発のしやすさはある一方、巨大なコードベースの上で開発することによる CI ・デプロイの遅さ、他の実装とのコンフリクトにより開発生産性が下がること、巨大なモノリスなサービスに乗せることで意図しない不具合に遭遇するなどと言った懸念があり、こういった実装時点での開発のつらさを避けたかったという思いは元々持っていました。加えて、eKYC の根幹である、本人かどうかを確認するプロセスについては Pairs 本体とは独立させて非同期で動かすことが可能、ということが最初からわかっていたこともあり、Lambda でサブシステムとして実装することでつらみを回避できる可能性がありました。

次に、今年の7月に RDS Proxy が GA になっていたことも渡に船でした(※2)
eKYC で必要になるユーザーの情報等は全て MySQL (Aurora) に入っており、もし MySQL に Lambda からシンプルにアクセスした場合、コネクションを自前で管理するのがめんどくさい問題がありました。RDS Proxy を使えば Lambda から MySQL に接続する時にコネクションをプールして再利用してくれるので当初想定していた課題は解決されますし、実装では特に何も意識することなく MySQL 上にある既存のデータを扱えます。
(※後述で注意点記載あり)

この上記2つの理由に加えて、僕はサーバレスが大好きなので、エウレカにあってもなんとかしてサーバレスにチャレンジしてみたい、ということを入社して少ししたくらいから考えていました。ちょうど要件的にもフィットしそうだし、そのことを SRE の @fukubaka0825 さんに相談したら、Lambda を激推しされた(推してくるということは何かあっても助けてくれるはず…!)ので、いい機会だと思って Lambda を中心に据えたサブシステムで実装することを決定しました。

※1. Class Method さんのこちらのエントリが詳しいです 。

※2. 202012 現在 RDS Proxy は Read/Write 構成を取ることができないので、いくら RDS Proxy があるとはいえ、参照系のクエリすらマスタを叩くことになります。仮にLambda が急速に増殖してしまう場合には、結局 Aurora 本体のコネクションを食い潰してしまうので、事前に RDS Proxy 経由でクエリを叩く Lambda の増加傾向やユースケースを精査してキャパシティプランニングしておくことは必要です。RDS Proxy 側でもコネクションのどれくらい使うか?を制限可能ですが、制限した結果応答速度が遅くなったり、エラーを返したりするので、それがそもそもどれくらい許容できるのか?と言ったことを考える必要はあります。

実際に採用してみてどうだったのか?

Good

  • サブシステムとして小さなコードベースで実装できたので開発生産性は高くなりました。
    実装においては Serverless Framework に完全に乗ることを選択したので、設定やデプロイパイプラインも整備が容易でした。eKYC 機能のリリースの当初はエンジニアによる手動デプロイを採用していましたが、すぐに Github Actions を使ったデプロイに切り替えて、現在は master に merge したタイミングで自動でデプロイされるようになっています。
  • 既存のアプリケーションの負の部分の影響を受けずに開発を進めることができました。
    特にテスタビリティを担保して実装を進めることができたので、効率的なデバックやコードの品質を担保できたのはよかったと思います。
  • SRE チームと協力して新しい技術をプロダクション環境に導入できたので、会社として採用できる技術の幅が広がりました。
  • そんなに頻繁に使われる機能、というわけでもないですが、リリースした直後を除いては安定稼働しており、ほぼ運用レスで動いてくれています。

More

  • 実装した際にAWS に不慣れだったのもあり、VPC 上に Lambda を立てたり、AWS の各リソースに接続する部分で相当手間取りました。自分がAWSにガッツリ触れた初めての機会だったのもあり、SRE チームに相当助けてもらいました。
  • 既存の Pairs から独立したサブシステムで、かつ非同期で動作するために、非同期システムならではのデバックの難しさがありました。特に Cloud Watch Logs の使い方に慣れるまで生ログ全検索でログの検索をやっていたので非常に時間がかかりました(※1)
  • 実際にサービスインしてみてから気づきましたが、同時実行数周りのケアについても今後はもしかしたら課題として上がってくるかもしれないな、という予感があります。実運用を見据えて考慮するべき事項については Masashi Yamamoto さんのアドベントカレンダーが参考になるので目を通しておくといいかもです。

※1. 現在は Cloud Watch Logs Insight を使っています。多少のラグはあるものの文字列でフィルタをして高速に関連するログを拾ってくれるので役に立っています。

結論

AWS の各種リソースの設定や実装につまづいたことを除けば、リリースまで比較的スムーズに進むことができました。また新しい技術領域でチャレンジすることがモチベーションになりましたし、総じて Lambda を採用したこと自体はポジティブだったと考えています。

一方で、かなり「えいや」で実装したので、Lambda を採用したことによる課題も残りました。 特にアラート監視と可読性の高い構造化ログがないことによる運用時の状態把握が困難な問題がリリースしてから1ヶ月ほど続いてしまい、ユーザーに迷惑をかけてしまったのは反省点です。
※ 現在は問題は大体解消されています。

リリース後も SRE チームも定期的にサーバーレスの運用についての Sync を行っており、アラート監視はとりあえず勘で閾値を決めて、現在運用をしながら調整中です。ただ、繰り返しになりますが、あまり多く使われる機能でもなくアラートがほとんど来ない(たまに外部ベンターとの接続が不調でエラーになる程度)ので、これでうまく言ってる!と言い切れないのが悲しいところです(※2)

また、構造化ログについては Opencensus の分散トレーシングのパッケージを利用して起動ごとに trace を取得(※1)して CloudWatch Logs Insight を使って trace ごとにログをまとめて出力できるようにしたので、生ログを全検索していた時期に比べるとだいぶマシになりました。

※1. Lambda 用に trace 付きでログをまとめることができるロガーをつくって Github に公開中です。

※2. ハードウェアリソースやレスポンス容量上限等も今回のユースケースでは特に問題になってません。言い換えると割と Lambda を最初に導入する機能としてはよかったと見ることもできます。

今後の Lambda 採用の展望

(先日の re:invent でも Lambda 周りの改善が多数発表されており、すごい勢いで進化してるなと感じますが) Pairs では Lambda をメインストリームとして活用していくことは時期尚早じゃないかなと思っています。

特にLambda を採用した理由でも説明しましたが、 Pairs ではユーザー情報などをはじめとした基本的な情報は RDS 入っており、Lambda をサービスの中核におく場合、その情報等にアクセスするには RDS Proxy を使って接続することになります。
しかし、Lambda の採用理由の注釈3でも記載した通り、RDS Proxy が202012 現在 read/write 構成を取ることができないので、参照系のクエリすら master に向けて叩いてしまい、master の負荷が上がってアプリケーション全体に影響を及ぼしかねません。このため、Lambda × RDS Proxy を使う場合には事前の設計だったり、キャパシティプランニングが重要になります。Lambda を選択して得られるメリットもありますが、現状では Lambda での実装のために事前調査等に時間をかけるくらいなら手慣れている ECS をファーストチョイスとして事業に貢献していく方が良いとされる状況がまだしばらく続くと思っています。運用周りも含めてもう少し手慣れてから適材適所で導入を広げていくような流れで Lambda を浸透させていくのが無難ではないかなと思っています。

ただ、今回 Lambda を中心としたサーバレスの技術をプロダクション環境で使ってみて、サーバーレスを実運用で使う良し悪しを再確認できたと共に、こうした技術検証をプロダクション環境で小さく試せることで、影響範囲を狭めつつ今後に活きる知見を得ることができました。

開発環境で試してみるのもいいですが、やはり本番用に作ってみる方が学びはありますね!

僕個人としてはサーバレスが大好きですし、これからもまだまだ成長をしていくであろう日本最大級のマッチングサービスを支える技術として Lambda の採用事例を少しずつ増やしていきたいなと思っています!大規模サービスでサーバレスにチャレンジしてみたい!という方はぜひお話ししましょう!色々議論できると思います。

では明日のエントリもお楽しみに〜👋

--

--