クラウドロックインされないアーキテクチャ「Cloud Agnostic Architecture」のすすめ

この記事は[フューチャー Advent Calendar 2023の20日目](https://qiita.com/advent-calendar/2023/future)の記事です。

## はじめに

先日ガートナーのレポートで「特定のクラウドベンダにシステムを集中させるリスクの重要度が多くの企業で上昇している」との発表がありました。

https://www.gartner.com/en/newsroom/press-releases/2023-10-30-gartner-says-cloud-concentration-now-a-significant-emerging-risk-for-many-organizations

日本においてクラウドの活用はますます進んでいますが、特定の Cloud Service Provider（CSP）にロックインされるリスクについては、まだまだ議論の余地があると考えています。
本記事では、特定のクラウドに依存しないアーキテクチャについて「Cloud Agnostic Architecture」という言葉を用いて整理していきます。

## Cloud Agnostic Architecture とは

Cloud Agnostic[^1] Architectureとは「特定のクラウドに依存しないアーキテクチャ」を意味します。これはクラウドプラットフォーム自体を利用しないという意味ではなく、複数のクラウドプラットフォーム間（ないしはオンプレミスとクラウドのハイブリッドモデル間）で、アプリケーション、ツール、サービスを含むワークロードをシームレスに移植できるように設計することを意味しています。

このアーキテクチャには次のようなメリットがあります。

* **クラウドロックイン[^2]の回避**
何かしらの事情により今利用しているクラウドプラットフォームから他のクラウドプラットフォームへ移行しなければならない（もしくは移行することでコスト面などの恩恵を受けられる）状況が発生した場合に、コストや時間をかけずに移行することが可能となります。

* **より広範なロケーションへのシステム展開**
複数のクラウドプラットフォームを利用することでより多くのロケーション（リージョン）にシステムを展開することができるだけではなく、各ロケーションに適したクラウドプラットフォームを選択できるようになります。
これは例えば、グローバルにシステムを展開するようなケースおいて、通常は AWS を利用するが、中国におけるシステム展開においては、中国の CSP（Alibaba CloudやTencent Cloud）を利用することで、法制度的なリスクを最小化するといったことが考えられます。

* **マルチクラウド構成の容易な実現**
DR 対策として複数のクラウドプラットフォーム上にシステムを展開しておくなど、冗長デプロイが必要なマルチクラウド構成をとることが容易になります。

## Cloud Agnostic Architecture を実現するためのアプローチ

この章では Cloud Agnostic Architecture を実現するためのいくつかのアプローチを紹介します。

### OSS技術の採用

CSPプロプライエタリなマネージドサービスを利用するのではなく、マネージドなオープンソースサービス（ないしはOSS互換性のあるサービス）を利用や、真に必要な場合はOSSのセルフホスティングを行います。

AWS を例に OSS / OSS互換のサービスとプロプライエタリなサービスの一例をみてみると、選択肢がいくつかあることがわかるでしょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42275/95265654-e5bc-9368-cb03-8f3b93f0bec4.png)

主要な OSS / OSS互換のサービスは、基本的にそれ自体が業界標準的な技術仕様に準拠する形で設計されており、メジャーなものは多くのクラウドプラットフォームにてマネージドサービスとして提供されているため（もしくは提供されていない場合でも、IaaSとしてのコンピューティングサービス上にホスティングすることで、クラウドプラットフォームに依存せず利用できるため）、積極的に利用することでクラウドの移植性を高めることができます。

### コンテナ技術の採用

Dockerに代表されるコンテナ型の仮想化技術によりホスト環境とアプリケーション環境を分離することで、アプリケーションのポータビリティが向上し、別のクラウドプラットフォームにアプリケーションを移行しやすくなります。

### 独立性のある DevOps の実践

特定のクラウドに依存しない DepOps のツールやサービスを活用し、ワークフローを自動化することで、別のクラウドプラットフォームへのスイッチングコストを低くすることができます。具体的にどのようなものなのか、いくつか例を紹介しましょう。

#### Infrastructure as Code

CSP プロプライエタリなサービス（例. AWSであれば[Amazon CloudFormation](https://aws.amazon.com/jp/cloudformation/)
や[AWS CDK](https://aws.amazon.com/jp/cdk/), GCPであれば[Cloud Deployment Manager](https://cloud.google.com/deployment-manager/docs)）ではなく、 [Terraform](https://www.terraform.io/) や [Crossplane](https://www.crossplane.io/) に代表される複数のクラウドに対応したOSSのツールを活用することで、特定のクラウドに依存しない IaC を実現することができます。

#### Observability

可観測性（Observability）を実現するためのツールやサービスは数多くありますが、複数のクラウドに対応したものを採用し、一元的なモニタリングを行うことで、特定のクラウドに依存しない独立性の高い Observability 基盤を実現することができます。

CNCFのCloud Native Landscapeを見てみても様々なツールやサービスがありますが、OSSを活用する一例としては、データ可視化に[Grafana](https://grafana.com/grafana/)、メトリクス監視に[Prometeus](https://prometheus.io/)、ログ監視に[Grafana Loki](https://grafana.com/products/cloud/logs/)、トレース監視に[Grafana Tempo](https://grafana.com/products/cloud/traces/)を採用する（あるいはこれらをマネージドサービスとして提供する[Grafana Cloud](https://grafana.com/products/cloud/)を利用する）といった形が考えられます。

あるいは [New Relic](https://newrelic.com/) や [DataDog](https://www.datadoghq.com/) といったSaaSを利用することも有効です。もちろんこれらのサービスはマルチクラウドに対応しています。

1点補足をしておくと、CSPプロプライエタリなモニタリングサービスでしか直接メトリクスを取得できないものがある（例. Amazon Aurora や AWS Lambda のメトリクスは Amazon CloudWatchでしか取得できない ）ため、CSPプロプライエタリなモニタリングツール（例. AWS であればAmazon CloudWatch）を完全に利用しないというケースはあまり考えられません。Amazon CloudWatch が提供するデータを Prometheus に連携するといったように、独立したObservability 基盤に一元化していくアプローチになります。

#### CI/CD

CI/CDについても他と同様、CSPプロプライエタリなサービスではなく、特定のクラウドに依存しないツールやサービスを活用してパイプラインを構築することで、クラウドプラットフォームの移植性が高くなります。
この領域においては、既に GitHub や Circle CI といった特定のクラウドに依存しないツールやサービスが広く使われており、AWSのCode Family[^3]のようなCSPプロプライエタリなサービスが活用される事例はそこまで多くないように見受けられます。

### 適切な抽象化

アプリケーションのレイヤにおいて、適切に抽象化されたインターフェースを用いてCSPの提供するサービスとやりとりを行うことで、コアとなるビジネスロジックが特定のCSPに依存しない疎結合なつくりが実現できます。これにより、別のクラウドプラットフォームのサービスに切り替えを行う（例. Amazon S3ではなくGCSを使用する）場合でも、既存のソースコードへの影響を最小限に抑えることが可能となります。
クリーンアーキテクチャやリポジトリパターンなどを実践して自身でインターフェースを定義するのも良いですし、[GoCDK](https://gocloud.dev/) や [Apache jclouds](https://jclouds.apache.org/) のような各クラウドサービスやOSSプロダクトへの透過的なインタフェースを提供するライブラリを活用する方法もあります。

## トレードオフを理解する

Cloud Agnostic Architecture はそれ自体が銀の弾丸ではないため、トレードオフを理解した上で採用することが重要となります。
先述したように Cloud Agnostic Architecture を採用することで、クラウドの移植性が向上します。一方で、クラウド非依存を目指すということは、同時に「クラウドのネイティブ機能を最大限活用しない」という判断を（多かれ少なかれ）していることでもあり、常にクラウドプラットフォーム間の差異を抽象化することを意識する必要があります。そのため、時には複雑性が増し、プロダクトを市場に投入するまでの時間が大きくなる可能性もあります。

CSPプロプライエタリなサービスのメリットの1つとして「サービス間のシームレスな連携」が挙げられますが、ここでは具体的な例として、オブジェクトストレージへの操作をトリガーとして、非同期処理を実行するケースを考えてみましょう。

AWSネイティブなサービス/機能を採用する場合、S3 のイベント通知を利用して、Lambda 関数を実行するアーキテクチャが考えられます。
S3のイベント通知は [At Least Once の到達が保証](https://docs.aws.amazon.com/AmazonS3/latest/userguide/EventNotifications.html)されてますが、イベントはS3内部でコントロールされるため、オブジェクト操作側の処理でイベントの作成を意識することはありません。また、非同期で呼び出される処理についても、Lambdaの機能として起動トリガーやリトライ回数、DLQの送信先などの設定ができるため、開発者はコアとなる処理のみに集中することができます。
このようにアプリケーションコードを必要最小限に保ちながら簡単に連携を実現できる点が、このアーキテクチャの1つのメリットだと言えます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42275/598c83a1-f884-40d9-be7a-67d2915d1ffa.png)

一方で、このワークロードを別のクラウドプラットフォームに移植しようとした場合、それは簡単でしょうか。オブジェクトストレージのイベントをトリガーとして処理を実行する機構は移行対象のクラウドプラットフォームに備わっているのでしょうか。備わっていたとして管理対象となっているイベントは充足している[^4]のでしょうか。
さらに言えば、非同期で呼び出される処理においては、少なくともイベントをハンドリングする部分の処理はクラウド依存しているため、ソースコードの修正/追加が必要となります。
このようにクラウドの移植時に困難が生じ得る、そのための変更に時間がかかるというのがこのアーキテクチャのデメリットでもあります。

次にこれを Cloud Agnostic Architecture で実現する例を見てみます。
AWSネイティブなS3のイベント機構は利用せず、代わりにマネージド Kafka を使用してイベントメッセージの管理を行います。またコンピューティンレイヤも コンテナベースのアーキテクチャを採用します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42275/3303f7d4-ca83-e76b-80a8-8953c36ad76a.png)

これによりAWSプロプライエタリなサービスに依存する部分が小さくなり、代わりにクラウドの移植性が高まります。
ただし、このようなアーキテクチャを採用することで、イベントメッセージの到達保証やエラー時のハンドリングなど、CSPに任せていた部分を自分自身で設計・実装する必要がでてくるかもしれません。また、S3イベント通知と同等の可用性や性能を担保するためには、時には追加のコストが必要になるかもしれません。

このようにそれぞれのアーキテクチャは一長一短であり、トレードオフを理解することが重要です。

## クラウド依存する or 依存しないの2択ではない

ロックイン自体が「ロックインする or しない」の2値で語られるものではないのと同様、Cloud Agnostic Architecture は 特定のクラウドに「依存する or 依存しない」の2択ではなく「どの程度クラウド間の移植性を高めるか」の度合いで、評価されるべきものです。

例えば、コスト面の観点からAWS Lambda を採用するが イベントをハンドリングする部分はコアロジックと分離し疎結合な作りにした上で、イベントソースは原則 API Gateway に限定することで、無尽蔵に依存度が高まらないようにするなどといったように、トレードオフの世界で最適な解を見つけることになります。

何が最適かというのは、対象となるシステムが置かれている状況に応じてさまざまです。
例えば、市場までの投入時間が重要な要件であるスタートアップにおいては、クラウドの移植性を犠牲にしてでも、CSPプロプライエタリなサービスを積極的に利用する方が良いかもしれません。逆に特定のCSPに依存することが大きなリスクとなり得るクリティカルなシステムや、グローバル展開に伴いマルチクラウド対応が前提となるシステムにおいては、クラウドの移植性が重要な要件になることでしょう。

このように唯一の正解はありませんが、1つだけ不正解と言える選択は存在します。
それは、ロックインのリスクを適切に評価せず、システム全体としてのポリシーをろくに定めないまま、個別最適を追求してCSPプロプライエタリなサービスを無闇やたらに採用することです。

適切にリスクアセスメントを行った上で、指針を定めることが重要となります。

## ロックインは完全に回避できない

最後に Cloud Agnostic Architecture を採用したからとしても システムにおけるロックインは完全に回避できるものではない点を補足しておきます。
システムにおけるロックインは、本記事で取り上げた CSP ロックインだけでなく、プロダクトロックインやバージョンロックイン、スキルロックインなどさまざまな次元に分類[^]することができます。

例えば、CSP ロックインを回避するために、OSS互換のサービスを積極的に採用したとしてもプロダクトロックインを回避できているわけではありません。
RDB の世界では ANSI SQL 標準に準拠することで、DBプロダクトの移植性を高めるといった工夫が考えられますが、各ロックインの次元において、ロックインされることによるリスクを適切に評価した上で、どこまで対応するかの判断を行うことが求められます。

## 参考資料

* [Don't get locked up into avoiding lock-in](https://martinfowler.com/articles/oss-lockin.html)
* [Modern cloud applications: Do they lock you in?](https://d1.awsstatic.com/events/Summits/reinvent2022/ARC207_Modern-cloud-applications-Do-they-lock-you-in.pdf)
* [開発におけるロックインのリスク評価と考え方](https://pages.awscloud.com/rs/112-TZM-766/images/F-3.pdf)
* [ベンダーロックインを解きほぐしていくために](https://d2908q01vomqb2.cloudfront.net/b3f0c7f6bb763af1be91d9e74eabfeb199dc1f1f/2022/01/01/unpicking-vendor-lock-in_JP_v5_asof20220101.pdf)

[^1]: Agnosticとは直訳すると「不可知論者」ですが “単語 + agnostic” で「～（単語）に依存しない」という意味になります。  

[^2]: クラウドロックインとは特定のクラウドプラットフォームに過度に依存することで、別のクラウドプラットフォームへの移行が困難になってしまう（=スイッチングコストが高い）状態のことを指します。

[^3]: [Code Family](https://catalog.us-east-1.prod.workshops.aws/workshops/752fd04a-f7c3-49a0-a9a0-c9b5ed40061b/en-US) とは AWS CodeCommit, AWS CodeArtifact, AWS CodeBuild, AWS CodeDeploy, AWS CodePipelineを指します。

[^4]: 例えば [AWS S3](https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/userguide/notification-how-to-event-types-and-destinations.html#supported-notification-event-types) と [Google Cloud Storage](https://cloud.google.com/functions/docs/calling/storage) は両方ともイベントトリガーの機構を持ちますが、イベントタイプには差異があります。

[^5]: [Don't get locked up into avoiding lock-in](https://martinfowler.com/articles/oss-lockin.html) ではロックインは合計8つの次元で分類されています。