自己紹介と本日の概要・目次

髙塚大暉氏:こんばんは。「ZOZOTOWN(16歳)の悩みをSREが赤裸々に語る」というタイトルで発表します。私は、ECプラットフォームSREチームの髙塚です。AWSとKubernetesでマイクロサービス基盤の構築・運用に従事しています。

本日の概要と目次です。今年で16年目のZOZOTOWNは、思い出だけでなく、技術的な課題もたくさん抱えています。今日はまず、昔からの悩みを説明して、次にアーキテクチャがどう変わってきたか、そして16歳になった今、どのような悩みが生まれてきたかを赤裸々に語ります。

第1章:ZOZOTOWNが抱えていた昔からの悩み

それでは、第1章「昔からの悩み」です。ZOZOTOWNは2004年に生まれ、以来アーキテクチャを変えずに規模を拡大してきました。

(スライドを指して)これがそのアーキテクチャです。オンプレ環境の上にWindowsサーバーで動いています。SQLサーバーのDBにロジックが載っているのが特徴で、いわゆるストアドプロシージャを活用しています。また、言語はVBScriptで動いています。

2004年当時はネットワークが貧弱だったので、このアーキテクチャは成功であったと言えます。しかし現在においては、このストアドをスケールしづらかったり、テストをかけづらかったり、ASPとのロジックの二重管理という問題が発生したりしてきました。また、この後説明するモノリスの課題もありました。

そこで我々は2017年から、まず「ストアド剥がし」を始め、AWS環境に新たにAPIを作りました。従来ストアドに載っていた機能をこのAPIに移し、データベースをレプリケーションします。APIを叩くことによって必要な機能を活用するということです。

これによってストアドは減り、スケーラビリティを得ることができました。しかし、まだWebからの入り口がオンプレ環境のため、(スライドを指して)IISを消せなかったり、更新系のリプレイスが未定であったり、次のページで紹介するモノリスの課題がありました。

モノリスとは何かというと、1つのアプリケーションの中にすべての機能を詰め込んだ状態と考えてください。つまり、これらの機能が密に結合しています。その結果、1つの変更の影響範囲が大きいため、例えばリリース時などにチームのコミュニケーションコストが大きかったり、この機能だけをスケールアウトさせたいのにそれができなくて、サーバー全体をスケールアウトさせたりしました。

つまり何が問題だったかというと、密な点です。密です。密です。そう、密は駄目なんです。

そこで、我々はマイクロサービス化します。モノリスなサービスを機能ごとに分けて、サービスとデータベースを1対1で対応させます。つまり、疎結合にしたわけです。

サービスと開発チームが必ず1対1というわけではありませんが、そう捉えてもらうと、メリットがわかりやすいと思います。開発サイクルが早くなり、このアプリだけをスケールアウトさせることが可能になります。サービスごとに最適な言語やフレームワークを選ぶことができ、1つのサービスが落ちたとしても他のサービスは大丈夫なので、対障害性が上がるといえます。

我々は開発スピードを上げ、インフラコストを下げ、そしてVBScriptから脱却して人材を増やすことでZOZOTOWNを成長させようと思い、2020年に1月にマイクロサービス化を開始しました。

第2章:ZOZOTOWNのアーキテクチャの変遷

第2章「アーキテクチャの変遷」です。スライドの図が2019年までです。

我々は2020年にまずAPI Gatewayをリリースします。何が変わったかというと、スマートフォンからのリクエストが必ずこのAPI Gatewayを経由するようになりました。また、このAPIを叩く時は必ずAPI Gatewayを経由するようになっています。

このAPI Gatewayは、URLのパスによって各サービスにルーティングする役割を持ちます。他にもスライドに書いたような機能をGo言語で独自実装しています。

これまで検索機能はSQLサーバーにありましたが、我々は2020年にまず、それをElasticsearchに移した検索APIや、ログイン機能をマイクロサービス化したID認証APIをリリースしています。このAPI Gatewayを用いて、モノリスなものを少しずつマイクロサービス化していくことをストラングラーパターンとも呼びます。

2021年に起きた大きな変化

ここで、GCPについても少し説明します。

我々はML、機械学習系の機能をGCPを使って構築することがあります。レコメンデーションやパーソナライズといった機能は、GCP上にAPIがあります。それを我々のAPI、またはオンプレ環境から直接叩くこともあります。2020年に行ったのはここまでです。

2021年に大きな変化が現れます。それがAggregation API、いわゆるBFFを導入したことです。何が変わったかというと、(スライドを指して)API Gatewayと商品API・検索APIの間に入ってきたわけです。これまでは、ZOZOTOWNのトップページをスマートフォンで表示する時は、必要なAPIを何回も叩きにいっていました。それが、BFFを1回叩くだけでBFFが必要なAPIから情報をまとめて返すようになったわけです。

将来についてもお話しします。我々は今、少しずつオンプレの機能のマイクロサービス化を進めているところです。

また、今日は一切触れていないWebのフロントエンドについてもリプレイス計画が進行し、完全クラウド化を目指しています。

第3章:16歳になったZOZOTOWNの新たな悩み

ここから第3章「16歳の新たな悩み」です。ここまでは主にオンプレの悩みについて話してきましたが、ここからは我々がマイクロサービス基盤と呼んでいるAWS環境の話になります。

その前にまず、この基盤の概要を説明します。我々はシングルクラスター、マルチテナントのKubernetesで全マイクロサービスを管理し、全面CI/CD化と、全面IaC化を達成しています。

では、16歳の悩みとは何か。実は、先ほど見せたこのアーキテクチャはとても簡略化していますが、実際にはもっと複雑です。(スライドを指して)例えば、BFFを経由せずに直接APIを叩くケース以外に、GCPや外部のAPIを叩きにいくケースもあります。そもそもスライドに表記していないマイクロサービスもたくさんあります。実際の通信はとても複雑であることが16歳の新たな悩みです。

具体的にはスライドのとおりです。例えば、リトライやタイムアウトなどを各サービスで実装するのは煩わしい。サービスの依存関係では、どのAPIがどのAPIを叩いているのかがわかりにくい。さらに、1つのAPIが障害を起こすと、それを叩くAPIも障害を起こします。そこで我々はサービスメッシュを導入しました。

サービスメッシュとは、マイクロサービス間の複雑な通信を制御する手法のことです。我々はそれにフレームワークであるIstioを用いています。Istioとは、KubernetesのPodにサイドカーコンテナとしてEnvoyプロキシを注入するものです。(スライドを指して)つまり、各マイクロサービスに、レイヤーを1つ増やしてプロキシ層を入れます。

プロキシはIstioのコントロールプレーンから中央集権的に管理します。それによって出現するのが、「Istioの機能」に記載されているものです。これらの機能をマイクロサービスごとに実装するのは特に大変ですが、Istioを使うことでサービスのコードを変更することなく実現できます。

我々はまだBFFの周りにサービスメッシュを入れている段階ですが、今はまさに全マイクロサービスにそれを埋め込もう、さらに高度な機能を使っていこうというフェーズです。

まとめと質疑応答

本日のまとめです。ZOZOTOWNは昔からストアドとモノリスに悩まされてきましたが、それらをマイクロサービス化して解決しようとし、その手法としてストラングラーパターンとBFFを用いています。16歳になってサービス間の通信が複雑になりましたが、それをサービスメッシュIstioで解決しようとしています。私の発表は以上です。

ここから質疑応答に移りたいと思います。まず1つ目、「マイクロサービスごとにSREがいますか?それとも全体を1つのチームで見ていますか?また、SREとバックエンドの仕事の分担はどうしていますか?」という質問をもらっています。

現状は、マイクロサービスごとにSREはいません。マイクロサービス基盤全体を見るSREチームが1つあり、それが私どものチームです。今は10人で新規案件から保守までやっています。

さらに、バックエンドとの仕事分担についてすごくざっくりいうと、コンテナイメージを作るところまでがバックエンドの仕事、そのイメージをAWS環境で動かすのがSREの仕事です。例えば、KubernetesのマニフェストはSREが書き、CI/CDもSREが構築します。一方で、Datadogのライブラリをコードに埋め込むような作業はバックエンドが担当しています。

ただ、明確な区分けはしていません。Kubernetesのマニフェストで環境変数を追加したり、CI/CDを変更したりするPull Requestはよくバックエンドが作ってくれるなど、かなり柔軟にやっています。会社全体でもかなり柔軟に組織体制が変わるので、今の分担も今後柔軟に変わっていく可能性が高いと思っています。

次の質問に移ります。「Istioを選んだ理由はなんですか?」。AWSでは、Istioの他にApp Meshという選択肢もありました。ただ、先ほど紹介したとおり、弊社はGKEも利用しているので、GKE側の運用チームとの技術共有を考慮し、OSSであるIstioを選びました。OSSの中ではIstioがデファクトスタンダードであるという認識でした。実際に、比較的長い時間をかけて調査や検証を行ったところ、Istioでやりたいことが実現できると確認できたので、他のOSSについてはあまり検討しませんでした。

引き続き、「モノリスのどこからマイクロサービスとして切り出すか、どのような考え・観点に基づいて決めたのでしょうか。また、あらためて今からマイクロサービス化できるとしたら、どこから切り出そうと思いますか?」という質問をもらっています。

これは、私たちもけっこう難しかったです。我々はリプレイスを担当しますが、それとは別に会社として、またZOZOTOWNのプロダクトとして実際に行いたい案件などがあります。

そこをまず複合的に、エンジニアとしてやりたいことと、ビジネス的にやりたいことの都合をつける必要があると思っています。しかし、柔軟に変わっていく中で、まだ模索している段階です。先ほど紹介したとおり、弊社では最初に参照系、更新しないところをできる限り進めていくという順番で行っていました。

あらためて今からやろうとしたら、やはりデータベースをSQLサーバーからAuroraに移すことが一番難しいことの1つなので、できる限りデータベースをアプリケーションと1対1に対応させられるところは、選択肢としてけっこういいのではないかと思っています。

引き続き「データベースもリプレイスしていますか?リプレイスしている場合はデータベースは何を利用していますか?」という質問をもらっています。先ほど言ったとおり、主にAuroraを利用しています。会社全体の方針として、クラウドのマネージドなDBを使っています。

ただ、まだリプレイスしている最中のため、例外もたくさんあります。例えば冒頭で紹介したとおり、先ほどの商品情報APIは、オンプレのSQLサーバーをクラウド側にそのままレプリケーションして、今も存在しています。

最後の質問になるかもしれません。「サービス間でAPIの後方互換性がない変更などが発生した場合に、サービス間の調整コストが高い、などの問題は発生していませんか?」。これはもう発生しています。

例えば、BFFを導入したと紹介しましたが、これはまずiOSアプリがバージョンアップして、そこから後方互換性がなくなって導入というかたちです。しかし、当然まだ古いバージョンのアプリからリクエストが来るので残しておく必要があります。いずれはいわゆる強制アップデートをお願いするかたちになりますが、回避できていない課題だと感じています。質問は以上です。