メインコンテンツまでスキップ

Server-Mesh 入門

· 約22分

今回の技術共有は、技術のマクロな考え方と認識レベルの共有にとどめます。具体的な設定の詳細やデプロイ手順は今回の議論の範囲外です。

はじめに

今回の議論は次の 3 つのポイントを中心に進めます。

  1. マイクロサービスの限界
  2. Server-Mesh の機能と実装方式の理解
  3. 現在 Server-Mesh をベースに実現されている Serverless

私たちが最もよく知り、日常的に使っている Java、Spring-Cloud、Spring-Cloud-Alibaba などの技術スタックは、従来型マイクロサービスのアーキテクチャ設計に属します。この設計には SDK との強い結合という問題があり、下位レイヤーの SDK バージョンが更新されるたびに、ビジネスレイヤーのサービス安定性に影響を及ぼす可能性が高くなります。SDK とコード環境が強く結合していると多くの制約が生まれ、世の中のさまざまな言語とそのエコシステムのコンポーネントを、それぞれの得意分野で十分に活用することができません。たとえば、柔軟で高速な Go や Python とそれに対応するコルーチン、クローラー、ニューラルネットワークなどのコンポーネント、あるいは厳密でガベージコレクションのオーバーヘッドがない Rust は、エンタープライズ向けミドルウェアの高効率・低メモリ消費のシーンにより適しています。つまり、各言語にはそれぞれの強みとエコシステムがあり、より長期的な視点で見れば、大規模なリーディング企業がビジネスのデプロイと実装を異なる言語に落とし込んで反復していくことは一つのトレンドになるでしょう。

従来型マイクロサービス体系の図:

さらに、今日 JVM が誇りとしてきた OS を跨げるという優位性も、K8S、Docker、Containerd、CRI-O、Kata などのコンテナ技術とそのエコシステムに取って代わられつつあります。ガベージコレクション機構、動的プロキシ、Agent、ZGC などの高度な機能も他の言語に取り入れられています。現時点で Java の地位を支えているのは、長年蓄積されてきたエコシステム(Apache、Spring、Ali、Huawei などのオープンソースコミュニティが新しいミドルウェアを注ぎ込んでおり、たとえば有名な Kafka、Hadoop、Hbase、RocketMQ、Flink、Seata など、そして今後もリリースされ続けるミドルウェアが言語エコシステムの活力を維持しています)です。しかし時間の経過とともに、長期的に見れば(20〜30 年以上、主観的な予測であり参考程度にしてください)、これらの優位性は後発の新星に奪われる可能性があり、次世代のマイクロサービス体系は必然的に各言語の強みの上に反復・更新されていくでしょう。

個人的な考察: Java はすでに Oracle に買収されていますが、Oracle は技術的に先鋭的な企業ではないため、今後 Java の発展を制限する可能性が十分にあります。オープンソース版はあるものの、オープンソースの力は企業の集中的な投資には及びません。現在、IT 業界の巨人 Google の Go 言語は急速に台頭し、すでに Java の市場の一部を占めています。これが ByteDance、Bilibili、Tencent、Baidu、JD、Xiaomi などの企業が Go を選んだ理由の一つかもしれません。

サービスメッシュ

概要

私たちが注目している Server-Mesh(サービスメッシュ)に話を戻すと、現在の主な実装アプローチは Sidecar(サイドカーパターン)です。K8S では Pod を基本的なデプロイ単位として使いますが、Sidecar は 1 つの Pod の中に Proxy コンテナをデプロイする方式です。Proxy コンテナはビジネス用の Server コンテナと同じ Pod 内にデプロイされ(Pod へのコンテナ注入)、Proxy コンテナが Server コンテナのすべてのトラフィックをプロキシします。

Istio による Server-Mesh アーキテクチャの俯瞰図:

citadel: 認証と証明書管理を担うコアセキュリティコンポーネント。

galley: 設定を管理するコンポーネント。設定ファイルのフォーマットや内容の正しさを検証し、それらの設定情報を pilot と mixer に提供します。

pilot: コントロールの中枢であり、サービスディスカバリとルールの変換・配布を含みます。

proxy: C++ で開発された Envoy と Pilot-agent によって実装され、動的サービスディスカバリ、ロードバランシング、TLS、サーキットブレーカー、ヘルスチェック、トラフィック分割、カナリアリリースなどの機能を提供します。さらにテレメトリデータを生成し、マイクロサービスにオブザーバビリティを提供します。

Ingressgateway: 入口にある gateway で、メッシュ外からメッシュ内のサービスへのアクセスはこの gateway を通して行われます。

Proxy コンテナによって、ビジネスコードと SDK の完全な分離が実現され、さらに多くの機能が手に入ります。トラフィックミラーリング、カナリアリリース、サービスの登録とディスカバリ、リモート呼び出し、トラフィックのサーキットブレーカー、デグレード、分散トレーシング、コントロールプレーン、内部ネットワークのデータ暗号化転送(分散トランザクションについては現時点で特別な解決策はありません。トランザクションは厳密に言えばサービスガバナンスのレイヤーには属さないためです)。しかもプログラマーにとっては完全に透過的で、開発者はデプロイの詳細を理解する必要がなく、ほぼ完全にスタンドアロン版の感覚で開発でき、言語の制約もなく、いかなるマイクロサービス SDK にも依存しません。企業は異なる言語の特性を活かして異なる機能モジュールを開発することもできます(コード管理コストやコミュニケーションコストが増える可能性はありますが、チームが扱える言語の幅は広がります)。

公式 Demo

公式 Demo の Book-Info マイクロサービスは、Helm で K8S 環境にワンクリックでデプロイでき、その機能を体験できます(Book-Info アーキテクチャ図):

Bookinfo マイクロサービスは Istio によるサイドカーデプロイを採用し、4 種類の異なる言語のプログラムを使用しています。さらに Java で開発された Reviews サービスは 3 つの異なるバージョンのアプリケーションを提供しており、マルチバージョン管理、トラフィック管理、トラフィック移行、統合など多方面における Istio の能力をよく示しています。ぜひ自分でデプロイして体験してみてください。Service-Mesh の機能の強力さと設定の柔軟さ(すべて秒単位で反映される設定で、無停止・無感知のトラフィック移行が可能)を直感的に感じられるはずです。

市場で最も一般的な実装

Istio

Istio は Google、IBM、Lyft が立ち上げたオープンソースの Service Mesh フレームワークです。プロジェクトは 2017 年に発表され、2018 年 7 月に 1.0 版がリリースされました。2022-12-06 時点の最新バージョンは 1.16.0 です。Istio は現在の Service Mesh 実装の代表格であり、Sidecar が Service Mesh 全体のデータプレーンだとすれば、Istio は主にコントロールプレーンでより多くの改善を行っています。Istio は Envoy を Sidecar として使い、コントロールプレーン関連はすべて Golang で書かれており、パフォーマンスが大きく向上しています。Istio はまずサービスメッシュですが、単なるサービスメッシュにとどまりません。Linkerd や Envoy のような典型的なサービスメッシュの上に、Istio は完全なソリューションを提供し、サービスメッシュ全体に行動の洞察と運用制御を提供して、マイクロサービスアプリケーションの多様なニーズに応えます。

Istio

Linkerd2

Linkerd は Buoyant 社が 2016 年にいち早くオープンソース化した高性能ネットワークプロキシで、業界初の Service Mesh フレームワークです。主に分散環境におけるサービス間通信が直面する問題、たとえばネットワークの信頼性の低さ、安全性の欠如、遅延やパケットロスなどを解決するために使われます。Linkerd は当初 Scala で書かれていましたが、Linkerd2 では Go と Rust で書き直されました。

The world’s lightest, fastest service mesh.

Conduit

Conduit は 2017 年 12 月にリリースされた、Buoyant が Linkerd に続いて支援するもう一つのオープンソースプロジェクトで、Linkerd の Kubernetes 向け独立バージョンという位置づけです。Conduit は、Linkerd のようにさまざまなプラットフォームに向けて最適化するのではなく、Kubernetes 上でサービスメッシュを使う際の複雑さを徹底的に簡素化し、ユーザー体験を向上させることを目指しています。Conduit の主な目標は、軽量、高性能、安全であること、そして非常に理解しやすく使いやすいことです。Linkerd や Istio と同様、Conduit もデータプレーンとコントロールプレーンを含みます。データプレーンは Rust で開発されており、Conduit は非常に少ないメモリリソースで動作します。コントロールプレーンは Go で開発されています。

Buoyant. All of the service mesh. None of the service mess.

各アーキテクチャの比較図

まとめ

Kubernetes の登場により、運用におけるコンテナのデプロイ、高可用性、マルチレプリカ、コンテナ移行、弾力的なスケールアウト、ローリングアップデート、イメージのバージョン管理、サービスの死活監視、計算リソースの割り当て、計算ノードの監視など、大部分の問題はすでに解決され、優れた自動運用の仕組みを備えています。しかし K8S は、アプリケーションレイヤーの Service コンテナに対する監視やトラフィック管理、コンテナ間の相互呼び出し、監視、登録、設定、トラフィックガバナンスなどの機能を提供していません。この機能モジュールを補うために Server-Mesh 体系の技術が登場し、K8S のこの分野の能力を拡張しました。これによりマイクロサービスは具体的な設定や環境の詳細を気にすることなく、ビジネス機能の実装に集中でき、言語環境の制約からも解放されます。

Serverless

概要

マイクロサービスの理念が浸透するにつれて、ますます多くの企業が自社のアプリケーションをモノリスからマイクロサービスアーキテクチャへと段階的に移行させており、Container 技術の登場がこの移行を加速させました。コンテナは多くのサービス実行環境の差異の問題を効果的に解決しましたが、サービス数が増えるにつれて、コンテナのオーケストレーションと管理が新たな課題になりました。Kubernetes の登場は、大規模マイクロサービスのコンテナオーケストレーションとデプロイがもたらす課題を解決し、業界全体に PaaS の実現が現実のものになり得ることを認識させました。そしてマイクロサービス体系のコンテナ数がますます増えると、サービスガバナンスとトラフィック管理が必然的に解決すべき問題となり、そこで Istio が登場しました。ネットワークプロキシと制御を分離する実装戦略に基づき、サービスの制御ポリシーを効果的かつ合理的に管理できるようにしています。

アーキテクチャの反復はここまで来ると、とても良い段階に到達したように見えます。

  • マイクロサービス: アプリケーションの凝集と肥大化の問題を解決。
  • Container: サービス実行環境の差異とデプロイの問題を解決。
  • Kubernetes: 大量のマイクロコンテナのオーケストレーション管理と「集約」デプロイの問題を解決。
  • Istio: サービスリリース時に直面するトラフィック、リリース、ガバナンスなど一連のコンテナ関連の問題を解決。

この段階を一見すると、コンテナクラウドの構築には完全な道筋と解決方法があるように見え、すべてが「完璧」になったかのようです。

しかし振り返って掘り下げてみると、マイクロサービス体系におけるサービス間のやり取りには、依然として問題が残っているのではないでしょうか。まず、HTTP であれ RPC であれ、本質的にはサービスとサービスのリモート呼び出しであり、アプリケーション開発においてサービス間の相互透過性を実現することはできません。これにより、マイクロサービスのビジネス分割がどれだけ「精緻」であっても、本質的にはビジネスユニット同士が独立して実行・進化することはできず、完全には疎結合になっていないという問題が生じます。同時に、異なる開発領域へと派生していくとき、最適な実装方式を選択することもできません。そこで私たちは、異なる「テンプレート」や「設定」に基づいて開発環境を標準化し、同時に「イベント」の仕組みを提供して、サービス間のやり取りの結合度を最小限に抑えたいと考えます。次に、サービスの本番運用における動的スケーリングの問題です。現在の Kubernetes 環境での弾力的なスケーリングは、利用者が監視データを収集し、自ら手動で実現する必要がありますが、私たちはサービスの運用がもっと自動化・インテリジェント化されることを望んでいます。

最後にサービスの標準化の問題です。サービス内部のモデルは標準的で、迅速に複製・構築できること。サービス通信は標準的であること(プロトコルの標準、フォーマットの標準)。実行環境は標準的であること(迅速なデプロイ、迅速な移行)。これらが求められます。

そこで Knative の登場が、リモート直接呼び出し、サービスのオンライン自動スケーリング、バージョンスナップショット、そして一連の標準化の問題をちょうど解決してくれました。

Knative

Knative は 2018 年に Google が発表した Serverless の世界における強力なツールで、あらゆるパブリッククラウドやプライベートクラウド上でサーバーレスアーキテクチャを実現でき、ユーザーはサーバーレスプログラミング技術を利用できます。現在参加している企業は主に Google、Pivotal、IBM、Red Hat で、2018 年 7 月 24 日に対外的に公開され、現在も急速に発展している段階です。Kubernetes とは異なり、K8S はアプリケーションにサービスを提供するために常に少なくとも 1 つの Pod インスタンスを実行し続ける必要がありますが、Knative はゼロまでスケールインできます(コールド/ホットスタート技術)。クライアントからアプリケーションへのリクエストが来たときに初めて、Knative はアプリケーションの Pod を実際に起動します。これにより、アプリを一年中稼働させ続けるための費用を大幅に節約できます。たとえばアクセス頻度が低い、利用頻度の少ない機能モジュールは、コールドスタートでの運用を検討することで、メモリと計算リソースを節約できます(技術的な手段でコンテナの起動時間を最適化し、コールドスタートの遅延を減らすことができます【最速でミリ秒単位の起動】。現在、中国国内で最も優れているのはおそらく Alibaba Cloud でしょう)。

公式サイト:

公式ドキュメント knative.dev/docsgithub.com/knative

Knative の目標は、Kubernetes の上で開発ライフサイクル全体を支援することです。その具体的な実現方法は、まず開発者として望む言語と方法でコードを書けるようにし、次にアプリケーションのビルドとパッケージングを支援し、最後にアプリケーションの実行とスケーリングを支援するというものです。Knative は主に Build、Serving、Eventing の 3 大コアコンポーネントで構成されており、この 3 つのコアコンポーネントこそが、Knative という Serverless の巨艦を前進させる原動力です。

Build(ビルドシステム)

  • 内部ビルド: ビルドは Kubernetes の中で行われ、関数を素早くコンパイルしてリリースでき、Kubernetes エコシステム全体との結びつきがより緊密です。
  • 標準化: 汎用的で標準化されたビルドコンポーネントを提供することを目指しており、他のより大きなシステムの一部として使うことができます。デプロイスクリプトが標準化・構造化されているため、サービスの移行デプロイをより円滑に行えます。

Serving(サービングシステム)

  • 迅速なデプロイ: Serverless コンテナを素早くデプロイ。
  • オンデマンドスケーリング: 自動スケールアウト/インと 0 インスタンスへの縮退をサポート。
  • ルーティングポリシー: Istio コンポーネントをベースに、ルーティングとネットワークプログラミングを提供。
  • バージョンスナップショット: デプロイのスナップショットをサポート(本番環境のコンテナスナップショットを長期保存でき、任意のスナップショットバージョンへ復元可能)。

Eventing(イベントシステム)

Source(ソース)、Channel(チャネル)、Subscription(サブスクリプション)

イベントシステムは、イベントの生成と消費を容易にします。イベントソースを抽象化し、運用者が自ら選んだメッセージングレイヤーを使えるようにします。Serverless で最も重要なのはイベントベースのトリガー機構、つまり何かが起きたときに特定の関数がトリガーされるという仕組みです。イベントという概念の登場により、関数と具体的な呼び出し側を疎結合にできます。関数はデプロイされても誰が呼び出すかを気にする必要がなく、イベントソースのトリガーも誰が処理するかを気にする必要がありません。簡単に言えば、コードの中で具体的な呼び出し先 Service を書く必要はなく、イベントの送信とイベントの処理にだけ注目すればよいのです(MQ キューに詳しい人ならすでにピンと来ているでしょう。ただし Eventing のイベントシステムはより完成度が高く、複数のイベント処理モードがあります)。私たちの Service はリモート RPC や HTTP 呼び出しの際、具体的なサービスインスタンスを気にする必要も、レジストリを購読する必要もなく、イベントソースを発行するだけでよく、イベントの戻りデータはすべて Eventing が処理します。これによりサービス間の透過性が真に実現され、サービスの結合問題が解決されます。【結合と疎結合の差は、往々にして中間層が一つあるかないかの違いにすぎない、というわけです】

全体的な優位性

利便性: Knative は Kubernetes を基盤フレームワークとしているため、オンラインでもオフラインでも、クラウドの Kubernetes サービスでも自前で構築した Kubernetes クラスタでも、Knative プラグインをインストールするだけで Serverless プラットフォームを素早く構築できます。

標準化: Knative は CNCF と連携してすべてのイベントを標準化し、CloudEvent に統一することで、イベントのクロスプラットフォーム能力を提供し、同時に関数と具体的な呼び出し側の疎結合を実現しています。

サービス間の疎結合: Knative を使うことで、アプリケーションは下位の依存サービスと強く結びつかなくなり、クラウドを跨いだビジネス連携が可能になります。

成熟したエコシステム: Knative は Kubernetes 体系の上に構築されており、Kubernetes エコシステムとの結びつきがより緊密です。

自動スケーリング: アプリケーションへのリクエストを監視し、自動的にスケールアウト/インします。Istio(ambassador、gloo など)の力を借りて、ブルーグリーンデプロイやロールバック機能を最初からサポートしており、アプリケーションのリリースフローを簡便にします。

アプリケーション監視: ログの収集・検索・分析をサポートし、metrics データの表示や呼び出し関係の tracing もサポートします。

スナップショットデプロイ: リリースごとにサービスのスナップショット情報を記録し、長期保存が可能で、任意の時点で無停止・無感知のままあるスナップショットバージョンへ復元できます。

まとめ

Serverless(サーバーレスアーキテクチャ)は現在の新しい技術ホットスポットとなっており、従来のコンテナ技術と Server-Mesh サービスメッシュの上に発展してきたものです。サーバーレスのクラウドファンクションにより、開発者はサーバーのデプロイや運用を気にすることなく、最もコアとなるビジネスロジックや関数を開発するだけでサービスインでき、自動的に分散災害対策能力を備え、負荷に応じて自動スケーリングします。パブリッククラウドでは実際の呼び出し回数、実行時間、計算リソース消費量に応じて課金されるため、計算リソースの無駄がなく、企業の支出をより効果的に節約できます。

Serverless は大きく 2 つのタイプに分けられます。【BaaS は Backend as a Service、FaaS は Function as a Service】

BaaS: サーバーレスという言葉は、まずサーバーサイドのロジックと状態を管理するために、サードパーティのクラウドホスティングされたアプリケーションやサービスを大幅に、あるいは完全に取り込んだアプリケーションを表すために使われました。これらは通常「リッチクライアント」アプリケーション(シングルページ Web アプリケーションやモバイルアプリなど)であり、クラウドからアクセス可能な巨大なデータベースエコシステム(例: Parse、Firebase)、認証サービス(例: Auth0、AWS Cognito)などを利用します。この種のサービスは以前「Backend as a Service」と呼ばれていました。つまり私たちが後端でよく使う Spring-boot、Tomcat、Dubbo、Weblogic、Gin、Flask などのコンテナやサービスミドルウェアに相当します。

FaaS: サーバーレスは、サーバーサイドのロジックを依然としてアプリケーション開発者が書くアプリケーションを指すこともあります。ただし従来のアーキテクチャとは異なり、それはステートレスな計算コンテナの中で実行されます。これらのコンテナはイベントトリガーで起動し、関数を 1 つ実装するだけでよく、他の環境を気にする必要がなく、短命であり(1 回の呼び出しだけで終わることもあります)、完全にサードパーティによって管理されます。これを理解する一つの方法が「Function as a Service」、つまり「FaaS」です。海外では AWS Lambda が現在最も人気のある Function as a Service プラットフォームの実装の一つで、中国国内で FaaS サービスを提供しているのは Alibaba Cloud の FC(Function Compute)サービスです。

要するに、サーバーレスアーキテクチャの登場は従来のアプリケーションを置き換えるためのものではなく、高度な柔軟性を持つ利用モデルとイベント駆動という特徴を出発点に、デプロイの削減、スケーラビリティの向上、コードの背後にあるインフラの保守負担の軽減を助け、企業により適したデプロイ方式を選ぶための、より多くの可能性を提供してくれるものなのです。

今後の考察

  1. 将来のデプロイアーキテクチャはどのように発展していくのでしょうか。高可用性・高性能・高並行という 3H の特性は、どのような新しい技術体系を生み出すのでしょうか。企業がデプロイするプライベートクラウドの信頼性は、どうすれば 6〜12 個の 9 の可用性を実現できるのでしょうか【6 個の 9: (1-99.9999%)*365*24*60*60=31秒、年間の停止時間は 31 秒を超えられません。しかし 12 個の 9 となると相当な挑戦であり、企業のコストの観点からは必要性がなく、実現不可能とすら言えます。年間の停止時間は (1-99.9999999999%)*365*24*60*60=0.00003秒 を超えられないのです】。マルチリージョン・アクティブアクティブのアーキテクチャ体系と組み合わせると、さらにどれだけの新しいミドルウェア技術が派生するでしょうか。

  2. このアーキテクチャには利点だけで欠点はないのでしょうか。そのオーバーヘッドと規模、制御可能性はすべての企業に適しているのでしょうか。ビジネスシーンを考慮せずにいきなり Serverless 体系を導入するのは科学的と言えるでしょうか。

  3. ソフトウェアにおけるコンテナエコシステム技術と、ハードウェアのハイパーコンバージド技術には、異曲同工の妙があることに気づいたでしょうか。その目的はいずれも、弾力性、移行、コスト削減、柔軟性、俊敏性、そしてより高い信頼性です。

不足があればぜひ補足してください。コメントでの交流をお待ちしています。

COMMENTS