リクルートの情報検索組織において検索APIの基盤をどうやってPaaS中心のシステムに移行したかを紹介する連載。今回は、AWS上のシステムをクラウドネイティブ化する際に用いるべき原理原則について解説する。
この記事は会員限定です。会員登録(無料)すると全てご覧いただけます。
リクルートの情報検索組織において検索APIの基盤をどうやってPaaS中心のシステムに移行したかを紹介する本連載「リクルート事例で分かるIaaS→PaaS移行のコツ」。連載第1回では、情報検索機能を提供する弊組織のスコープとそれを取り巻く環境の変化の歴史的いきさつを解説しました。第2回の今回は、「スコープがシャープに限定されることで、目的達成のためにどのようにクラウドサービスを採用したか」について、われわれのチームが導入した原理原則を交えて技術的な変遷の概要を紹介します。
全体の構成は、初めにサービスとシステムの概要を説明し、「システムにおける各コンポーネントがどのような課題を持ち、それを解決するためにどのようにクラウドネイティブ化したか」を具体的に解説します。次に、クラウドネイティブ化に際し、われわれのチームがその都度導入、参考にした原理原則に関して紹介します。
「クラウドネイティブ化によって各課題を解決する際、われわれのチームがどのように考えたか?」について、原理原則を紹介することによってお伝えできればと思います。内容は、ベーシックなものです。
また、なるべく情報検索に特化せず、情報検索以外のシステムのクラウドネイティブ化に参考になるよう心掛けて記載しました。
試行錯誤や失敗を繰り返し、先人の知恵である原理原則を借りて、あるシステムがクラウドネイティブ化した一例を提供できれば幸いです。
なお、本稿の想定読者は、クラウドサービスを採用する際の、試行錯誤の歴史的な変遷の事例を知りたい方、クラウドネイティブ化におけるチームが採用した原理原則に興味のある方です。
初めに、積極的にクラウドネイティブ化した時期における、提供サービスの背景について説明します。われわれのチームは、検索機能の品質向上をメインに担当するチームですが、同時にサービスを運用するチームでもあります。
われわれのサービスは、情報検索機能のAPIを提供することであり、マイクロサービスにおける1つのサービス/コンポーネントと考えることができます。基本的に、複数のサービスを同じコードベースの共通のシステムで提供していますが、マルチテナントではなく複数のシングルテナントです。われわれのシステムで提供されているサービスは、本記事執筆時で、次のような状態にあります:
本記事では、次の2点を主に扱います。
われわれのシステムは大別して、以下5つのコンポーネントから成り立っています。
各コンポーネントは新旧の世代で混在した状態です。そのような状態ですが、コンポーネント単位で気軽に入れ替えが可能な状態になるまでの事例紹介にもなればと思います。クラウドネイティブ化を進めることによって、各コンポーネントを互いに疎結合にすることが促進され、フレキシビリティを向上させることもチームの目標の一つです。
ここまでのサービス、システム、コンポーネントの関係は図1のようになります。幸い、われわれの扱う情報検索機能は、非常にシンプルな構成をとることが可能です。
連載第1回で触れたように、われわれのシステムの目標は明確になり、スコープが絞り込まれました。
目標は、サービスの改善や新規サービス追加の際、「短期学生バイトや入社直後の新卒の方でも動くAPIを作ることができ、そのAPIの品質向上に利用するデータやアルゴリズムの探索に集中」できることです。われわれのチームに参加してもらったエンジニアが、すぐさま検索サービスの提供や検索品質の改善に集中できるようにすることです。そして、「ユーザー体験やアルゴリズムの試行錯誤を重視した開発の比重が大幅に高まった」ので、それ以外の仕事に割かれるリソースを徹底的に削減し、「フォーマット化、もしくは、テンプレート化」できるようにスコープを絞ることでした。
目標とスコープを先に挙げた5つのコンポーネントに当てはめれば、それぞれに上げた目的に開発者が集中できることであり、フレキシビリティを向上させて試行錯誤を可能にすることです。
われわれのチームの目標とスコープを実現するため、旧世代のシステムから新世代のシステムに移行し、その過程で積極的にクラウドネイティブ化した技術的な変遷の内容と、その過程で採用した原理原則の紹介が、本記事の扱う内容です。
各コンポーネントにおけるクラウドネイティブ化の技術的な変遷を紹介します。何世代かのシステムの変移を、その過程で挙がった課題とその解決を中心に、比較的汎用(はんよう)性の高いコンポーネントを例に紹介します。また、現在検討中の未来像に関しても簡単に触れます。
当初、フェーズ1の状態にあったわれわれのシステムでは、CI/CD(継続的インテグレーション/継続的デリバリー)をJenkinsサーバで行っていました。Jenkinsサーバは、CI/CDに加え、ETL(データ連携、インデックス更新処理)や分析処理のコントロールだけでなく、ETLや分析処理における一部の処理の実行も担っていました。サーバは「Amazon EC2」上で動作し、サーバの構成管理を「Chef」で行います。
残念ながら、Jenkinsサーバは、後ほど紹介する「ペットと家畜」の「ペット」状態でした。Jenkinsサーバがなくなっても、辛うじてサービス自体は継続できますが、その後何もできない状態になります。多少の時間をかければ再構築も可能でしたが、手軽に交換、更新、破棄できる状態ではありませんでした。
特に問題となったのは、Jenkinsサーバが本来データ連携、インデックス更新処理、分析処理という個別のツールやサービスで行うべき処理をローカルの環境で実行していたことです。これは、データや実行時間の増加に伴ってスケールアウト/スケールインができない状態です。
また、後に触れる「単一責任の原則」に違反しているので、Jenkinsの構成自体も肥大化してしまいました。サービスの追加も肥大化に拍車を掛け、「一貫性」は辛うじて構成管理のリポジトリレベルで保持できている状態です。
結果として、もっとも重要な試行錯誤を気軽に試せる状態ではなくなってしまいました。
そこで、フェーズ2への移行とともに、CI/CDの実行環境をサーバレス化し、ETLや分析処理を切り離し、本来のCI/CDの機能、ETLや分析処理のコントロールの実行のみに変更しました。
サーバレス化は「AWS CodeBuild」「AWS CodePipeline」「AWS CodeDeploy」への置き換えです。特にCodeBuildは、Dockerイメージを指定します。個別の実行単位となる各ビルドプロジェクトは、それぞれ限定されたほぼ単一の機能だけになり、Dockerイメージは機能単位を分割してシンプルで独立した状態にすることができました。ETLや分析処理に関しては、次のセクションで詳しく触れます。
詳しくは、連載の後の回で触れますが、次の5つの大きなCI/CD機能を独立してテンプレート化し、手軽に構築、変更、破棄が可能な状態に近づきました。
ここで簡単にですが、構成管理に触れます。Jenkinsサーバの構成管理ではChefを利用していましたが、その後「Ansible」「Puppet」を検討し、さらにクラウドへの特化という文脈で「Terraform」と「AWS Cloud Development Kit」(CDK)を検討しました。最終的に、Pythonベースの開発が多いわれわれのチームは、「AWS CDK in Python」を採用しました(実を申し上げれば、当初AWS CDKを「TypeScript」で記述していましたが、その後「一貫性」の文脈で、可能な限りPythonを採用する方針に転換したので、AWS CDK in Pythonに書き直しました)。
Copyright © ITmedia, Inc. All Rights Reserved.