[レポート] モダンなクラウドアプリケーションのロックイン問題について考える #ARC207 #reinvent

2023.05.07

アノテーション テクニカルサポートの川崎です。

本記事は AWS re:Invent 2022 のセッションレポートとなります。

概要

クラウド上での構築は素晴らしいですね。フルマネージドなサービス、オンデマンドでのスケーリング、細かなアクセス制御がすぐに利用できます。サーバーレスのエコシステム上でアプリケーションを開発すれば、クラウドが基盤となるインフラのデプロイや管理まで面倒を見てくれます。しかし、クラウドにより多くのことを任せることで、自分たちがロックインされてしまうのでしょうか?もし、ある日アプリケーションを別の場所に移さなければならなくなったらどうなるのでしょうか? このセッションでは、モダンなクラウドアプリケーションにおけるトレードオフを議論し、なぜ「ロックイン」が利用しているサービスの結果だけでないのかを説明し、最適な抽象化レイヤーがあなたの頭の中にある理由を示します。

セッション動画

セッション資料

Modern cloud applications: Do they lock you in?

セッション情報

ARC207

はじめに

このセッションでは、最新のクラウドアプリが優れている理由や、その使用や構築を行う際に切り替えが難しくなるかどうかについて説明していきます。 私は Gregor といいます。 日中の私の仕事は、エンタープライズ ストラテジストです。 つまり、お客様とクラウドへの移行やIT変革に協力しています。 そして、夜はほとんどの時間をアプリケーションの構築に費やしており、正直なところ、サーバーレス製品をいじっています。 特にサーバーレス製品の統合に注力しています。 私は、非同期システムの統合と構築に長い間携わってきました。 そのため、それがアプリケーションを構築するための優れた方法であると理解しています。 さて、このような二重生活は興味深い洞察につながります。 一方で、私は組織の非常に様々なレベルで会話をするようになり、様々な層が様々な種類の懸念を持っていることを見てきました。 しかし、意思決定者がエンジンルームから切り離され、最適ではない決定につながることも時々見られます。 したがって、ロックインの管理やスイッチングコストの管理、最新のサーバーレス・クラウドアプリケーションの構築など、 高レベルの戦略を関連付けることは、非常に価値のあることです。 それでは、モダンなクラウドアプリとはどういう意味なのか、定義から始めましょう。

モダンは単純にランタイムだけのことではありません

モダンなランタイムに関する話題では、右に行くほど、クールでモダンな感じが増すとされています。 VM から始めてコンテナに入り、最終的にはサーバーレスに到達します。 それは良いことですが、全体像のごく一部にすぎないと思います。 アプリケーションを観察する時、それがどこで実行されているかを見ることはありません。 また、すべてを手作業で行っているのか、それとも自動化しているのかを知りたいです。 CI/CD の継続的インテグレーションを使用していますか、それともダクトテープとストリングワイヤのような方法を使っているのかなどが気になります。 また、オブザーバビリティやマネージドサービスの使用も重要です。 最新のサービスを使用する必要があり、きめ細かいものを構築する場合は、そのようなシステムの管理やオブザーバビリティへの注意が必要で、 さらに質問のリストが続きます。 サーバーレスのモノリスを構築しているのではないか、そしてそれが一番右にあるのかどうかなどです。 COBOL で書かれたものがあるかもしれませんが、最新のアプリケーションを使っているとは言い難いです。 したがって、モダンアプリケーションとはランタイムだけでなく、言語、アーキテクチャ、作業方法、クラウドで動作しているか、自動化の使用、マネージドサービスの使用など、これらすべての総計を意味すると考えます。 これを理解することが重要です。

サーバーレス - 単なるランタイムではありません

サーバーレスは AWS の Lambda や Fargate だけではなく、非同期性やイベント駆動型アーキテクチャ、 EventBridge、Step Functions、SQL、SNS、DynamoDB などを含んだアプリケーション構築方法です。 アーキテクトの視点から見れば、柔軟性を犠牲にしてでも、サーバーレスエコシステム上でクラウドネイティブな方法でアプリケーションを構築することが望まれます。 しかし、進化可能性と進化可能なアーキテクチャが求められる場合もあります。 つまり、サーバーレスは単なるランタイムではなく、アプリケーションを構築する多様な方法を提供しています。 アプリケーションは自由に変更可能であり、さまざまな方法で進化が可能です。 ですので、アーキテクトとしては多次元的にサーバーレスを捉え、適切なアプリケーション構築方法を選択することが重要です。

一次元ビュー

一次元ビューでは、左側に古い作業方法があります。 好ましくないものです。 これらはモノリスで自動化が不足しており、マネージドサービスが採用されていない、という問題があります。 私は最新のアプリケーションを作りたいと思っていますが、一次元的な見方によって制約されてしまいます。 このような状況に満足できず、アーキテクトとして、なぜこのビューが一次元でなければならないのか疑問を持ちます。 なぜ左右だけなのか、また、なぜ赤と緑だけなのか、そしてなぜこれ以上の次元を持たないのか、これらの問いに答えを求めることが重要です。

アーキテクトはより多くの次元を見る

アーキテクトはより多くの次元を見るというテーマについて、 私はプラットフォームの使用量のチャートが提示されていると説明します。 しかし、そのチャートには恐ろしいロックインという言葉があります。 一見、それは一次元的に見える直線ですが、私は新しいモデルを取り入れて考えています。 私たちアーキテクトは、モデルを用いて思考を研ぎ澄ますのが好きです。 このモデルには2つの次元があり、線形であるのか、曲線を弱めることができるのかという議論ができます。 切り替え費用が発生することを認識していますが、実際にはそれほど上がらないかもしれません。 さらに、全く別の次元やレベルの議論ができます。 XファクターやZファクターといった別の要素が存在するのではないでしょうか。 パラレルユニバース全体に移行できると、ロックインを推進し、スイッチングコストを削減できる可能性があります。 このようなアーキテクチャモデルを使用することで、問題の見方や対処法が根本的に変わります。 ロックインの概念について話すと、まるで刑務所に行くようなイメージがありますが、 私たちアーキテクトはより多くの次元を考慮に入れることで、新しい解決策を見つけ出すことができると考えます。

「ロックイン」には多くの次元があります

「ロックイン」という言葉は一見奇妙に感じるかもしれませんが、実際には多くの次元と様々な段階が存在します。 そこで、重要なことを2つお伝えしたいと思います。 まず1つ目は、これはバイナリのようなものではないということです。 閉じ込められたり、独占状態に陥ったり、刑務所のような状態になるわけではありません。 実際には、多くの次元と様々な段階が存在します。 例えば、ベンダーロックインがありますが、あるベンダーから別のベンダーに切り替えることが難しい場合があります。 しかし、それだけでなく、製品やバージョンのロックインも存在します。 商用製品のあるバージョンから別のバージョンにアップグレードするだけで多額の費用を費やしている組織を知っています。 アーキテクチャの切り替えコストです。 自分でアプリケーションを構築したとしても、すべてを自由に変更することはできません。

それぞれが潜在的な切り替えコストを表しています

2つ目は、ロックインという言葉が誤解を招きやすいことです。 組織が商用製品のバージョンをアップグレードする際には、多額の費用がかかります。 アーキテクチャの切り替えコストも存在し、すべてを自由に変更することはできません。 ロックインという言葉は誤解を招きやすく、実際にはスイッチングコストを指しています。 これは、AからBに移行する際の費用であり、無料ではありません。 商用ソフトウェア製品の利用にはコストがかかりますが、それに対して利益を得られることが期待されます。 アーキテクトはトレードオフのビジネスであり、支払っている以上の価値が得られるかどうかを考慮するべきです。

オープンソースは便利ですが、スイッチングコストを魔法のようになくすわけではありません。 ベンダー関連のスイッチングコストは削減されますが、バージョンや製品、アーキテクチャの切り替えコストはまだ存在します。 オープンソースの主な利点は移植性ではなく、誰もが貢献し、透明性があり、コミュニティを持つことです。 メンタルロックインという概念もありますが、これは精神的に閉じ込められることを防ぐ方法です。

ベンダーは同等のサービスを提供しているように見える

切り替えコストについて話すとき、通常はサービスマッピングというツールが使用されます。 クラウドプロバイダーには、これらのマッピングがあります。 ベンダーは同等のサービスを提供しているようですが、実際には違いがあると言えます。 例えば、AWS には様々なデータベースがありますが、他のベンダーが同じようにデータベースを提供しているとは限りません。 一見、すべてのサービスが似ているかのように見えますが、個々のサービスにはそれぞれ違いがあります。 私たちが頻繁に使うサービスの1つである EventBridge は、イベントブローカーとしてどれだけの深みがあるかがわかる例です。 これは、AWSのサービスのほんの一部であり、他のすべてのこと、たとえば、IAM 統合や CloudWatch 統合など、 プラットフォームの一部である他のすべてのことについては言及していません。 これが、別の場所で正確に一致する可能性は非常に低いと言えます。 そのため、各ベンダー間でサービスマッピングを1対1で試みることは実際にはうまく機能しないことがわかります。 代わりに、抽象化レイヤーを作成することで、様々なサービスを使い分ける方法が求められます。 しかし、間接的なレイヤーが多すぎると、かえって問題が生じることもあります。 このように、ベンダーが提供しているサービスが同等であるという考えは一部の快適さを与えるかもしれませんが、 現実にはサービスに違いがあることを理解し、適切に対応することが重要です。

共通要素に同意することで柔軟性が生まれる

開発チームが多く存在し、プログラミング言語の選択肢を与えたい場合、 共通要素に同意することで柔軟性が生まれます。 伝統的なプログラミング言語があり、モダンなものもあるので、 APIと共通の通信プロトコルを構築する層を作成し、違いを本質的になくすことができます。 つまり、このレベルの間接性では、こちらの Python コードからあちらの TypeScript コードに話しかけることはありません。 このレイヤーがあり、かなりうまく機能します。私たちはこれをいつも使っています。 この共通層を導入することで、プログラミング言語を自由に選択できるオプションを提供し、柔軟性が生まれます。 ただし、オプションを提供するために、他のオプションもいくつか削除しなければなりません。 例えば、全員が同じ API レイヤーを使用する必要があります。 このような方法は、いくつかの要素を調和させる一方で、他の部分に柔軟性を持たせることができる興味深い方法です。 しかし、オプションと呼ばれる理由や販売オプションと呼ばれる理由があります。 それは、販売とは無料ではなく、コストがかかるということを意味します。 したがって、これらのオプションにもコストがかかります。

オプションは無料ではありません

まず、エンジニアが機能を構築する以外のことをする時、機会費用を支払っていることに注意が必要です。 1週間かけて機能を構築した場合、そのコストは単純に1日あたりの料金に比例するわけではありません。 機会費用とは、その間にエンジニアがもっとビジネス価値を生み出すことができた可能性を意味します。 しかし、これらの無料オプションやコンポーネントには、管理や維持などの面で複雑さが伴います。 APIの利用や再試行、インターフェースや契約の変更などによる影響があります。 さらに、分散システムに関連する状態管理や一貫性、有効性などの問題も発生します。 また、使用率が低いというコストも発生します。 これは、API がすべての言語や特殊なデータ型をサポートできない場合やオブジェクト指向でない場合に起こることです。 柔軟性と抽象化を追求することは、複雑性への対処を要求します。 すべてのオプションが必要な場合は、複雑さに溺れてしまうことがあります。 成功している組織は、うまく管理し、いくつかの決定を固定化して他のものを獲得することで、複雑性の罠を回避します。 範囲やオプションの概念に戻り、金融サービスから出てきたモデルを引用しています。 どのような決定をすべきかという問いに対しては、モデルが好きだと言うアーキテクトの意見が紹介されています。 このような状況では、柔軟性と抽象化を適切にバランスさせた上で、効果的な判断を下すことが重要です。

オプション取引: オプション価格 vs. 権利行使価格

クラウド上にレイヤーを設置することで、切り替えコストを削減できるという利点があります。 しかしこのレイヤーは現在のコストがかかります。 この問題に対処するために最適な方法を見つけることが目的です。 金融サービス業界では、オプション価格と権利行使価格の概念があります。 オプション価格は現在支払う金額で、権利行使価格はオプションを利用する際に支払う金額です。 これらの価値は今日現在のドルに比べて将来のドルで高くなります。 金利は組織の収益率に影響を与え、動きが速い組織ほどこの割引率が高くなります。 そのため、動きが速い組織は、切り替えコスト削減のための作業をほとんど行いません。 組織がスピードアップするほど、切り替えコストの価値が低くなります。 SQL は移植性を考慮して開発されたわけではなく、データベース操作の研究プロジェクトから生まれました。 しかし、その仕様は複雑であり、違う文脈から来ています。

最小公分母問題

既存のプラットフォーム上にレイヤーを配置する際、 2つのサービスが完全に一致しない最小公分母問題が発生します。 選択肢はギャップを埋めるか、一致しない機能を使用しないかです。 しかし、いずれの選択肢も問題があります。 APIレイヤーを作成すると、価格モデルやスケーリングメカニズム、パフォーマンスが異なる2つのサービスをうまく吸収できないことがあります。 こうした状況では、潜在的な遠く離れたケースではなく、今日の価値提案が重要になります。 分散システムの分野では、オープンソースプロジェクトがたくさんありますが、 ロックインを減らすことが主な利益として売り込まれる場合があります。 しかしこれは、未確定の将来に対するものであって、今すぐに利益を生み出すものではないことが多いです。 開発者の生活を楽にし、速度を上げ、ミスを減らすことが重要です。 速度を上げる方法はたくさんありますが、プラスの影響を与えることが大切です。 抽象化レイヤーのアイデアは周囲に存在しますが、様々なクラウド間に共通のものを入れると、 最小公分母の問題に陥りやすくなります。 そのため、切り替えコストを削減するために、新しい次元を考えることが重要です。 速度を上げることが鍵となり、今日の成功を妥協しないで、将来の約束を実現することも重要です。 今日成功するためには、速度を上げる方法を見つけることが不可欠です。

速度: 現在は良好で、移行の場合に備えて

ソフトウェア開発は、インベントリの概念があるため、インベントリを減らすことで効率を向上させられます。 リリースサイクルを短くし、頻繁に行うことで、投資後すぐに価値を取り戻すことができます。 また、開発速度が速ければ、切り替えコストも削減できます。 例として、JDK 16が非推奨となり、アップグレードが必要になったケースが挙げられています。 組織によって対応速度が違い、速度が速い組織の方が問題に対処しやすいことが分かります。 また、小さな反復で価値を提供し、価値のないものを構築しないことが重要です。 アーキテクチャで閉じ込められず、プラットフォームに近づきすぎないようにすることも大切です。 より高い開発速度は、製品を成功させるチャンスを増やし、切り替えコストも削減できます。

サービスを利用する目的は何ですか?

サービスを利用する目的は、複数のフィールドを組み合わせた条件を適用することです。 EventBridge を使用して、メッセージのフィルタリングを行いたいと考えていますが、 複雑な条件が必要な場合には実行できないことがあります。 そこで、Lambda 関数を作成し、同じことができないか検討することがあります。 ただし、サービスアイコンのみが含まれるアーキテクチャでは、意図や考慮すべきポイントが失われることが多いです。 このため、意図をよりよく伝え、表現力を持たせることが重要です。 サービス語彙のみでソリューションを説明すると、考慮すべき要素を把握しにくくなりますし、 リバースエンジニアリングが必要になる場合もあるため、難しさが増します。 しかし、サービスマップなど他の方法で全体像を捉えることができれば、理解しやすくなります。 また、求めていたものを覚えておくことで、適切な判断ができることがあります。 パターンを検討するに当たって、偏りがあることもありますが、 これらを参考にしながらより良いアプローチを模索することが大切です。

中央のパターン: Scatter-Gather

デザインプロセスの一部として、中央のパターン「Scatter-Gather」があります。 このパターンでは、複数の受信者にメッセージが送信され、結果が再集計されます。 これは古典的な統合パターンであり、重要なアーキテクチャ上の決定を要求します。例えば、受信者の数、動的性、追加・削除の可否などです。 また、受信者がどのように応答するか、棄権の可否、完了時の判断方法など、さまざまな設計上の決定事項があります。 このプロセスはサービス選択とは無関係であり、分散システム設計の重要な部分です。 サービス選択に重点を置くあまり、この設計プロセスをスキップすることは危険です。 ビジネスユーザーにも理解できるよう、要件の次にシステム設計と重要な設計上の決定を行うことが大切です。 このようなアプローチは、ソフトウェア設計やスイッチングコストの削減にも価値があります。 ですので、Scatter-Gatherなどのパターンを用いて、設計プロセスを正しく行いましょう。

レイヤーごとに語彙を分ける

意図を表すアイコンを使います。 適切なサービスを選択することも重要ですが、同時に意図も示しています。 pop-sub チャネルがあり、メッセージのフィルタリングがあります。 最後に、ここで何を達成しようとしているのかを説明する集計があります。 これの良いところは、ソリューションを3 つの異なる言語で説明できるようになったことです。

まず、ビジネス言語があります。 私がいつも使用している例は、ローンブローカーのようなものです。 誰かがローンを組みたいと思ったら、いくつかの銀行に相談して最良の見積もりを取得し、顧客に最良の見積もりを返します。 これは、ビジネスドメインの言語です。 銀行、相場、住宅ローンブローカーについて話します。 それがビジネスドメインの言語です。

そして、AWS サーバーレス・ソリューションの言語があります。 アグリゲーターを構築するためのSQL、SNS、DynamoDB があります。 関数を実行するための Lambda、その語彙です。

しかし、中間に重要な語彙があり、それは分散システムを構築するための語彙です。 これは pop-sub チャネル、メッセージ フィルター、コンテンツフィルター、アグリゲーター、トランスレーター、リシーケンサーの用語です。 この本には65個あります。 そして、それらを分離することは、現在、および可能な切り替えシナリオで非常に役立ちます。

現在までに、クラウドはいくつかのことを成し遂げてきました。 クラウドが成し遂げた最も驚くべきことの 1 つは自動化です。 自動化は、クラウドが非常に便利な理由であり、最新のクラウド・アプリケーションの構築に固有の側面です。 きめの細かいサーバーレス・アプリケーションを手に入れて、 すべてを手作業で行うことは想像できません。自動化は基本です。 これで、かなり魔法のようなことができるようになりました。 自動化とクラウドによって、デザインパターンが実現可能になり、 アグリゲーターなどのパターンをコード化できるようになりました。

複数のメッセージを組み合わせる必要がある

イベントドリブンアーキテクチャでは、入ってくるデータを結合し、 関連するイベントをまとめる必要があります。 これは DynamoDB を使用してうまく構築できます。 DynamoDB にはアトミックな操作があるため、リストに追加したりカウンターをインクリメントしたりする場合でも競合を回避できます。 しかし、デモアプリケーションで競合が高く、トランザクションが失敗する場合もあります。 この問題に対処するためには再試行が必要ですが、 Time To Liveを設定して無限に再試行されないように注意する必要があります。 例として、DynamoDB を使用した場合と他のクラウドで実装した場合の違いがあります。 DynamoDB の場合はシンプルですが、他のクラウドではメッセージキュー全体をコーディングし、 一部をサーバーレス関数やデータベースで実装します。 マッピングは複数の場所で行われるため、サービスマッピングがうまく機能しないことがあります。 最後に、パターンがどのように役立つかについてです。 DynamoDB のリストにランダムに追加することで、データを効果的に統合できることがわかります。 ただし、他のクラウド環境では実装が異なるため、適切なデザインパターンを選択し、競合や再試行戦略を正しく設定することが重要です。

アグリゲーターを構築しています

アグリゲーターを構築することで、アプリケーションの様々な場所で発生する必要性を一つのコードにまとめることができます。 エンタープライズ統合パターンの一つであるアグリゲーターを使用することで、柔軟なコード構造が可能になります。 アグリゲーターを使うと、ドキュメントのブランチからペイロードを取得し、回答を連結することができます。 また、DynamoDB を使用すれば、再試行や Time To Live の処理をする必要がなくなります。 このパターンを用いることで、異なるリソースへの対応も簡単になります。 例えば、Time To Live と再試行はキューに存在しますが、それをパターンとしてコーディングすることで、 違いが一つの場所に吸収され、他の場所への移動が容易になります。 高いレベルの抽象化を行うことで、アプリケーション内の Lambda、SQL、DynamoDB がランダムに混在しても、 それらが何をするのか正確に把握することができます。 また、複数のイベントを集約し、他のクラウドで同等のソリューションを構築することが可能です。 アプリケーションの残りの部分はほとんど変更しなくても、変更が分離された上で、 古典的な優れたアーキテクチャの操作が可能になります。 変更の伝播を減らすことで、システムの処理やテストが容易になり、システムの移植も容易になります。

パターンは設計時の抽象化です(でした)

これらのパターンは設計時の抽象化であり、 以前は紙の上で構築が行われましたが、 クラウドの登場によりプログラム可能になりました。 自動化を活用し、複雑なメッセージフィルターとコンテンツフィルターを実装しました。 メッセージフィルターは基準を満たす場合のみメッセージを渡し、コンテンツフィルターはすべてのコンテンツを通さず、特定のサブセットを提供します。 CDK を使用し、パターンをコード化しました。 中間言語を用いて、メッセージフィルターは銀行IDが含まれたメッセージを渡すなど、 コンテンツフィルターはペイロードだけを提供する機能を実装しました。 他方、EventBridgeは、メッセージフィルタリングとコンテンツフィルタリングを行うサービスです。 抽象化の層が自動化スクリプトにあり、実装を交換することが可能になりました。 これにより、より効率的に設計を行うことができます。

抽象化と切り替えコストの再考

サーバーレスと CDK を組み合わせることで、抽象化をプログラムで実現し、コードの一部にすることができます。 しかし、抽象化レイヤーには問題があります。 したがって、使用できる優れたテクニックの 1 つは、速度を上げることです。 速度が速いほど、スイッチングコストが低くなります。 それは、あなたが持っている素晴らしいレバーです。

もう 1 つのレバーは、その重要なステップをスキップしないことです。 設計意図の把握をスキップしないでください。 アーキテクチャと設計は、サービスの選択だけではありません。 そこにはもっと多くのことがあり、パターンはそれを捉えるのに役立ちます。

アーキテクチャと設計を考慮し、CDK や Pulumi などでコーディングすることで、はるかに優れた出発点になります。 これは、ソフトウェアを構築するための優れた方法であり、切り替えコストも削減します。

まとめ

  • 「ロックイン」とは、スイッチング コストを意味します。
  • オプションは価値がありますが、価格があります。
  • サービス マッピングは実際には機能しません。
  • ボトムアップからの抽象化レイヤーも機能しません。
  • サービスにとらわれることはメンタル・ロックインです。
  • 速度の向上により、スイッチングコストが削減されます。
  • デザインパターンは、アプリケーションの意図と、抽象的なプラットフォームの差異を捉えます。
  • これらの抽象化は、CDK などの最新の自動化ツールでコーディングできます。

特に最新のクラウド アプリケーションの場合、より優れたアプリケーションを構築し、スイッチング コストを低く抑えるには、設計パターンと抽象化に加えて、自動化による優れたソフトウェア配信規律を使用することが最善の方法です。

追加の学習リソース

本セッションの内容に興味を持たれた方は、上部のリンクからセッション動画、セッション資料をご覧ください。