Aeraki — Istioサービスメッシュで任意のレイヤー7プロトコルを管理
Aerakiは、IstioがHTTP以外のより多くのレイヤー7プロトコルをサポートできるようにするフレームワークを提供します。
Aeraki [エアラキ] はギリシャ語で「そよ風」を意味します。Istioがサービスメッシュ内のマイクロサービスを接続する一方、AerakiはIstioがHTTPとgRPC以外のより多くのレイヤー7プロトコルをサポートできるようにするフレームワークを提供します。このそよ風が、Istioがもう少し先まで進むのを助けられることを願っています。
サービスメッシュにおけるプロトコルサポートの欠如
私たちは現在、サービスメッシュに関していくつかの課題に直面しています。
- Istioやその他の一般的なサービスメッシュの実装は、HTTPやgRPC以外のレイヤー7プロトコルのサポートが非常に限られています。
- Envoy RDS(Route Discovery Service)は、HTTP専用に設計されています。DubboやThriftなどの他のプロトコルは、トラフィック管理にインラインルートをリスナーでしか使用できず、ルートが変更されると既存の接続が切断されます。
- 独自のプロトコルをサービスメッシュに導入するには、多大な労力がかかります。データプレーンでトラフィックを処理するEnvoyフィルターと、それらのEnvoyを管理するコントロールプレーンを作成する必要があります。
これらの障害により、ユーザーがマイクロサービスで広く使用されている他のレイヤー7プロトコルのトラフィックを管理することが、不可能ではないにしても非常に困難になっています。たとえば、マイクロサービスアプリケーションでは、以下のプロトコルが存在する可能性があります。
- RPC:HTTP、gRPC、Thrift、Dubbo、独自のRPCプロトコル…
- メッセージング:Kafka、RabbitMQ…
- キャッシュ:Redis、Memcached…
- データベース:MySQL、PostgreSQL、MongoDB…
すでにサービスメッシュへの移行に多くの労力を費やしている場合、当然、そのメリットを最大限に活用したいと考えるでしょう。つまり、マイクロサービス内のすべてのプロトコルのトラフィックを管理したいと考えるでしょう。
Aerakiのアプローチ
これらの問題に対処するために、私たちはオープンソースプロジェクトであるAeraki Meshを作成し、Istioサービスメッシュで任意のレイヤー7トラフィックを非侵入的で拡張可能な方法で管理できるようにしました。
この図が示すように、Aerakiフレームワークは以下のコンポーネントで構成されています。
- Aeraki:Aerakiは、オペレーションに高度でユーザーフレンドリーなトラフィック管理ルールを提供し、ルールをEnvoyフィルター構成に変換し、Istioの
EnvoyFilter
APIを活用して構成をサイドカープロキシにプッシュします。Aerakiは、データプレーンのMetaProtocolプロキシのRDSサーバーとしても機能します。HTTPに焦点を当てたEnvoy RDSとは対照的に、Aeraki RDSはすべてのレイヤー7プロトコルに一般的な動的ルート機能を提供することを目的としています。 - MetaProtocolプロキシ:MetaProtocolプロキシは、負荷分散、サーキットブレーカー、負荷分散、ルーティング、レート制限、障害注入、認証など、レイヤー7プロトコルに共通の機能を提供します。レイヤー7プロトコルはMetaProtocolの上に構築できます。新しいプロトコルをサービスメッシュに追加するために必要なことは、コーデックインターフェースと数行の構成を実装することだけです。組み込み機能で対応できない特別な要件がある場合、MetaProtocolプロキシにはアプリケーションレベルのフィルターチェーンメカニズムもあり、ユーザーは独自のレイヤー7フィルターを記述してカスタムロジックをMetaProtocolプロキシに追加できます。
DubboとThriftは、すでにMetaProtocolに基づいて実装されています。より多くのプロトコルが開発中です。クローズドソースの独自のプロトコルを使用している場合は、MetaProtocolコーデックを作成するだけで、サービスメッシュでそれを管理できます。
ほとんどのリクエスト/レスポンススタイルのステートレスプロトコルは、MetaProtocolプロキシの上に構築できます。ただし、一部のプロトコルのルーティングポリシーは「特殊」すぎて、MetaProtocolで正規化できません。たとえば、Redisプロキシは、クライアントクエリを特定のRedisサーバーノードにマッピングするためにスロット番号を使用し、スロット番号はリクエスト内のキーによって計算されます。Aerakiは、Envoyプロキシ側に利用可能なEnvoyフィルターがある限り、これらのプロトコルを管理できます。現在、このカテゴリのプロトコルについては、RedisとKafkaがAerakiでサポートされています。
MetaProtocolの詳細
MetaProtocolがどのように機能するかを見てみましょう。MetaProtocolが導入される前は、特定のプロトコルのトラフィックをプロキシしたい場合、そのプロトコルを理解するEnvoyフィルターを作成し、ルーティング、ヘッダーの変更、障害注入、トラフィックミラーリングなど、トラフィックを操作するコードを追加する必要がありました。
ほとんどのリクエスト/レスポンススタイルのプロトコルの場合、トラフィック操作のコードは非常に似ています。したがって、異なるEnvoyフィルターでこれらの機能を重複させることを避けるために、Aerakiフレームワークは、レイヤー7プロトコルプロキシの一般的な機能のほとんどを1つの場所(MetaProtocolプロキシフィルター)に実装しています。
このアプローチにより、新しいEnvoyフィルターを作成するための障壁が大幅に低くなります。つまり、完全に機能するフィルターを作成する代わりに、コーデックインターフェースを実装するだけで済みます。さらに、コントロールプレーンはすでに整っています。Aerakiは、コントロールプレーンで動作し、MetaProtocolの上に構築されたすべてのプロトコルのMetaProtocol構成と動的ルートを提供します。
MetaProtocolプロキシには、MetadataとMutationという2つの重要なデータ構造があります。Metadataはルーティングに使用され、Mutationはヘッダー操作に使用されます。
リクエストパスでは、デコーダー(コーデック実装のデコードメソッド)がリクエストから解析されたキーと値のペアでMetadataデータ構造を設定し、MetadataはMetaProtocolルーターに渡されます。ルーターは、RDS経由でAerakiから受信したルート構成とMetadataを照合した後、適切なアップストリームクラスターを選択します。
リクエストを変更する必要がある場合(ヘッダーの追加やヘッダーの値の変更など)、カスタムフィルターは任意のキーと値のペアでMutationデータ構造を設定できます。次に、Mutationデータ構造はエンコーダー(コーデック実装のエンコードメソッド)に渡されます。エンコーダーは、キーと値のペアをワイヤプロトコルに書き込む役割を担います。
レスポンスパスは、方向が異なるだけでリクエストパスと似ています。
例
MetaProtocolに基づいてアプリケーションプロトコルを実装する必要がある場合は、以下の手順に従うことができます(例としてThriftを使用)。
データプレーン
コーデックインターフェースを実装して、プロトコルパッケージをエンコードおよびデコードします。DubboコーデックとThriftコーデックを参照して、独自の実装を作成できます。
このYAMLスニペットが示すように、Aeraki
ApplicationProtocol
CRDでプロトコルを定義します。
apiVersion: metaprotocol.aeraki.io/v1alpha1
kind: ApplicationProtocol
metadata:
name: thrift
namespace: istio-system
spec:
protocol: thrift
codec: aeraki.meta_protocol.codec.thrift
コントロールプレーン
コントロールプレーンを実装する必要はありません。Aerakiはサービスとトラフィックルールを監視し、サイドカープロキシの構成を生成し、EnvoyFilter
とMetaProtocol RDSを介して構成をデータプレーンに送信します。
プロトコルの選択
Istioと同様に、プロトコルはサービスポートのプレフィックスによって識別されます。サービスポートの名前は、tcp-metaprotocol-{アプリケーションプロトコル}-xxxというパターンで指定してください。たとえば、Thriftサービスポートの名前はtcp-metaprotocol-thriftにする必要があります。
トラフィック管理
MetaRouter
CRDを介してルートを変更できます。例:リクエストの20%をv1に、80%をv2に送信します。
apiVersion: metaprotocol.aeraki.io/v1alpha1
kind: MetaRouter
metadata:
name: test-metaprotocol-route
spec:
hosts:
- thrift-sample-server.thrift.svc.cluster.local
routes:
- name: traffic-spilt
route:
- destination:
host: thrift-sample-server.thrift.svc.cluster.local
subset: v1
weight: 20
- destination:
host: thrift-sample-server.thrift.svc.cluster.local
subset: v2
weight: 80
サービスメッシュでHTTP以外のプロトコルを管理する必要がある場合に役立つことを願っています。ご不明な点がございましたら、zhaohuabingまでお問い合わせください。