書き込みがあるワークロードにおける ZOZOTOWN マルチクラウド構想とその検討停止について

この記事は[ZOZOテクノロジーズ #1 Advent Calendar 2019](https://qiita.com/advent-calendar/2019/zozo_tech) 23日目の記事です。
昨日の記事は弊チームの [inductor](https://qiita.com/inductor) による「[GKEの内部負荷分散機能を使ってInternal Load Balancerを構築する](https://qiita.com/inductor/items/c5bf93bc9d9c4081a1fc)」でした。面倒で困っているのでGCP様にはなんとかして欲しいものです :pray: 

さて本記事では、残念ながら本番運用には至らなかったのですが、私がここ暫く[MLOps業](https://medium.com/@sonots/mlops%E3%83%81%E3%83%BC%E3%83%A0%E3%81%8C%E3%81%A7%E3%81%8D%E3%81%BE%E3%81%97%E3%81%9F-daad623e58ce)の裏でやっていた「書き込みがあるワークロードにおける ZOZOTOWN マルチクラウド構想」の検討結果について供養のつもりで記そうと思います。

なお、今年は弊社では全部で5つのAdvent Calendarが公開されています。

[ZOZOテクノロジーズ #1 Advent Calendar 2019](https://qiita.com/advent-calendar/2019/zozo_tech)
[ZOZOテクノロジーズ #2 Advent Calendar 2019](https://qiita.com/advent-calendar/2019/zozo_tech2)
[ZOZOテクノロジーズ #3 Advent Calendar 2019](https://qiita.com/advent-calendar/2019/zozo_tech3)
[ZOZOテクノロジーズ #4 Advent Calendar 2019](https://qiita.com/advent-calendar/2019/zozo_tech4)
[ZOZOテクノロジーズ #5 Advent Calendar 2019](https://qiita.com/advent-calendar/2019/zozo_tech5)

宜しければご覧ください。

# TL;DR

* ZOZOTOWNではマルチクラウドアーキテクチャ(*1)をすすめている。 Ref: [CNDT2019 ZOZOTOWN CloudNative Journey](https://docs.google.com/presentation/d/1XehkTtJowHQTSEQxXdUvVjYpL2h25eHTObGvm28AnSY/edit#slide=id.g5de42805e8_0_219)
* 今までは参照のみだったが、今回書き込みがあるワークロードでマルチクラウド設計をしてみた
* 良いDBaaS がなかったので辞めた。今後に期待。

(*1) ここで言っているマルチクラウドは、機能ごとに別のクラウドを使って組み合わせるハイブリットクラウドではなく、可用性向上を目的に同じ機能を複数のクラウドで動かすアーキテクチャのことを指す。

# 背景およびマルチクラウド設計の動機

ZOZOTOWNではマルチクラウド設計を進めており、実際にいくつかのシステムはすでにマルチクラウドで稼働している。

マルチクラウド設計を狙う動機としては、2019年上期にクラウドベンダXXXXにおいて全リージョンでの障害が発生したことが１つの大きな理由としてあげられる。ZOZOTOWNが数時間止まると損失規模が大きいため、自分たちでコントロールできる技術の力でそのような事象をカバーしようと思った時に、マルチクラウドアーキテクチャ構想が立ち上がった。

現況については、Cloud Native Days Tokyo 2019 で弊社の岡が発表したスライド ([CNDT2019 ZOZOTOWN CloudNative Journey](https://docs.google.com/presentation/d/1XehkTtJowHQTSEQxXdUvVjYpL2h25eHTObGvm28AnSY/edit#slide=id.g5de42805e8_0_219)) があるのでそちらを引用する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/9641/2b725731-43d4-3175-36a1-89f444f487e2.png)

現在稼働しているこのシステムは、書き込みを行わない参照系のシステムであり、今回初めて書き込みを伴うワークロードでどのようにマルチクラウドアーキテクチャを実現できるか検討した。（この段階で私も検討に加わった)

# マルチクラウド設計の方針

*大方針: 「実装も運用も最小コストで。マネージドサービスの利用が前提」*

### クラウド依存の実装をアプリケーションに入れない

マルチクラウドで動かすからと言って、アプリケーションにクラウドごとの分岐処理を入れて、クラウドベンダの差異を吸収するような実装は入れない。

例えば GCP では Spanner を使い、AWS では DynamoDB を使うような設計は避ける。同じアプリケーションコードが複数クラウドで動くように、オープンな仕様もしくは実装が提供されているミドルウェアのみを使う。例えば MySQL など。

また、アプリケーションを動かす環境も、Google App Engine (GAE) や AWS Lambda のようにクラウドに依存する環境は使わずにオープンな仕様の環境を使う。例えば Kubernetes など。

### マネージドサービスを使う

自分たちでOSSなミドルウェアをIaaS上にセットアップすれば、AWSでもGCPでもAzureでも動くような環境を作ることはできるだろうが、運用が大変になるのでやりたくない。

SaaS (DBaaS) の利用を視野に入れ、マネージドサービスの利用を前提に設計する。

# 書き込みがあるワークロードにおけるマルチクラウド構想

## マルチクラウド/マルチライト構想

可能であれば理想となるアーキテクチャ案。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/9641/bdd36b26-7242-c98b-2dbd-b6785de01a68.png)

Fastly は例だが、複数クラウドに振り分けるロードバランサが何かしら必要。もしもFastly(例)が落ちた場合は、一時的にDNS切り替えで直接AWS(例)のロードバランサにユーザリクエストが飛ぶようにすることで全サービス断を回避する。

アプリケーションを k8s で動くように実装し、それぞれのクラウドベンダの k8s マネージドサービスで動かす。絵には Azure がないが、Azure にも Azure Kubernetes Service (AKS) があるため Azure でも可能。

DBaaS のクラウド環境とは VPC Peering を貼ることでレイテンシを除去。問題はマルチクラウド・マルチライト、VPC Peering に対応している DB が果たして世の中にあるのかどうかという点。

## シングルライト・マルチクラウド/マルチリード構想(妥協案)

軽く調べた時点で、マルチクラウド/マルチライトなDBの存在が疑わしかったので、現実的な路線として、書き込みはシングルクラウドに対してだけ行い、読み込みはマルチクラウドで負荷分散できるようなアーキテクチャ案を考案した。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/9641/d2cce8d9-127c-3dbe-4aa0-564b54e032f6.png)

Fastly(例)のレイヤーで、書き込みリクエストをAWS(例)だけに振り、読み込みリクエストはマルチクラウドに分散させる。

オンプレを介した専用線経由でレプリケーションする。もしくは、DBaaSの専用機能を使う。

マスター側のDBが落ちた場合にインタークラウドフェイルオーバーしたいが、現実的な路線として、できなくても許容する。マスターDB側のクラウドが落ちた場合は、読み込みのみに機能縮退する。

# 要件を満たす DBaaS サービスの検討

構想通りのシステムを作れるのか、以下のように要件を定義して、それを満たしている DBaaS があるか調査したのでまとめる。

| 要件 |
|:--|
| 最新バージョンが使える |
| 東京リージョンがある |
| AWS, GCP, Azure にDBインスタンスがデプロイされる |
| こちらの AWS, GCP, Azure 環境と DB 間で VPC Peering が貼れる(もしくはその他の手段でネットワークが専用線並) |
| インタークラウドレプリケーションが可能 |
| ↑が可能な場合ネットワークが専用線並 |
| インタークラウドフェイルオーバーが可能 |

## MongoDB (Atlas)

https://www.mongodb.com/cloud/atlas

MongoDB開発元が提供しているSaaS。複数のクラウドベンダに対応している。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/9641/fc89bd9d-6e6b-4ccd-4882-94837ee7b348.png)

しかし、インタークラウドレプリケーションには対応していなかった。

## CockroachDB

https://www.cockroachlabs.com/

Google Spanner を元にした設計の DB を OSS として作成し、さらに DBaaS 化しようとしているもの。元 Google 社員が開発。

インスタンス自体は主要クラウドベンダのどこかのインスタンスで稼働し、ゴキブリ並みの可用性を持たせることをゴールとしている。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/9641/fd6938b9-5d98-4241-6cbf-d2bef1a278a0.png)

設計思想としては我々のマルチクラウド戦略に一番マッチしていると思うが、如何せん発展途上すぎるという印象を持った。

* まだまだ発展途上で実用段階ではなさそう
* 他社事例もほぼない。日本では一切ない(あったら教えてください)
* DBインスタンスへの接続もインターネット越し

1年後だったら可能性があったかもしれないが、今採用するのは難しいという印象を持った。

## Cassandra (DataStax)

https://www.datastax.com/services/datastax-managed-services

Cassandra は書き込み分散ができるカラムナーデータベース。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/9641/83742a3e-935d-dee3-f6b4-710da65c3283.png)


しかし、 ~~GCP はまだサポートしておらず~~ (現在はサポートしていました!)、当然のようにインタークラウドレプリはできなかった。

## Elasticsearch (ElasticCloud)

https://www.elastic.co/jp/products/elasticsearch/service

検索エンジンなので用途が違う。

## PostgreSQL (ElephantSQL)

https://www.elephantsql.com/

PostgreSQLのSaaS。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/9641/b1dde52a-a830-417d-28e7-508690e2d8fc.png)

インタークラウドレプリケーション、インタークラウドフェイルオーバーサポートしているらしい。PostgreSQL自体がシングルマスターのDBなのでマルチライトは当然のごとくできない。

PostgreSQLであれば Amazon RDS、Cloud SQL などでもサポートされているので選択するかは悩ましいところ。

## MySQL+Vitess (PlanetScale)

https://planetscale.com/

Vitess 運用で有名な Youtube 出身のエンジニアが作った DBaaS とのこと。Vitess を使うとMySQLマスターの書き込みも分散もされる。

時期的に、最近やっとリリースをしたばかりで、東京リージョンのサポートもなく、現状で採用できるものではなかった。

## Kafka (Confluent)

https://www.confluent.io/

用途が違うが、メッセージキューをマルチクラウドで使いたくなった場合、Kafka 開発元の Confluent が提供している SaaS を利用できる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/9641/0eba4ed1-0a56-47f0-3985-1a9e959e8e06.png)

## Amazon Aurora -> CloudSQL への MySQLレプリケーション

こちらは単独の DBaaS サービスではないが、AWS と GCP それぞれのマネージドサービスを使って要件を満たせるのかも調査した。

調査結果については弊チームの hkame が記述したこちらの記事を参照 > [Aurora → CloudSQLへMySQLレプリケーションはできるのか](https://qiita.com/hkame/items/9cff6117bc1763ac7810)

Cloud SQL でマスターを指定する時に、FQDN ではなく IPv4 しか指定できないため、Aurora でフェイルオーバーが走った場合に、IPアドレスが変わってレプリが止まってしまいダメだったという結果となった。自動で付け替えるような作り込みをしないといけなそう。

## DBaaS 検討まとめ

採用候補となるのは、シングルライト・マルチクラウド/マルチリード構想(妥協案)向けとなるが、 PostgreSQL (ElephantSQL) ぐらいという調査結果となった。

# 要件を満たすインタークラウドロードバランサーの検討

こちらの検討では、クラウドの前段で、クラウドへのアクセスを振り分けるサービスの調査を行った。

## Fastly

Fastlyならば、VCLを自分で書いて挙動をコントロールできるのでかなり自由度が高い。CDNではなく高機能ロードバランサーとしての利用。

https://www.fastly.com/

シングルライト・マルチクラウド/マルチライト構想の振り分けも当然のように可能であり、要件を満たしてくれた。

Fastlyが落ちた場合は、前述したようにDNS切り替えでAWS(例)のロードバランサーに直接リクエストが飛ぶようにすることで、全サービス断を回避することができるだろう。

## Avi Networks

[VMwareがマルチクラウドロードバランシングのAvi Networksを買収](https://jp.techcrunch.com/2019/06/14/2019-06-13-vmware-announces-intent-to-buy-avi-networks-startup-that-raised-115m/) という記事が流れてきたので、VMware さんに弊社に来ていただき話を聞いた。

Avi Networks の場合は、我々の IaaS 環境に Avi Networks のロードバランサをデプロイすることになり、マネージドサービスとは言い難い。またコア数に応じてライセンス料金がかかるので、セール時のみパフォーマンスをあげようと思っても年間ライセンス購入(月間や、まして秒間ライセンスはない)からやらなければならない。

シングルライト・マルチクラウド/マルチライト構想のロードバランンシングは、次のような戦略を取ることで可能であるとのことだった。

* 読み込みリクエストの場合: DNSラウンドロビンでどちらかのクラウドに振り分ける
* 書き込みリクエストの場合: DNSラウンドロビンで一旦どちらかのクラウドに振り分ける。GCP(仮)に書き込みリクエストが来た場合は、AWS(仮)にプロキシーしてリクエストし、レスポンスを返す。

## インタークラウドロードバランサー検討まとめ

やろうと思えば、Fastly、Avi Networks いずれでも実現できるという結果となった。私個人としては Fastly の方が柔軟性が高く、我々の IaaS にデプロイして自前で管理する必要がないため、軍配があがると感じた。

# 方針転換、そして検討停止

以上のように設計を進めていたのだが、 深遠な理由により最初のターゲットとしていたマイクロサービスAPIの特性が **ほとんど書き込みのみ** のワークロードに変更となった。

この時点で、読み込みのみ分散できる **シングルライト・マルチクラウド/マルチリード構想** の設計は意味をなさなくなり、またマルチクラウド/マルチライトをサポートしているDBが存在しないため、検討を停止することに決定し合意を得た。

今後、プロダクションレディなマルチクラウド/マルチライトな DBaaS サービスが発表されたら、マルチクラウド構成を再度考慮できる可能性は出てくる。[CockroachDB](https://www.cockroachlabs.com) には期待している。

# マルチクラウド設計をしたことで得た知見

最後に、マルチクラウド設計をしたことで得た個人の感想を記して供養とする。

### :x: マルチクラウドにしたからと言って可用性が上がると言い切るのは難しい

設計難易度と複雑性が跳ね上がるので、マルチクラウド化によってむしろ耐障害性が落ちるとすら感じた。

まずはシングルクラウドシングルリージョンで、アプリケーションの Reliability を向上することに時間を費やして、クラウドベンダのカタログスペック通りの 99.99% の可用性を担保できるようになってから、マルチクラウドに移行してさらに耐障害性を上げる、というアプローチを取るのがよさそうという感想を得た。

### :x: 設計コストは3〜4倍

クラウド x 2 + クラウド間の繋ぎこみ + SaaSの検討で、3〜4倍になったと感じた。

### :question: 運用コストはXXX倍

今回は運用にまで至らなかったのでこの知見は得られなかった。

シンプルに考えると設計コストと同じく3〜4倍になると想像できるため、この運用コストを1倍程度に抑えるための設計(難易度が高い)と自動化が重要になってくるだろう。運用自動化するということは、自動化のための作り込みにコストを支払うということであり、また学習コストは依然として3〜4倍支払う必要があるため、恐らく頑張って作り込みをしたとしても1.5倍〜2倍程度までにしか抑えることはできないのではいかと想像している。

### :x: アジリティ(機敏性)への悪影響

例えば、Job Queue を使いたい、オンメモリDBを使いたい、となった時に、マルチクラウドでどう実現するかを考えなければならず、準備ができるまで時間がかかると感じた。

特に新しいSaaSを使うとなった場合に、SaaSとの契約からやらなければならないため、エンジニアリング外の調整に時間がかかり、機敏性が損なわれた。

機敏性が損なわれることにより、ビジネス上の時機を逃して、売上を損なう危険性があると感じた。インフラのせいで売上を逃したと評価されるのは避けたい。

### :o: ベンダーロックインの排除、開発環境が用意しやすい

マルチクラウド設計の大方針として、アプリケーションの実装をクラウドごとに変更しないですむようにオープンな仕様または実装のあるミドルウェアのみを使うとしていた。

そのおかげで、ベンダーロックインが排除できたのに加え、ローカルのマシンにOSSだけで完全な開発環境を構築できるという恩恵があった。

# おわりに

これからマルチクラウドアーキテクチャにチャレンジする方には、

> 設計難易度と複雑性が跳ね上がるので、マルチクラウド化によってむしろ耐障害性が落ちるとすら感じた。

この点を考慮してチャレンジすべしとアドバイスさせて頂く。