トラフィックレーンは、呼び出しチェーン全体にわたってリクエストを特定のサービスバージョンにルーティングします。たとえば、v2 とタグ付けされたすべてのリクエストは、チェーン内の各サービスの v2 インスタンスに到達します。許容モードでは、対象のサービスに対して一致するバージョンが存在しない場合、トラフィックは失敗する代わりに自動的にベースラインバージョンへフォールバックします。このアプローチにより、マルチサービスアーキテクチャ全体で安全なカナリアリリースおよびバージョンベースのテストを実施できます。また、すべてのサービスにすべてのバージョンをデプロイする必要はありません。
仕組み
トラフィックレーンを実装するために、以下の 4 種類のリソースが連携して動作します。
| リソース | 役割 |
|---|---|
| OpenTelemetry Instrumentation | コード変更を伴わず、サービス呼び出し間でバゲージヘッダーを自動的に伝搬します |
| ASMHeaderPropagation | ASM 固有の CRD であり、バゲージコンテキストから指定されたヘッダー(例:version)を抽出し、呼び出しチェーン全体でリクエストヘッダーとして付与します |
| DestinationRule | Pod のラベルに基づいてサービスサブセット(v1、v2、v3)を定義します |
| VirtualService | 伝搬された version ヘッダーに一致するようにリクエストを正しいサブセットにルーティングします。対象バージョンに健全なエンドポイントがない場合は、ベースラインサブセットへフォールバックします |
トラフィックフロー:
バゲージ: userId=alice,serverNode=DF%2028,isProduction=falsefallback フィールドは、標準の Istio VirtualService API に対する ASM 固有の拡張機能です。対象サブセットの健全なエンドポイント数がゼロの場合にトリガーされ、エラーを返す代わりに指定されたフォールバックサブセットへトラフィックをルーティングします。このフィールドは、アップストリームの Istio には存在しません。バゲージヘッダー
バゲージは、分散トレース内でプロセス間でキー/バリュー形式のコンテキストを伝搬するための OpenTelemetry 機構です。HTTP ヘッダーを使用します。
baggage: userId=alice,serverNode=DF%2028,isProduction=falseバゲージヘッダーは、テナント ID、トレース ID、セキュリティ認証情報などのコンテキストデータを保持し、コード変更を伴わずにトレース分析およびログ相関を可能にします。
トラフィックレーンの詳細については、「トラフィックレーンの概要」をご参照ください。
前提条件
開始する前に、以下の条件を満たしていることを確認してください。
Enterprise Edition または Ultimate Edition の Service Mesh (ASM) インスタンス(バージョン 1.21.6.54 以降) — 「ASM インスタンスの作成」または「ASM インスタンスの更新」をご参照ください
ASM インスタンスに追加された Kubernetes クラスター — 「ASM インスタンスへのクラスターの追加」をご参照ください
ingressgatewayという名前の ASM イングレスゲートウェイ — 「イングレスゲートウェイの作成」をご参照くださいローカルマシンに Helm がインストール済みであること — 「Helm のインストール」をご参照ください
ステップ 1:OpenTelemetry Operator のデプロイおよび自動インストルメンテーションの構成
OpenTelemetry Operator は、サービス Pod を自動的にインストルメント化し、コード変更を伴わずバゲージヘッダーを呼び出し間で伝搬します。
OpenTelemetry Operator のデプロイ
kubectl を使用して Kubernetes クラスターに接続し、
opentelemetry-operator-system名前空間を作成します。kubectl create namespace opentelemetry-operator-systemHelm を使用して OpenTelemetry Operator をインストールします。
helm repo add open-telemetry https://open-telemetry.github.io/opentelemetry-helm-charts helm install \ --namespace=opentelemetry-operator-system \ --version=0.46.0 \ --set admissionWebhooks.certManager.enabled=false \ --set admissionWebhooks.certManager.autoGenerateCert=true \ --set manager.image.repository="registry-cn-hangzhou.ack.aliyuncs.com/acs/opentelemetry-operator" \ --set manager.image.tag="0.92.1" \ --set kubeRBACProxy.image.repository="registry-cn-hangzhou.ack.aliyuncs.com/acs/kube-rbac-proxy" \ --set kubeRBACProxy.image.tag="v0.13.1" \ --set manager.collectorImage.repository="registry-cn-hangzhou.ack.aliyuncs.com/acs/opentelemetry-collector" \ --set manager.collectorImage.tag="0.97.0" \ --set manager.opampBridgeImage.repository="registry-cn-hangzhou.ack.aliyuncs.com/acs/operator-opamp-bridge" \ --set manager.opampBridgeImage.tag="0.97.0" \ --set manager.targetAllocatorImage.repository="registry-cn-hangzhou.ack.aliyuncs.com/acs/target-allocator" \ --set manager.targetAllocatorImage.tag="0.97.0" \ --set manager.autoInstrumentationImage.java.repository="registry-cn-hangzhou.ack.aliyuncs.com/acs/autoinstrumentation-java" \ --set manager.autoInstrumentationImage.java.tag="1.32.1" \ --set manager.autoInstrumentationImage.nodejs.repository="registry-cn-hangzhou.ack.aliyuncs.com/acs/autoinstrumentation-nodejs" \ --set manager.autoInstrumentationImage.nodejs.tag="0.49.1" \ --set manager.autoInstrumentationImage.python.repository="registry-cn-hangzhou.ack.aliyuncs.com/acs/autoinstrumentation-python" \ --set manager.autoInstrumentationImage.python.tag="0.44b0" \ --set manager.autoInstrumentationImage.dotnet.repository="registry-cn-hangzhou.ack.aliyuncs.com/acs/autoinstrumentation-dotnet" \ --set manager.autoInstrumentationImage.dotnet.tag="1.2.0" \ --set manager.autoInstrumentationImage.go.repository="registry-cn-hangzhou.ack.aliyuncs.com/acs/opentelemetry-go-instrumentation" \ --set manager.autoInstrumentationImage.go.tag="v0.10.1.alpha-2-aliyun" \ opentelemetry-operator open-telemetry/opentelemetry-operatorOperator Pod が実行中であることを確認します。期待される出力例:
kubectl get pod -n opentelemetry-operator-systemNAME READY STATUS RESTARTS AGE opentelemetry-operator-854fb558b5-pvllj 2/2 Running 0 1m
自動インストルメンテーションの構成
バゲージ伝搬プロパゲーターを宣言する instrumentation.yaml ファイルを作成します。環境に OpenTelemetry Collector がデプロイされているかどうかに応じて、適切な構成を選択してください。
OpenTelemetry Collector が未デプロイの場合 — コレクターのエンドポイントが利用できない場合のエラーを回避するため、メトリックエクスポートおよびトレーシングを無効化します。
apiVersion: opentelemetry.io/v1alpha1
kind: Instrumentation
metadata:
name: demo-instrumentation
spec:
env:
- name: OTEL_METRICS_EXPORTER
value: none
propagators:
- baggage
sampler:
argument: "1"
type: always_offOpenTelemetry Collector がデプロイ済みの場合 — 親ベースのサンプリングを用いた完全なトレーシングを有効化します。
apiVersion: opentelemetry.io/v1alpha1
kind: Instrumentation
metadata:
name: demo-instrumentation
spec:
propagators:
- baggage
sampler:
type: parentbased_traceidratio
argument: "1"インストルメンテーションリソースを default 名前空間に適用します。
kubectl apply -f instrumentation.yamlOpenTelemetry Collector をデプロイして可観測性データを収集することは、ベストプラクティスです。詳細については、「ASM トレースデータを OpenTelemetry 向けマネージドサービスに収集する」をご参照ください。
ステップ 2:サンプルサービスのデプロイ
このステップでは、mocka、mockb、mockc の 3 つのサービスをそれぞれ v1、v2、v3 の 3 つのバージョンでデプロイします。これらのサービスは mocka → mockb → mockc という呼び出しチェーンを形成します。各 Pod には Java 自動インストルメンテーション用のアノテーションが付与されているため、バゲージヘッダーが自動的に伝搬します。
default名前空間に対して自動サイドカープロキシ注入を有効化します。詳細については、「グローバル名前空間の管理」をご参照ください。サイドカーインジェクションの詳細については、「自動サイドカープロキシ注入を有効にする」をご参照ください。
以下の内容で
mock.yamlファイルを作成します。YAML マニフェストの主なポイント:
構成 目的 ASM_TRAFFIC_TAGラベルトラフィックレーンルーティングのために各 Pod をそのバージョン(v1、v2、または v3)でタグ付けします instrumentation.opentelemetry.io/inject-java: "true"Java コンテナに対する OpenTelemetry 自動インストルメンテーションをトリガーします instrumentation.opentelemetry.io/container-names: "default"インストルメント化対象のコンテナを指定します upstream_url環境変数呼び出しチェーンを定義します: mocka→mockb→mockcサービスをデプロイします。自動インストルメンテーションが有効化されているため、Pod は呼び出しチェーン全体で自動的にバゲージヘッダーを伝搬します。
kubectl apply -f mock.yaml
ステップ 3:トラフィックレーンのルーティングルールの作成
このステップでは、宛先ルール、ASMHeaderPropagation CRD、仮想サービス、およびイングレスゲートウェイルールを作成します。これらのリソースを組み合わせることで、伝搬された version ヘッダーに基づいてリクエストを正しいサービスバージョンにルーティングし、バージョンが存在しない場合には v1 へフォールバックします。
宛先ルールの作成
宛先ルールは、Pod のラベルに基づいてサービスサブセットを定義します。すべてのサービスが 3 つのバージョンすべてを備えているわけではありません。これは意図的な設計であり、許容モードのフォールバック動作を実証するものです。
| サービス | 利用可能なサブセット |
|---|---|
mocka | v1、v2、v3 |
mockb | v1、v3 |
mockc | v1、v2 |
以下の内容で
dr-mock.yamlファイルを作成します。kubectl を使用して ASM インスタンスに接続し、宛先ルールを適用します。
kubectl apply -f dr-mock.yaml
ASMHeaderPropagation CRD の作成
ASMHeaderPropagation CRD は、ASM に対してバゲージコンテキストからどのヘッダーを抽出し、呼び出しチェーン全体で伝搬させるかを指示します。この例では、version ヘッダーを抽出することで、ダウンストリームサービスが正しいルーティングコンテキストを受信できるようにします。
propagation.yamlファイルを作成します。フィールド 説明 apiVersionistio.alibabacloud.com/v1beta1— ASM 固有の API グループkindASMHeaderPropagation— バゲージコンテキストからのヘッダー伝搬のための CRDspec.headersバゲージから抽出し、リクエストヘッダーとして伝搬するヘッダー名のリスト apiVersion: istio.alibabacloud.com/v1beta1 kind: ASMHeaderPropagation metadata: name: version-propagation spec: headers: - versionkubectl を使用して ASM インスタンスに接続し、CRD を適用します。
kubectl apply -f propagation.yaml
仮想サービスの作成
仮想サービスは、version ヘッダーに一致するようにリクエストを正しいサブセットにルーティングします。各ルールには、v1(ベースラインバージョン)を指す fallback ターゲットが含まれています。許容モードでは、リクエストが存在しないバージョン(例:mockb には v2 が存在しない)をターゲットとする場合、ASM はエラーを返す代わりにフォールバックサブセットへルーティングします。
以下の内容で
vs-mock.yamlファイルを作成します。各サービスのルーティングパターンは、以下の構造に従います。
# 各バージョン一致に対し、プライマリ送信先とフォールバックを指定 - match: - headers: version: exact: v2 # 伝搬されたバージョンヘッダーに一致 route: - destination: host: <service>.default.svc.cluster.local subset: v2 # プライマリ:一致するバージョンへルーティング fallback: target: host: <service>.default.svc.cluster.local subset: v1 # フォールバック:v2 に健全なエンドポイントがない場合、ベースラインへルーティングkubectl を使用して ASM インスタンスに接続し、仮想サービスを適用します。
kubectl apply -f vs-mock.yaml
イングレスゲートウェイルールの作成
イングレスゲートウェイは、重みに基づいて着信トラフィックをサービスバージョン間で分散し、各リクエストに対して対象バージョンに一致する version ヘッダーを設定します。
以下の内容で
gw-mock.yamlファイルを作成します。この構成では、
mockaの v1、v2、v3 へのトラフィックを 40:30:30 の比率で分散します。各リクエストに対して、ゲートウェイはversionヘッダーを対象バージョンに設定し、呼び出しチェーン内のダウンストリームサービスがバゲージ伝搬を通じて正しいルーティングコンテキストを受信できるようにします。kubectl を使用して ASM インスタンスに接続し、ゲートウェイルールを適用します。
kubectl apply -f gw-mock.yaml
ステップ 4:トラフィックレーンルーティングの検証
イングレスゲートウェイのパブリック IP アドレスを取得してください。詳細については、「ASM イングレスゲートウェイの IP アドレスを取得する」をご参照ください。
ゲートウェイ IP を環境変数に設定します。
<gateway-ip>を実際の IP アドレスに置き換えてください。export ASM_GATEWAY_IP=<gateway-ip>繰り返しリクエストを送信してトラフィックの分散状況を確認します。出力例:
for i in {1..100}; do curl http://${ASM_GATEWAY_IP}; echo ''; sleep 1; done-> mocka(version: v1, ip: 192.168.1.27)-> mockb(version: v1, ip: 192.168.1.30)-> mockc(version: v1, ip: 192.168.1.14) -> mocka(version: v2, ip: 192.168.1.28)-> mockb(version: v1, ip: 192.168.1.30)-> mockc(version: v2, ip: 192.168.1.1) -> mocka(version: v3, ip: 192.168.1.26)-> mockb(version: v3, ip: 192.168.1.29)-> mockc(version: v1, ip: 192.168.1.14)結果を検証します。出力は以下の 2 つの動作を確認できます。重み付き分散:トラフィックは約 40:30:30 の比率で v1、v2、v3 に分割されます。許容モードフォールバック:サービスに対してバージョンが存在しない場合、トラフィックは v1 へフォールバックします。
v2 レーン:
mocka-v2→mockb-v1(mockb-v2は存在しないため、v1 へフォールバック)→mockc-v2v3 レーン:
mocka-v3→mockb-v3→mockc-v1(mockc-v3は存在しないため、v1 へフォールバック)
レーン mocka mockb mockc v1 v1 v1 v1 v2 v2 v1(v2 なし、フォールバック) v2 v3 v3 v3 v1(v3 なし、フォールバック)