BT

最新技術を追い求めるデベロッパのための情報コミュニティ

寄稿

Topics

地域を選ぶ

InfoQ ホームページ アーティクル サーバーレス時代のKubernetesワークロード:アーキテクチャ、プラットフォーム、トレンド

サーバーレス時代のKubernetesワークロード:アーキテクチャ、プラットフォーム、トレンド

ブックマーク

原文(投稿日:2019/08/12)へのリンク

 

私のRed Hat Summitでの講演「サーバレスワールドのインテグレーションパターン」は、Kubernetesが支配的な現在のエンタープライズクラウドネイティブの世界において、どこにサーバレスワークロードがフィットするかを尋ねる顧客にインスピレーションを受けました。

この記事では、その話を要約しますが、インテグレーションにはあまり焦点を当てず、さまざまなKubernetesワークロードとサーバレス製品の制限について詳しく見ていきます。関連トピックに関する次回のウェビナーに参加したい場合は、この記事の最後にある詳細をご覧ください。

分散アーキテクチャの進歩

サーバレスがどこに向かっているのか、どこに収まるのかを予測する前に、最初に、どのように、なぜここにたどり着いたかを分析する必要があります。

モノリシックアーキテクチャ

私の大規模なインテグレーションプロジェクトのキャリアは、サービス指向アーキテクチャ(SOA)が最も一般的なアーキテクチャであり、エンタープライズサービスバス(ESB)が最も一般的な実装であったときに始まりました。

SOAは優れた原則に基づいており、その大半はまだ有効です。それは契約優先開発、疎結合、構成可能、ステートレスなサービスであり、自律的で再利用可能です。

ESBフレームワークは、プロトコル変換、テクノロジーコネクタ、ルーティングおよびオーケストレーションメカニズム、エラー処理、高可用性プリミティブなどの優れた機能セットを提供しました。

分散アーキテクチャの進歩

SOAとESBの主な問題は、アーキテクチャと組織の両方の観点からの集中化でした。SOAの重要な原則は、サービスとコンポーネントの再利用でした。これにより、再利用を可能にするが、緊密なアーキテクチャ上のサービスカップリングを引き起こす階層化サービスアーキテクチャが作成されました。組織的には、ESBは単一のチームによって所有されていました。それによって、ミドルウェアは、スケーラビリティの観点で、さらに重要なことに急速な進化の観点で技術的および組織的なボトルネックになりました。少人数のグループによって定義された複雑な業界仕様がゆっくりと進化しました。

マイクロサービスアーキテクチャ1.0

SOAは企業レベルの複雑さに取り組むための優れた基盤を提供しましたが、テクノロジーは急速に進化しました。オープンソースモデルは、より迅速なイノベーションをもたらし、テクノロジーの新しい普及および標準化メカニズムになりました。

並行して、XP、スクラム、かんばんなどのアジャイル開発プラクティスにより、反復的なソフトウェア開発が行われましたが、このアプローチは、迅速にデプロイされるインクリメンタルデザインに対応できない既存のモノリシックアーキテクチャと衝突しました。その結果、機能は2週間の反復で開発されましたが、本番環境に展開されるのは年に1、2回だけでした。

マイクロサービスアーキテクチャは、適切なタイミングで万能薬として浮上し、これらの課題に対処することを約束しました。マイクロサービスアーキテクチャは、その指針原則のおかげでより迅速に変化できました。サービスはビジネスドメインを中心にモデル化され、再利用可能なSOAサービスよりも効果的にサービスの境界内に変更を含めることができました。自律的で独立して展開可能なサービスにより、各サービスは独自のペースで進化および拡張できました。

これらの新しい原則は、高速な反復と実験の時代に向けてSOAを最適化する一方で、すべてのアプリケーションを分散システムに変えるという課題ももたらしました。結果として、マイクロサービスは、高度に自動化可能で、高度に監視可能で、フォールトトレラントであり、分散システムコンポーネントが必要とするすべてである必要があります。これは誰もが最初から実現したわけではなく、さらに、必ずしも対応する準備ができていなかったものです。

マイクロサービスアーキテクチャは、高速で反復的な開発と実験の時代の技術的答えとして生まれました。しかし、古くなったツールの上にマイクロサービスの第1世代を構築したため、管理が困難でした。ESB時代には、ビジネスロジックがプラットフォームに漏れ、あらゆる種類のカップリングを引き起こしましたが、初期のマイクロサービス時代には、逆に、インフラストラクチャの懸念がすべてのマイクロサービスに漏れていました。初期のマイクロサービスには、独自の課題がありました。独自のサービス検出、構成管理、ネットワーク回復力、ログ配布などを行う必要がありました。数十または数百の新しいサービスを作成する能力は、必ずしも組織が、既存のツールを使用して本番環境にデプロイし、管理する準備が整ったことを意味するものではありませんでした。運用チーム向けのリリース、管理、処理するためのプロセスとサポートツールを改善する必要がありました。それが私たちを、Kubernetes時代に推し進めました。

クラウドネイティブアーキテクチャ(別名、マイクロサービス2.0)

マイクロサービスアーキテクチャは急速な変化のためにSOAを最適化しましたが、コードの複雑さを運用の複雑さの引き換えにすることで達成しました。その課題はコンテナの採用につながり、業界を一夜で、それまでのものと取って代わりました。コンテナは、多数のマイクロサービスを均一かつ効果的にデプロイするという苦痛を技術的に解決するものとして生まれ、最新のDevOpsプラクティスを実現しました。コンテナを使用すると、開発チームと運用チームが理解して使用できる形式で、アプリケーションをパッケージ化し、実行できます。数十または数百のコンテナを管理するには自動化が必要であり、Kubernetesが天国からやって来て、すべての競合相手を一掃したことは早い段階から明らかでした。Kubernetesは技術的課題に対処し、DevOpsプラクティスはマイクロサービスの文化的側面に対処しました。このクラウドネイティブツールは非常に基本的なものであったため、第2世代のマイクロサービスプラットフォームが登場しました。

これは、インフラストラクチャの責任がアプリケーションレイヤーからプラットフォームレイヤーに移行するという新しいシフトの始まりでした。クラウドネイティブプラットフォーム(最初は多数でしたが、最終的に主にKubernetes)は、リソースの分離と管理、自動配置、宣言的展開、正常性プローブと自己修復、構成管理、サービス検出、自動スケーリングなどの機能を提供しました。これらの機能により、アプリケーション開発者はビジネスロジックに集中し、すぐに使用できるプラットフォーム機能を使用して、インフラストラクチャの懸念に対して一様に対処できるようになります。

当時、人気のあったマイクロサービス1.0ツール(Spring CloudとNetflix OSS)とマイクロサービス2.0ツール(事実上の標準としてのKubernetes)を比較し、読者からさまざまな反応を受けました。今日では、Kubernetesはより広く理解され、受け入れられている変遷です。それは、マイクロサービス管理プラットフォームとしてのKubernetesの完全な優位性と、前世代からあった多くのNetflix OSSライブラリの非推奨によって確実なものになっています。

しかし、それはすべて歴史です。Kubernetesで次に何が来るのかを見てみましょう。

Kubernetesの輝き

Kubernetesアーキテクチャには多くの魅力的な要素があります。コンテナは、その基盤として、共通のパッケージング、ランタイム、リソース分離モデルを提供します。また、コンポーネントの実際の状態を監視し、これを目的の状態と調整するシンプルな制御ループメカニズムを提供します。さらにカスタムリソース定義を提供します。しかし、Kubernetesを拡張して多様なワークロードをサポートする真のイネーブラーは、ポッドの概念です。

ポッドは2組の保証を提供します。デプロイの保証により、ポッドのコンテナーが常に同じノードに配置されることが保証されます。この動作には、コンテナがローカルホストを超えて、あるいは、プロセス間通信(IPC)で、あるいは、ローカルファイルシステムを使って、同期または非同期に通信できるようにするなど、いくつかの役立つプロパティがあります。

ポッドのライフサイクル保証では、ポッド内のコンテナが実際に2つのグループ(initコンテナとアプリケーションコンテナ)で管理されていることを保証します。initコンテナが最初に実行され、前のコンテナが正常に完了した場合にのみ、次のものが実行されます。initコンテナーは、順次パイプライン動作を可能にし、単一のコンテナーが各ステップを実行します。一方、アプリケーションコンテナは並列に実行され、順序の保証はありません。このグループのコンテナによって、直交する機能を備えた既存のコンテナの機能を拡張および強化するための一般的なサイドカーパターンが可能になります。

 

ポッドのデプロイとライフサイクルの保証

 

拡張可能な制御ループメカニズムと一般的なポッドの特性を組み合わせることで、Kubernetesはサーバレスを含むさまざまなワークロードを処理できます。 これらの多様なワークロードを調査して、それぞれに適したユースケースを見てみましょう。

クラウドネイティブのワークロード

Kubernetesが多様なワークロードとユースケースをサポートできるユニバーサルプラットフォームである理由を証明するには、さまざまなワークロードタイプとそのニーズを調査する必要があります。

ステートフルサービス

興味深くはないが、ほとんど常にエンタープライズ環境に存在するワークロード、つまりステートフルサービスから始めましょう。ステートを外部データストアに移動することにより、ビジネスロジックを備えたステートフルサービスをスケーラブルなステートレスサービスに変えることができます。このような設計により、制約がビジネスサービスからデータソースに移動し、データソースがアーキテクチャのステートフルコンポーネントになります。これらのデータストアは通常、既製のリレーショナルデータベース、分散キャッシュ、キーバリューストア、検索インデックスなどです。動的クラウドインフラストラクチャで分散ステートフルコンポーネントを管理するには、次のような特定の保証が必要となります。

  • 永続ストレージ —状態は通常ディスク上に存在し、分散ステートフルアプリケーションは、状態を保存するためにすべてのインスタンスに専用の永続ストレージを必要とします。
  • 安定したネットワークID —ストレージ要件と同様に、分散ステートフルアプリケーションには安定したネットワークIDが必要です。ストレージ領域にアプリケーション固有のデータを保存することに加えて、ステートフルアプリケーションは、ホスト名やピアの接続詳細などの構成詳細も保存します。これは、ReplicaSetのポッドIPアドレスの場合のように、すべてのインスタンスが、予測可能なアドレスを介して到達可能であり、アドレスは動的に変更されるべきではないことを意味します。
  • 安定したID —前述の要件からわかるように、クラスタ化されたステートフルアプリケーションは、その永続的なストレージとネットワークIDを保持しているすべてのインスタンスに大きく依存しています。これは、ステートフルアプリケーションでは、すべてのインスタンスが一意であり、独自のIDを知っているためです。そのIDの主な要素は、長寿命のストレージとネットワーク座標です。このリストに、インスタンスのID/名前を追加することもできます(一部のステートフルアプリケーションには一意の永続名も必要です)。これはKubernetesではポッド名になります。
  • 順序 —一意で長期間存続するIDに加えて、クラスタ化されたステートフルアプリケーションのすべてのインスタンスは、重要な他のインスタンスに対して固定された位置を持ちます。通常、この順序は、インスタンスのスケールアップとスケールダウンの順序に影響しますが、一貫性のあるハッシュアルゴリズム、データの分散とアクセス、およびロック、シングルトン、マスターなどのクラスタ内動作の配置の基盤としても使用できます。

 


Kubernetes上の分散ステートフルアプリケーション

これらは、Kubernetes StatefulSetが提供する保証です。StatefulSet は、ステートフル特性を持つポッドを管理するための汎用プリミティブを提供します。StatefulSetを使用した一般的なZooKeeper、Redis、およびHazelcastのデプロイとは別に、他のユースケースには、メッセージブローカ、さらにはトランザクションマネージャも含まれます。

たとえば、Narayanaトランザクションマネージャは、StatefulSetを使用して、分散トランザクションを使用するサービスのスケールダウン中にJTAログを見逃さないようにします。Apache Artemisメッセージブローカは、StatefulSetに依存して、クラスタ化されたメッセージブローカを縮小するときにメッセージを排出します。StatefulSetは強力な汎用的な抽象化であり、複雑なステートフルユースケースに役立ちます。

グローバルシングルトン

Gang of Fourのシングルトンパターンは、古くからよく知られている概念です。分散されたクラウドネイティブの世界で同等なのは、グローバルなシングルトン(すべての分散サービスの中で)でありながら可用性の高いシングルトンコンポーネント(サービス全体またはその一部のみ)の概念です。このワークロードタイプのユースケースは、通常、同時に1つのクライアント(シングルトン)アクセスのみを許可するAPI、データソース、ファイルシステムなどを通して対話する必要がある他のシステムの技術的な制約から生じます。別のユースケースは、消費サービスでメッセージの順序を保つ必要がある場合であり、シングルトンに制限されます。 Kubernetesには、これらの種類のユースケースをサポートするいくつかのオプションがあります。

最も簡単なオプションは、Kubernetesに依存してサービスの単一インスタンスを実行することです。replicas=1でReplicaSetまたはStatefulSetを使用することで、簡単に実現できます。2つの選択肢の違いは、「最大で1つ」の保証を持つ強い一貫性のあるシングルトンが必要か、「少なくとも1つ」の保証を持つ弱いシングルトンが必要かです。ReplicaSetは、可用性を優先し、単一のインスタンスを維持することを優先します(「少なくとも1つ」のセマンティクス)。これにより、同時に複数のインスタンスが実行される場合があります。例えば、ノードがクラスタから切断され、最初のポッドが停止したことを確認せずに、ReplicaSetが別のノードで別のポッドを開始したときです。StatefulSetは、可用性よりも一貫性を優先し、「最大で1つ」のセマンティクスを提供します。ノードがクラスタから切断されている場合、正常なノードでポッドを起動しません。オペレーターが切断されたノードを確認するか、ポッドが実際にシャットダウンされた後にのみ起動します。これにより、サービスのダウンタイムが発生する場合がありますが、同時に複数のインスタンスが実行されることはありません。

アプリケーション内から自己管理シングルトンを実装するオプションもあります。前述のユースケースでは、アプリケーションはシングルトンとして管理されていることを認識していませんでしたが、自己管理シングルトンにより、起動されるサービスインスタンス(ポッド)の数に関係なく、単一のコンポーネントのみがアクティブになります。このシングルトンアプローチでは、ロックを取得してシングルトンとして機能するためにランタイム固有の実装が必要ですが、いくつかの利点があります。まず、偶発的な構成ミスの危険はありません。レプリカの数を増やしても、常に1つのコンポーネントのみがアクティブになります。第二に、エンドポイントなどのサービスの一部のみに対してシングルトン動作を保証しながら、サービスのスケーリングを可能にします。これは、特定の操作またはエンドポイントに関する外部の技術的な制限のために、全体ではなくマイクロサービスの一部のみがシングルトンでなければならない場合に役立ちます。このユースケースの実装例は、Apache CamelのKubernetesコネクタのシングルトン機能です。これは、Kubernetes ConfigMapを分散キーとして使用でき、Kubernetesに展開された複数のCamelサービスで、単一のCamelコンシューマーのみをアクティブ化します。


Kubernetesのシングルトンワークロード

シングルトンは少数に使われるワークロードタイプですが、取り上げる上で十分一般的です。シングルトンと高可用性の2つは相反する要件ですが、Kubernetesは許容できる妥協点で両方を提供するのに十分柔軟です。

バッチジョブ

バッチジョブの使用例は、分離されたアトミックな作業単位を処理するワークロードの管理に適しています。Kubernetesの本質は、分散環境で短命のポッドを完了するまで確実に実行するジョブ抽象化として実装されます。

 

Kubernetesでのバッチおよび繰り返しワークロード

ライフサイクルの観点から見ると、バッチワークロードには、非同期のサーバレスワークロードに似た特性がほとんどありません。単一の操作に焦点が当てられており、短命で、タスクが完了するまで持続します。ただし、ジョブベースのワークロードは本質的に非同期ですが、消費者から直接入力されることはなく、消費者の要求に応じて直接開始されることもありません。 通常、ジョブは入力データを取得する場所と結果を書き込む場所を知っています。ジョブに時間ディメンションがある場合、つまりスケジュールされている場合、その実行は一時的なイベントによって定期的にトリガーされます。

ステートレスワークロード(別名12-Factor-Apps)

ステートレスワークロードは、Kubernetesで最も広く使用されているワークロードタイプです。これは、典型的な12要素アプリケーション、またはReplicaSetを使用してKubernetes上で管理されるマイクロサービスベースのシステムです。通常、ReplicaSetはそのようなサービスの複数のインスタンスを管理し、別の自動スケーリング戦略を使用して、そのようなワークロードを水平および垂直にスケーリングさせます。


Kubernetesでのサービス検出によるステートレスワークロード

ReplicaSetによって管理されるサービスの一般的な要件は、サービスの検出と負荷分散です。そして、ここでKubernetesはすぐに使えるさまざまなオプションを提供しています。

 
Kubernetesのサービス検出メカニズム

ここでのポイントは、健全なポッドインスタンスと不健全なポッドインスタンスを動的に検出できるさまざまなサービス検出メカニズムがある場合でも、異なるサービスタイプは本質的には比較的静的であるということです。Kubernetesサービスプリミティブは、動的なトラフィック監視とシフト機能を提供しません。ここで、サービスメッシュの出番です。

サービスメッシュ

マイクロサービスベースのシステムを実装する際の課題の1つは、回復力のある通信、トレース、監視など、ビジネスロジックの一部ではないコモディティ機能を構築することです。このロジックは、以前は中央のESBレイヤーに常駐していたため、マイクロサービスのスマートクライアント間で分離して繰り返す必要があります。サービスメッシュテクノロジーは、次のような追加の拡張ネットワーキング機能を提供することにより、この問題を解決することを目的としています。

  • トラフィックルーティング — A/Bテスト、段階的なロールアウト。
  • 復元力 — 再試行、サーキットブレーカー、接続制限、ヘルスチェック。
  • セキュリティ — 認証、承認、暗号化(mTLS)。
  • 観測性 — メトリック、トレース。
  • テスト — フォールトインジェクション、トラフィックミラーリング。
  • プラットフォームの独立 — ランタイム構成を可能にするポリグロット。

これらの機能をよく見ると、インテグレーションフレームワークによって提供される機能にかなりの重複があることに気付くでしょう。


サービスメッシュと統合フレームワークの責任の重複

これらの責任のすべてをサービスの外に移すことが良いアプローチであるかどうかについては、さまざまな意見があります。ネットワークの責任はアプリケーション層から共通のクラウドネイティブプラットフォームに明確に移行していますが、すべてのネットワークの責任がアプリケーションから移動するわけではありません。

  • サービスメッシュはコネクションベースのトラフィックルーティングに適しており、サービス内からのインテグレーションフレームワークはコンテンツベースルーティングに適しています。
  • サービスメッシュはプロトコル変換を実行でき、インテグレーションフレームワークはコンテンツ変換を実行できます。
  • サービスメッシュはダークローンチを実行でき、インテグレーションフレームワークは盗聴を行います。
  • サービスメッシュはコネクションベースの暗号化を行い、インテグレーションフレームワークはコンテンツの暗号化を行います。

特定の要件はサービス内でより適切に処理され、一部はサービスメッシュを使用して外部から処理されます。また、一部はまだ両方のレイヤーで処理する必要があります。接続タイムアウトはサービスメッシュレイヤーで設定できますが、サービス内からも設定する必要があります。これは、再試行やその他のエラー処理ロジックによる回復など、他の動作にも当てはまります。サービスメッシュ、Kubernetes、およびその他のクラウドサービスは今日提供されるツールですが、アプリケーションのエンドツーエンドの信頼性と正確性に対する最終的な責任は、サービスの実装とその開発および設計チームにあります。これは変わりません。

サービスメッシュテクノロジーは、第1世代と第2世代のマイクロサービスの主な違い、つまり特定の運用責任のプラットフォームへのシフトをさらに強調しています。Kubernetesはデプロイの責任をプラットフォームにシフトし、サービスメッシュはネットワークの責任をプラットフォームにシフトします。しかし、それは最終状態ではありません。これらの変遷は、デプロイメントとトラフィックベースのインスタントスケーラビリティが必要条件であるサーバレスの世界への道を開くだけです。

サーバレスの概念

視点がすべて

サーバレスの特徴を議論するために、Cloud Native Computing Foundation(CNCF)のサーバレスワーキンググループの定義を使用します。多くのソフトウェアベンダーで最も広く合意されている定義の1つです。

サーバレスコンピューティングとは、サーバの管理を必要としないアプリケーションの構築と実行の概念を指します。1つまたは複数の機能としてバンドルされたアプリケーションがプラットフォームにアップロードされ、正確な需要に応じて実行、スケーリング、課金される、きめ細かい導入モデルについて説明します。

この定義を、サーバレスプラットフォームの恩恵を受けるコードを記述する開発者から見れば、「サーバ管理なしで、きめ細かい機能をオンデマンドで実行できる」アーキテクチャとしてサーバレスを要約できます。サーバレスは通常、開発者の観点から考慮されますが、別の、あまり議論されていない観点もあります。すべてのサーバレスプラットフォームには、プラットフォームとサーバを管理するプロバイダーがいます。粗粒度のコンピューティングユニットを管理する必要があり、そのプラットフォームには需要に関係なく24時間365日のコストがかかります。プロバイダーは、AWS Lambda、Azure Functions、Google Cloud Functionsの背後にあるチーム、またはApache OpenWhisk、Knativeを使用するKubernetesなどを管理する社内のチームです。いずれの場合でも、開発者はプロバイダーを使用して、サーバの概念を持たないワークロードタイプとしてコンピューティングとストレージを使用できます。組織およびビジネスの要因に応じて、プロバイダーは同じ組織内の別のチーム/部署(ニーズに応じてAWS Lambdaを使用するAmazonチームをイメージしてください)または別の組織(AWSの顧客がLambdaと他のサービスを使用する場合)になります。プロバイダーとコンシューマー間のビジネスの取り決めがどうであれ、コンシューマーはサーバに対して責任を負いません。プロバイダーが負います。

サーバレスアーキテクチャ

上記の定義は、「サーバレスコンピューティング」のことのみを言っています。しかし、アプリケーションのアーキテクチャは、計算とデータの組み合わせで構成されます。サーバレスアーキテクチャのより完全な定義は、サーバレスコンピューティングとサーバレスデータの両方を含むものです。通常、このようなアプリケーションにはクラウドホストサービスが組み込まれ、認証、APIゲートウェイ、監視、アラート、ロギングなどの状態および汎用サーバサイドロジックを管理します。通常、これらのホストサービスを「back-end as a service」(BaaS)と呼びます。DynamoDB、SQS、SNS、API Gateway、CloudWatchなどのサービスを思い浮かべてください。後から考えると、「サーバレス」ではなく「サービスフル」という用語は、結果として生じるアーキテクチャをより正確に説明している可能性があります。ただし、すべてをサードパーティのサービスに置き換えることはできません。これが事実であり、ビジネスロジック用のサービスが存在する場合、ビジネスの中に入ることはできません。このため、サーバレスアーキテクチャには通常、functions as a service(FaaS)としての要素を持ちます。その要素は、イベントによってトリガーされるカスタムステートレスコンピューティングの実行を可能にします。ここで最も人気のある例はAWS Lambdaです。

完全なサーバレスアーキテクチャはBaaSとFaaSで構成されており、消費者/開発者の観点からサーバの概念はありません。管理またはプロビジョニングするサーバがないということは、消費量ベースの価格設定(プロビジョニングされた容量ではない)、組み込みの自動スケーリング(制限まで)、組み込みの可用性とフォールトトレランス、組み込みのパッチとセキュリティ強化(組み込みのサポートポリシー制限付き)、監視およびロギング(追加の有料サービスとして)なども意味します。これらはすべてサーバレスの開発者によって消費され、サーバレスのプロバイダーによって提供されます。

純粋なサーバレス

サーバレスアーキテクチャが非常に良さそうであれば、すべてのコンポーネントが100%サーバレスであり、サーバの概念がない純粋なサーバレスアーキテクチャを持たないのはなぜでしょうか。その理由は、Ellen Ullman氏からの次の引用で説明できます。「コンピューターシステムは、都市を構築するのと同じ方法で構築します。時間をかけて、計画を立てずに、廃虚の上に」。エンタープライズシステムは旧市街のようなもので、通常は10年以上前から存在しており、その価値と重要性の源泉となっています。これが「エンタープライズ」になっている理由です。2000年以上前から存在するロンドンの街を想像してみてください。その世紀のTubeシステム、狭い通り、宮殿、ビクトリア朝の近隣、供給システムがあります。使用中のこのような複雑なシステムを新しいシステムに完全に置き換えることはできず、常に復元と更新(リファクタリング、アップグレード、移行、IT用語でのリプラットフォーミング)が行われます。そのようなシステムでは、変化しているという状態が標準となります。古い存在と新しい存在の混合の状態は標準です。それが、これらのシステムがどのようにして存在するに至ったかです。

サーバレス1.0

コンテナテクノロジーは長年にわたってさまざまな形で存在していましたが、Dockerはそれを普及させ、Kubernetesはそれをデプロイに対して標準にしました。 同様に、サーバレステクノロジーは長年にわたって存在していましたが、AWS Lambdaはそれを普及させ、誰がそれを次のレベルに引き上げるのかまだわかりません。

Serverless 1.0は基本的にAWSによって定義され、FaaSコンポーネントの場合はAWS Lambdaによって、BaaSコンポーネントの場合はAPI Gateway、SQS、SNSなどの他のAWSサービスによって表されます。AWSがトレンドを定義し、GoogleやAzureなど他の企業が追いつくことを試みているが、現在の世代のサーバレスの特徴のうち、理想的とは言えないものがいくつかあり、改善の対象となる可能性があります。

非決定的実行モデルには次のものがあります。

  • 予測不可能なコンテナのライフサイクルとコールドスタートに関係するセマンティクスの再利用
  • プログラミングモデルの制約は、コードの初期化ロジックに影響を与え、コールバックリークを引き起こし、追加の再帰呼び出しコストを生む
  • /tmpファイルストレージなどの予測不能なリソースライフサイクル
  • メモリ、タイムアウト、ペイロード、パッケージ、一時ファイルシステム、env変数に関する任意の制限
  • 特定のサーバレスベンダーのプログラミングモデルに影響を与える標準化されていない制約を伴う、業界を通して標準化されていない全体的な実行モデル

限られたランタイムサポートとは次のことを意味します。

  • サーバレスソフトウェアスタックは、オペレーティングシステム、言語ランタイム、ライブラリバージョンの組み合わせであり、(単一バージョンの)OS、JDK、およびアプリケーションライブラリ(AWS SDKなど)に制限されます。
  • プラットフォームサポートポリシーでは、多くの場合、サーバレススタックコンポーネントを廃止および更新できる条件が規定されており、すべてのサーバレスユーザーが同じペースで厳格なスケジュールに従うことが強制されます。
  • プログラミングAPIは問題を引き起こす可能性があります。他のサービスにAWS SDKを使用した経験は豊富ですが、すべての機能をcom.amazonaws.services.lambda.runtimeパッケージとそのプログラミングモデルと強く結合する必要があるという事実は好きではありません。
  • 標準でないパッケージを使用しています。.zip、uber-JAR、libディレクトリをカスタムAWS固有の階層化および依存関係モデルで使用しても、パッケージングが時代遅れにならないことや、サーバレスプラットフォームで機能することを確信できません。
  • カスタム環境変数(AWS_で始まる)は、他のサーバレスプラットフォームでは機能しません。

独自のデータ形式

独自のデータ形式は障害です。イベントは、サーバレスアーキテクチャの機能に対する主要な接続メカニズムです。イベントはそれぞれの機能を他の機能やBaaSに接続します。イベントは事実上、関数に対するAPIとデータフォーマットです。すべての関数でcom.amazonaws.services.lambda.runtime.eventsパッケージで定義されたイベントを使用すると、相互運用性がゼロになります。

Javaサポートなし

AWS LambdaにはJavaランタイムがありますが、JavaとLambdaにはAWSでさえお勧めできないミスマッチがあります。Tim Bray氏の講演「AWSの内部:最新のアプリケーションのためのテクノロジーの選択」で、彼は代わりにGoとPythonを使用することを提案しています。数百万人のJava開発者を再教育し、数百万のJavaライブラリのエコシステムを変更しようとするのではなく、サーバレスプロバイダーがより良くなるように、ランタイムを改善することを期待しています。Javaは既に Goと同じくらい軽くて速いため(あるいは、たとえ良くなくても)、この言語でサーバレスを構築することは避けられません。

考えられる影響

レビューでは、非決定的で標準化されていない実行モデル、独自のランタイム、独自のデータ形式、独自のAPI、およびJavaサポートの欠落の組み合わせは、これらすべての問題がアプリケーションコードに漏れて、ビジネスロジックを実装する方法に影響を与えることを意味します。これは、ある組織から別の組織への究極の委譲です。現在のサーバレスはビルド時のアーティファクトを、SDKおよびパッケージ形式、イベント形式、ソフトウェアスタックの形式で提供します。そして、ランタイム環境を提供し、サーバレスコンシューマーはサポートポリシーとプロバイダーが課す独自の制限にコミットします。コンシューマーは、プロバイダーの言語ランタイム、SDK、アップグレード、および非推奨に固執し続け、それらについていくことにコミットします。彼らは、サーバレスプラットフォーム間で相互運用性のない関数を記述することで、これらの条件を守ります。すべてに対してBaaSを使用し、関数で記述された組織のビジネスロジックを独自の実行モデル、ランタイム、API、データ形式に結合した場合、他ではどこでも使えません。他の場所には行きたくないかもしれませんが、オプションを持つことは重要です。

結合とロックイン自体は悪くありませんが、移行のコストは高くなります。AWS AMI、AWS RDSを使うこと、人気のあるオープンソースプロジェクトをマネージドサービスとして使うこと、SQSを使うことでさえも、ロックインされることを気にしないコンシューマーの例です。それらは、代替サービスまたは代替プロバイダーへの移行が現実的にあり得る代替になるにも関わらずです。これは、ビジネスロジックを未熟なサーバレステクノロジーとサーバレスプロバイダーの特性に具体的に結合することとは異なります。ここでは、移行作業はビジネスロジックとグルーコードの完全な書き換えとテストであり、サーバレスアーキテクチャの高度に分散された性質を考慮すると特にコストがかかります。

Microservicesは、コードの複雑さを運用の複雑さと引き換えにしています。サーバレスは速度を制御を引き換えにします。モダンなアーキテクチャを選択しますが、小さな活字を読んでください。アーキテクチャの選択はすべてトレードオフです。

サーバレス1.5

AWSは、サーバレスをこの場所に持ち込むという驚くべき仕事をしましたが、サーバレスの現在の状態がその最高点ならば悲しいことでしょう。また、サーバレスで革新し、その将来を定義できるのがAWSだけである場合も悲しいでしょう。オープンソースエコシステムにおけるAWSのバックグラウンドが比較的限られていることを考えると、AWSがサーバレスパラダイムを標準化し、そのような基本的なレベルで業界全体に影響を与えることを期待するのは過剰な期待でしょう。AWSのビジネスモデルと市場での地位は、市場の動向と初期のクローズドイノベーションを特定するのに適していますが、オープンソースモデルは、一般化、標準化、および強制のない業界全体の受け入れに適しています。私は、業界全体がより広範にコラボレーションして、オープンソースモデルを使用して、次世代のサーバレスが作成され、その採用と相互運用性が向上することと期待しています。そのプロセスが開始され、今日の独自のサーバレス製品の相互運用性と移植性を業界はゆっくりと模索しています。

明日のサーバレステクノロジーを推進し、影響を与えると信じている業界のトレンドのいくつかについて、特に順序はつけませんが、議論しましょう。

統一されたパッケージングおよび実行モデル

コンテナは、アプリケーションのパッケージ化とランタイムの業界標準として確立されています。コンテナ化されたアプリケーションと強力なオーケストレーションエンジンを組み合わせることで、これまで見てきたように、様々なワークロードを実現できます。サーバレスワークロードが例外である理由はありません。これにより、パッケージング形式と実行モデルが混在する状態に戻ります。Knativeは、サーバレスの特性(ゼロへのスケーリング、HTTPリクエストに基づく自動スケーリング、サブスクリプション、デリバリ、バインディング、イベントの管理)をKubernetes上のコンテナベースのワークロードに載せようと、現状に挑戦している複数のベンダーによるオープンな共同の取り組みです。コンテナベースのパッケージングとKubernetesベースの実行により、複数のサーバレスプロバイダーで標準化できるオープンな実行モデルが可能になります。これにより、Java、カスタムソフトウェアスタック、制限、カスタマイズ性のサポートが強化され、より豊富なランタイムが利用できるようになります。

言語ランタイムとイベントハンドラーを関数パッケージに含めることは、サーバレスのオリジナルの定義によるFaaSではなく、実装の詳細であり、これは明日のサーバレスに必要とされるオプションであると主張する人もいるかもしれません。

業界で受け入れられているイベント形式

サーバレスアーキテクチャは定義上、イベント駆動型であり、イベントは中心的な役割を果たします。サーバレス環境に存在するイベントの種類が多いほど、開発者の経験が豊かになり、市販のサービスで置き換えることができるロジックが増えます。しかし、ビジネスロジックがイベントの形式と構造と連動するようになると、高くつきます。コアビジネスロジックを分離し、イベント処理ロジックを個別のメソッドに分割するためにAWSベストプラクティスを読むことができますが、デカップリングにはほど遠いです。ビジネスロジックとサーバレスプラットフォームのデータ形式の結合により、相互運用性が妨げられます。CloudEventsは、すべてのサーバレスプラットフォームで動作する標準化されたイベント形式を作成するための活動です。素晴らしいアイデアであるだけでなく、AWSを含む業界の大きな関心があります。これはおそらく、その重要性と採用可能かどうかの最終的な検証になります。

移植性と相互運用性

標準パッケージング形式と標準イベントがあれば、次のレベルの自由は、パブリックまたはプライベートクラウド上で、オンプレミスで、エッジでサーバレスプロバイダーを越えてサーバレスワークロードを実行し、必要に応じてハイブリッドで、すべてをミックスし適合させる機能です。機能は、マルチクラウド、ハイブリッドクラウド、任意のクラウド、非クラウド、またはそれらの混合で実行できるべきであり、いくつかの構成とマッピングのみでできるべきです。Javaアプリケーションを記述して抽象インターフェースを実装し、それらを異なるWebコンテナにデプロイするのと同じように、私は、独自でないAPI、イベント、プログラミングモデルに対して関数を記述し、それを任意のサーバレスプラットフォームにデプロイし、予測可能で決定的な方法で動作させたいです。

移植性に加えて、機能がどこで実行されているかに関係なく、どのプラットフォームからでもイベントを消費できる関数を備えた相互運用性を見たいです。KEDAなどのプロジェクトによって、AWS、Azure、その他のイベントトリガーに応じて、Azure Functionsなどのカスタム関数を実行できるようになります。TriggerMeshなどのプロジェクトによって、KubernetesやOpenShiftで、AWS Lambda互換関数をデプロイできるようになります。これらは、パッケージング、実行環境、イベントフォーマット、イベントソース、ツールなど、複数のレベルで将来の機能が移植可能で相互運用可能になる兆候です。

Javaをファーストクラスとして扱う

サーバレスワークロードは多くのユースケースに適していますが、企業の最も一般的なプログラミング言語であるJavaの使用を妨げることは大きな制限です。VMのサブストレートと、Quarkusのようなフレームワークのおかげで、Javaは既に軽量で高速、クラウドネイティブ、サーバレスに対応しています。また、このようなJavaランタイムは、期待した通り、AWS Lambda向けを含め、サーバレスでもまもなく利用可能になる気配があります。

サーバレスの特性を持ち、標準化されたイベントと共に機能の移植性および相互運用性を備え、クラウドネイティブおよびサーバレス環境用に作成された超軽量で高速なJavaランタイムを備えた、コンテナ化されたワークロードは、すべてサーバレスが変化しようとしているシグナルです。私はまだこれらの指標に「第2世代サーバレス」というラベルを付けたくありません。しかし、それは第1世代のサーバレスではなく、1.5が正しいと感じています。

Cloud FoundryがPaaS戦争に勝ったと多くの人が思ったのを覚えていますが、その後Kubernetesが生まれました。多くの人が、AWS LambdaがFaaS戦争に勝ったと主張しています。Kubernetes(またはそれ以上のもの)がそれらが間違っていることを証明することを願っています。

サーバレスワークロード

ビジネスドメインのサービスをモデリングし、サービス内の変更をカプセル化することにより、マイクロサービスアーキテクチャがモノリシックアプリケーションのデプロイサイクルをどのように改善するかを見ました。サーバレスの素朴な説明は、これをさらに小さなマイクロサービスとして表現することです。すべての操作は関数です。それは技術的には可能ですが、それは両方のアーキテクチャにとって最悪である。結果として生まれるアーキテクチャから利益を得ることなく、多数の関数が同期的に相互に呼び出すことになります。

マイクロサービスの価値は、WebベースのAPI(通常はRESTスタイル)を使用して、一連の要求/応答スタイルの操作の背後にある複雑なビジネスドメインロジックと永続化ロジックをカプセル化できるという事実にあります。一方、サーバレスおよび関数は、イベントとトリガーに焦点を当てています。関数をAPIゲートウェイの背後に配置して要求/応答スタイルで動作させることはできますが、APIは主要なインターフェースとなることを意図していません。イベントとトリガーが主役です。サーバレスアプリケーションは、アプリケーションが非同期(要求/応答ではなく、単方向のファイア・アンド・フォーゲットスタイル)で、キューまたはその他のデータおよびイベントソースを介して接続する場合に最適に動作する傾向があります。結果として、各関数は1つのアクションのみを実行することを目的としており、他の関数を直接呼び出すことを避け、その結果をイベントストアに書き込む必要があります。実行モデルのため、関数は短命であり、典型的なRDBMSの場合のように、接続指向ではない他のサーバレスデータソースと共に使用されることが想定されています。デプロイサイズの点で軽量で、起動が高速です。次のユースケースはすべて、さまざまなイベント駆動型システムを接続するグルーコードとして機能するため、サーバレスによりふさわしいものとなります。

  • バッチ処理、ストリーム処理、extract-transform-load(ETL)などのオンデマンド機能
  • バッチジョブなど、短時間実行される分割可能な作業のタスクスケジューリング
  • データソースの変更に応じてロジックを実行するイベント駆動型アーキテクチャ
  • 頻繁に発生しない、または予測不可能な負荷のある一貫性のないトラフィックのような不均一なトラフィックの処理
  • 運用における汎用の「glue」コード
  • ビルドジョブ用のオンデマンドリソースを備えた継続的インテグレーションパイプライン
  • インシデントの発生時のアクションのトリガーや人への通話による通知などの運用タスクの自動化

サーバレスの世界で起こっているいくつかの主要な革新について説明しましたが、Kubernetesでどのように見えるかについては説明しませんでした。多くの努力がサーバレスをKubernetesに持ち込もうとしましたが、業界で最も幅広いサポートがあり、成功の可能性が最も高いプロジェクトはKnativeです。 Knativeの主な目標は、一般的なサーバレスユースケース向けに高レベルの抽象化を備えた集中型APIを提供することです。それはまだ若いプロジェクト(執筆時点ではバージョン0.5)であり、急速に変化しています。Knativeが現在サポートしているサーバレスワークロードを調べてみましょう。

リクエストの配信

マイクロサービスからサーバレスへ少ない摩擦で移行するアプローチは、単一操作関数を使用してHTTP要求を処理することです。私たちはサーバレスプラットフォームが数秒でステートレスでスケーラブルな関数を立ち上げることができると期待しています。これは、Knative Servingがサーバレスワークロード用の共通のツールキットとAPIフレームワークを提供することで達成するつもりのものです。このコンテキストでのサーバレスワークロードは、主にアプリケーションレベル(L7)のリクエストトラフィックによって駆動される、単一コンテナーのステートレスポッドです。

Knative Servingプロジェクトは、以下を可能にするプリミティブを提供します。

  • 高レベルで特定の目的を持ったプリミティブを提供することによるサーバレスコンテナの迅速なデプロイ
  • リクエストにより、アクティベーション、スケールアップ、ゼロへのスケールダウン
  • 低レベルのプリミティブの自動ルーティングと構成
  • リビジョンの不変のスナップショット(デプロイされたコードと構成)

上記のすべては、ポッドごとに1つのコンテナー、1つのポート、永続性なし、およびその他のいくつかの制限など、特定の制限内で実現可能です。

イベンティング

Knative Eventingプロジェクトは、信頼性が高くスケーラブルな非同期イベント駆動型アプリケーションを作成するためのビルディングブロックを提供します。CloudEvents標準を使用して、イベントの消費と作成に関する標準的なエクスペリエンスを作成することを目指しています。Knative Eventingの高レベルの機能は次のとおりです。

  • インポーター(GitHub、Kafka、SQS、Apache Camelなど)およびチャネル実装(Kafka、Google Pub/Sub、NATS、インメモリなど)のさまざまな実装を可能にする拡張可能でプラグ可能なアーキテクチャ
  • イベントタイプのカタログを維持するためのイベントレジストリ
  • イベントソース、トリガー、サービスをバインドすることによる、イベントオーケストレーション用の宣言型API
  • 特定のブローカからのイベントへのサブスクライブと、下流のKnativeサービスにイベントをルーティングする前のオプションのフィルタリングを可能にするトリガー機能

これらの機能は興味深いものですが、クラウドネイティブ開発者がKubernetes上でより生産的になるためにどのように役立つでしょうか。

関数を実装し、それをコンテナとして構築し、徹底的にテストしたと仮定します。それは基本的には、HTTP経由でCloudEventsを受け入れる単一の操作を備えたサービスです。Knativeを使用して、サーバレスの特性を持つワークロードとしてコンテナをKubernetesにデプロイできます。たとえば、Knative Servingプリミティブを使用すると、コンテナはHTTP要求がある場合にのみアクティブになり、必要に応じて迅速にスケーリングできます。さらに、チャネルにサブスクライブすることにより、ブローカからCloudEventsを受け入れるように同じポッドを構成することもできます。このポッドは、Knative Sequenceを介して定義されたより複雑なイベントオーケストレーションフローのステップとしても機能します。これらはすべて、宣言的なKnative設定のみを使用して、既に構築されているコンテナーを変更することなく可能です。Knativeは、サーバレスインフラストラクチャのルーティング、アクティベーション、スケーラビリティ、信頼性、サブスクリプション、再配信、およびブローカの回復力を保証します。まだ到達していませんが、そこに向かっています。

カスタムワークロード

それだけではありません。 標準のワークロードプリミティブでは提供されない非常に特殊なニーズを持つアプリケーションがある場合、Kubernetesにはさらに多くのオプションがあります。このような場合、Custom Controllerは、Kubernetesリソースのセットを望ましい状態でアクティブに監視および維持することにより、クラスタの動作にカスタムの機能を追加できます。

高レベルでは、コントローラーは「Observe -> Analyze -> Act」ステップを実行するアクティブな調整プロセスです。望ましい状態になるように対象オブジェクトを監視し、それらを世界の実際の状態と比較します。次に、プロセスは、世界の現在の状態を望ましい状態に近づけるように指示を送信します。

カスタムワークロードを処理するためのより高度なアプローチは、別のすばらしいKubernetes拡張メカニズムであるCustomResourceDefinitionsを利用することです。Kubernetes OperatorをCustomResourceDefinitionsと組み合わせると、特定のアプリケーションのニーズに対する運用知識を「アルゴリズム」の形でカプセル化できます。オペレーターは、Kubernetesとアプリケーションドメインを理解するKubernetesコントローラーです。両方の領域の知識を組み合わせることにより、通常は人間のオペレーターが必要なタスクを自動化できます。

コントローラーとオペレーターは、プラットフォームを拡張し、Kubernetesで複雑なアプリケーションライフサイクルを実現するための標準メカニズムに変わりつつあります。その結果、より洗練されたクラウドネイティブのワークロードのライフサイクル全体を管理するためのコントローラーのエコシステムが形成されていきます。

Operatorパターンを使用すると、Controllerパターンを拡張して、柔軟性と表現力を高めることができます。この記事で説明されているすべてのワークロードタイプとその他の関連パターンは、最近私が共同で作成した書籍Kubernetes Patternsに記載されています。これらのトピックの詳細については、こちらをご覧ください。

クラウド固有のトレンド

Kubernetesエコシステムでは、ビジネスロジックの一部でないコモディティ機能を次々にプラットフォームレイヤーに移行する傾向が続いています。

  • デプロイ、配置、ヘルスチェック、リカバリ、スケーリング、サービス検出、構成管理はすべてKubernetesレイヤーに移動しました。
  • サービスメッシュは、復元力のある通信、トレース、監視、トランスポートレベルのセキュリティ、トラフィック管理などのネットワーク関連の責任をプラットフォームに移行することで、このトレンドを継続しています。
  • Knativeは、特殊なサーバレスプリミティブを追加し、迅速なスケールアップ、ゼロへのスケーリング、ルーティング、イベンティングインフラストラクチャの抽象化、イベント発行、サブスクリプションメカニズム、ワークフロー構成などの責任もプラットフォームへ移動しています。

これにより、主にアプリケーション開発者が実装するビジネスロジックに対する懸念が残ります。プラットフォームが残りの部分を処理します。


責任はプラットフォームに移る。より多くの抽象化により、多様なワークロードが可能になる

私たちは、Kubernetesに高レベルの抽象化を追加することにより、ますますコモディティに対する責任をアプリケーションレイヤーからプラットフォームへシフトします。たとえば、Istioは、低レベルのKubernetesプリミティブに依存する高レベルのネットワーク抽象化を提供します。Knativeは、KubernetesおよびIstioからの下位レベルの抽象化に依存する上位レベルのサーバレス抽象化を追加します(注意ですが、これは、変更されようとしており、Knativeは今後Istioに依存することはありませんが、同様の機能を実装する必要があります)。

これらの追加の抽象化により、Kuberntetesは、同じオープンパッケージとランタイム形式で、サーバレスを含むさまざまなワークロードを均一にサポートできます。

ランタイムとアプリケーション設計

モノリシックアーキテクチャからマイクロサービスおよびサーバレスへの移行に伴い、ランタイムも進化しています。そのため、20年前のJavaランタイムは「「一度(プログラムを)書けば、どこでも実行できる」から離れ、ネイティブ、軽量、高速、サーバレスファーストになります。


Javaランタイムとアプリケーション設計の傾向

 

長年にわたり、ムーアの法則および計算能力の向上は、Javaを、高度なガベージコレクター、JITコンパイラー、および他の多くのものが備わった最も高度なランタイムの1つを構築する方向に導いている。ムーアの法則の終わりにより、Javaはマルチプロセッサシステムとマルチコアシステムの恩恵を受けるノンブロッキングプリミティブとライブラリを導入しました。同じ精神で、クラウドネイティブやサーバレスなどのプラットフォームのトレンドにより、分散システムコンポーネントは軽量で高速になり、1つのタスクに最適化されています。

サーバレス

サーバレスパラダイムは、次の基本的なアーキテクチャの進化であると認識されています。しかし、現在のサーバレスの世代は、優先度が速度であるアーリー・アダプタと破壊者の中から出現しました。それは、複雑なビジネスおよび技術的な制約がある企業の優先事項ではありません。これらの組織の中で、業界標準はコンテナオーケストレーションです。Kubernetesは、Knativeイニシアチブを通じてクラウドネイティブとサーバレスをリンクしようとしています。CloudEventsやSubstrate VMなどの他のプロジェクトもサーバレスエコシステムに影響を与えており、オープン性、移植性、相互運用性、ハイブリッドクラウド、グローバルな採用の時代へと進んでいます。

 

2019年10月10日木曜日、「Kubernetesパターンを使用したクラウドネイティブアプリケーションの設計」をRed Hatが主催する仮想イベントで紹介します。このトピックとコンテンツに興味がある場合は、議題を確認して登録し、ライブで聞いてください。

著者について

Bilgin Ibryam氏は、Red Hatのプリンシパルアーキテクトであり、複数のApache Software Foundationプロジェクトのコミッターです。彼はブロガー、オープンソースの伝道者、ブロックチェーン愛好家、講演者です。彼は書籍Camel Design PatternsKubernetes Patternsの著者です。彼は、高度にスケーラブルで回復力のある分散システムの設計と構築について10年以上の経験を持っています。Ibryam氏は日々の仕事で、実績のある反復可能なパターンと実践を通じて、大規模なオープンソースソリューションの構築を成功させるために、企業のチームを指導することを楽しんでいます。彼の現在の関心には、エンタープライズブロックチェーン、クラウドネイティブおよびサーバレスパラダイムです。これらのトピックの定期的な更新情報については、@bibryam をフォローしてください。

 
 

この記事に星をつける

おすすめ度
スタイル

BT