Service Mesh (ASM) は、コードを変更することなく、Istio ベースのトラフィック管理を Spring Cloud アプリケーションに追加します。Spring Cloud サービスを ASM に接続すると、アプリケーションは既存のサービスレジストリをサービス検出に引き続き使用しながら、VirtualService や DestinationRule などの Istio CRD を使用して、ルーティング、負荷分散、バージョンベースのトラフィック分割を制御できます。
サポートされる実装とレジストリ
ASM は、以下の Spring Cloud 実装をサポートしています。すべての移行でコードの変更は不要です。
| Spring Cloud 実装 | サービスレジストリ | コード変更なしでの移行サポート |
|---|---|---|
| Spring Cloud Alibaba | Microservices Engine (MSE) Nacos | はい |
| Spring Cloud Alibaba | 自己管理の Nacos | はい |
| Spring Cloud Netflix | Eureka | はい。ASM バージョン 1.13.4.53 以降が必要です。 |
| Spring Cloud Consul | Consul | はい。ASM バージョン 1.13.4.53 以降が必要です。 |
| Spring Cloud Zookeeper | Zookeeper | はい。ASM バージョン 1.13.4.53 以降が必要です。 |
仕組み
Spring Cloud アプリケーションは、サービス検出のためにサービスレジストリ (Nacos、Eureka、Consul、または Zookeeper) に依存しています。ASM は、EnvoyFilter を介してレジストリのトラフィックをインターセプトすることで、このレジストリベースの検出と Istio のメッシュネイティブモデルを橋渡しします。インターセプト後、サイドカープロキシはサービス名を Pod IP に解決し、Istio CRD がサービス間のすべてのトラフィックを管理します。
ASM コントロールプレーンでこのブリッジを有効にするには、2 つのメソッドがあります:
| メソッド | サポートされるレジストリ | 要件 |
|---|---|---|
| メソッド 1:逆引き DNS | すべてのレジストリ | ASM 1.13.4.32 以降 |
| メソッド 2:Lua フィルター | Nacos のみ | 2.0 より前の Nacos クライアント SDK (v2.0 以降は gRPC を使用するため、Lua とは互換性がありません) |
前提条件
開始する前に、以下を確認してください:
Enterprise Edition または Ultimate Edition の ASM インスタンス。詳細については、「ASM インスタンスの作成」をご参照ください。
ACK マネージドクラスター。詳細については、「ACK マネージドクラスターの作成」をご参照ください。
ASM インスタンスに追加された ACK クラスターです。「ASM インスタンスにクラスターを追加する」を参照してください。
イングレスゲートウェイがデプロイ済みであること。 詳細については、「イングレスゲートウェイを作成する」をご参照ください。
デモアーキテクチャ
このチュートリアルでは、3 つのサービスを持つ Spring Cloud Nacos デモを使用します:
コンシューマーサービス:ポート 8080 を公開し、
/echoエンドポイントを持ちます。リクエストをプロバイダーサービスに転送し、その応答を返します。プロバイダーサービス (V1):
Hello Nacos Discovery From v1<parameter>で応答します。プロバイダーサービス (V2):
Hello Nacos Discovery From v2<parameter>で応答します。
両方のプロバイダーバージョンは Nacos レジストリに登録されます。コンシューマーは Nacos を通じてこれらを検出し、ラウンドロビン方式で V1 と V2 にリクエストを分散します。
例えば、/echo/world へのリクエストは、Hello Nacos Discovery From v1world または Hello Nacos Discovery From v2world のいずれかを返します。

デモのソースコードは nacos-examples リポジトリからダウンロードしてください。
サイドカープロキシ注入がない場合、これらのサービスは正常に動作しますが、Istio からは認識されません。以下の手順では、既存の Spring Cloud サービス検出の上に、メッシュベースのトラフィック管理を追加します。
ステップ 1:ASM コントロールプレーンでの Spring Cloud サポートの有効化
メソッド 1:逆引き DNS (すべてのレジストリ)
ASM 1.13.4.32 以降が必要です。
宛先サービスとして Kubernetes サービスが存在する必要があります。サービスポートと宛先ポートは、アプリケーションが Server Load Balancer (SLB) インスタンスを介してルーティングされるポートと一致する必要があります。
ASM 1.23.6.32 以降では、REGISTRY_ONLY を無効にしてください。
kubectl を ASM コントロールプレーンに接続します。詳細については、「コントロールプレーン上の kubectl を使用した Istio リソースへのアクセス」をご参照ください。
any-spring-cloud-support.yamlという名前のファイルを作成します。ご利用の環境に応じて、次の値を置き換えてください:パラメーター 説明 確認場所 portNumberご利用の Spring Cloud サービスのポート。このパラメーターを削除するとすべてのポートに一致します。特定のポートを対象にするには、個別の EnvoyFilter リソースを作成します。 アプリケーションの構成 pod_cidrsACK クラスターまたは ACK Serverless クラスターの Pod CIDR ブロック。 「Container Service for Kubernetes (ACK) コンソール」で、[クラスター] に移動し、ご使用のクラスターをクリックして、[クラスターリソース] タブを開きます。vSwitch CIDR ブロックを表示するには、VPC リンクをクリックします。 apiVersion: networking.istio.io/v1alpha3 kind: EnvoyFilter metadata: labels: provider: "asm" asm-system: "true" name: any-spring-cloud-support namespace: istio-system spec: configPatches: - applyTo: HTTP_FILTER match: proxy: proxyVersion: "^1.*" context: SIDECAR_OUTBOUND listener: portNumber: 8070 filterChain: filter: name: "envoy.filters.network.http_connection_manager" subFilter: name: "envoy.filters.http.router" patch: operation: INSERT_BEFORE value: name: com.aliyun.reverse_dns typed_config: "@type": "type.googleapis.com/udpa.type.v1.TypedStruct" type_url: type.googleapis.com/envoy.config.filter.reverse_dns.v3alpha.CommonConfig value: pod_cidrs: - "10.0.128.0/18"EnvoyFilter を適用します:
kubectl apply -f any-spring-cloud-support.yaml
メソッド 2:Lua フィルター (Nacos のみ)
kubectl を ASM コントロールプレーンに接続します。詳細については、「コントロールプレーン上の kubectl を使用した Istio リソースへのアクセス」をご参照ください。
external-nacos-svc.yamlという名前のファイルを作成して、Nacos サーバーのサービスエントリを定義します。<your-nacos-server-host>を Nacos サーバーのエンドポイント (例:mse-xxx-p.nacos-ans.mse.aliyuncs.com) に置き換えてください。ポート8848はデフォルトの Nacos ポートです。自己管理の Nacos が異なるポートを使用している場合は、numberの値を更新してください。kind: ServiceEntry metadata: name: external-nacos-svc spec: hosts: - "<your-nacos-server-host>" # 例:mse-xxx-p.nacos-ans.mse.aliyuncs.com location: MESH_EXTERNAL ports: - number: 8848 name: http resolution: DNSサービスエントリを適用します:
kubectl apply -f external-nacos-svc.yamlLua ベースの EnvoyFilter 用に
external-envoyfilter.yamlという名前のファイルを作成します:apiVersion: networking.istio.io/v1alpha3 kind: EnvoyFilter metadata: labels: provider: "asm" asm-system: "true" name: nacos-subscribe-lua namespace: istio-system spec: configPatches: - applyTo: HTTP_FILTER match: proxy: proxyVersion: "^1.*" context: SIDECAR_OUTBOUND listener: portNumber: 8848 filterChain: filter: name: "envoy.filters.network.http_connection_manager" subFilter: name: "envoy.filters.http.router" patch: operation: INSERT_BEFORE value: name: envoy.lua typed_config: "@type": "type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua" inlineCode: | -- copyright: ASM (Alibaba Cloud ServiceMesh) function envoy_on_request(request_handle) local request_headers = request_handle:headers() local path = request_headers:get(":path") if string.match(path,"^/nacos/v1/ns/instance/list") then local servicename = string.gsub(path,".*&serviceName.*40([%w.\\_\\-]+)&.*","%1") request_handle:streamInfo():dynamicMetadata():set("context", "request.path", path) request_handle:streamInfo():dynamicMetadata():set("context", "request.servicename", servicename) request_handle:logInfo("subscribe for serviceName: " .. servicename) else request_handle:streamInfo():dynamicMetadata():set("context", "request.path", "") end end function envoy_on_response(response_handle) local request_path = response_handle:streamInfo():dynamicMetadata():get("context")["request.path"] if request_path == "" then return end local servicename = response_handle:streamInfo():dynamicMetadata():get("context")["request.servicename"] response_handle:logInfo("modified response ip to serviceName:" .. servicename) local bodyObject = response_handle:body(true) local body= bodyObject:getBytes(0,bodyObject:length()) body = string.gsub(body,"%s+","") body = string.gsub(body,"(ip\":\")(%d+.%d+.%d+.%d+)","%1"..servicename) response_handle:body():setBytes(body) endEnvoyFilter を適用します:
kubectl apply -f external-envoyfilter.yaml
ステップ 2:Spring Cloud サービスのデプロイ
ステップ 1 の EnvoyFilter は、サービスをデプロイする前に適用してください。フィルターは、サービス登録プロセスをインターセプトするために、最初から配置されている必要があります。サービスがすでにデプロイされている場合は、それらのデプロイメントでローリングアップデートをトリガーしてください。
各 Spring Cloud サービスには、クラスター IP アドレスを持つ Kubernetes サービスリソースが必要です。
kubectl を ACK データプレーンに接続します。詳細については、「クラスターの kubeconfig ファイルの取得」をご参照ください。
デモサービスをデプロイします。
<your-nacos-endpoint>を、ご利用の MSE Nacos レジストリまたは自己管理の Nacos レジストリのエンドポイントに置き換えてください。# Nacos レジストリエンドポイントを設定します (VPC エンドポイントを推奨) export NACOS_ADDRESS=<your-nacos-endpoint> # デモのデプロイメントをダウンロードして適用します wget https://alibabacloudservicemesh.oss-cn-beijing.aliyuncs.com/asm-labs/springcloud/demo.yaml -O demo.yaml sed -e "s/NACOS_SERVER_CLUSTERIP/$NACOS_ADDRESS/g" demo.yaml | kubectl apply -f -すべての Pod が 2/2 のコンテナ (アプリケーション + サイドカー) で実行されていることを確認します。期待される出力:READY 列の
2/2は、アプリケーションコンテナと Envoy サイドカープロキシの両方が実行中であることを示します。kubectl get podsconsumer-bdd464654-jn8q7 2/2 Running 0 25h provider-v1-66bc67fb6d-46pgl 2/2 Running 0 25h provider-v2-76568c45f6-85z87 2/2 Running 0 25h
ステップ 3:Istio ゲートウェイと仮想サービスの作成
Istio ゲートウェイ用に
test-gateway.yamlという名前のファイルを作成します:apiVersion: networking.istio.io/v1alpha3 kind: Gateway metadata: name: test-gateway spec: selector: istio: ingressgateway servers: - port: number: 80 name: http protocol: HTTP hosts: - "*"kubectl を ASM コントロールプレーンに接続し、ゲートウェイを適用します:
kubectl apply -f test-gateway.yaml受信トラフィックをコンシューマーにルーティングする仮想サービス用に
consumer.yamlという名前のファイルを作成します:apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: consumer spec: hosts: - "*" gateways: - test-gateway http: - match: - uri: prefix: / route: - destination: host: consumer.default.svc.cluster.local port: number: 8080仮想サービスを適用します:
kubectl apply -f consumer.yaml
ステップ 4:トラフィック管理の検証
このステップでは、ASM が Spring Cloud のトラフィックを制御していることを確認します。まず、ルーティングルールなしでのデフォルトのラウンドロビン動作を観察し、次に Istio のルーティングルールを適用して変更を検証します。
デフォルトの動作の観察 (ルーティングルール適用前)
イングレスゲートウェイの IP アドレスを取得します:
ASM コンソールにログインします。
左側のナビゲーションウィンドウで、[Service Mesh] > [メッシュ管理] を選択します。
ASM インスタンス名をクリックし、[ASM ゲートウェイ] > [Ingress ゲートウェイ] を選択します。
「サービスアドレス」を [Ingress Gateway] ページでご確認ください。
コンシューマーサービスに複数回リクエストを送信します。応答は V1 と V2 の間でラウンドロビン方式で交互に返されます。これにより、コンシューマーが Nacos を通じて両方のプロバイダーバージョンを検出し、トラフィックを均等に分散していることが確認できます。この時点では、Istio のルーティングルールはまだ有効ではありません。
curl <ingress-gateway-ip>/echo/worldHello Nacos Discovery From v1world Hello Nacos Discovery From v2world Hello Nacos Discovery From v1world Hello Nacos Discovery From v2world
ルーティングルールの適用 (適用後)
バージョンベースのサブセットを持つ宛先ルールを定義するために、
service-provider.yamlという名前のファイルを作成します:apiVersion: networking.istio.io/v1alpha3 kind: DestinationRule metadata: name: service-provider spec: host: service-provider subsets: - name: v1 labels: label: v1 - name: v2 labels: label: v2宛先ルールを適用します:
kubectl apply -f service-provider.yaml/echo/helloへのリクエストを V1 に、それ以外のすべてのリクエストを V2 にルーティングする仮想サービスを定義するために、service-provider-vs.yamlという名前のファイルを作成します:apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: service-provider spec: hosts: - service-provider http: - name: "hello-v1" match: - uri: prefix: "/echo/hello" route: - destination: host: service-provider subset: v1 - name: "default" route: - destination: host: service-provider subset: v2仮想サービスを適用します:
kubectl apply -f service-provider-vs.yamlルーティングルールをテストします。すべての応答が V1 からのみ返されるようになります。これを先ほど観察したラウンドロビン動作と比較してください。
/echo/helloへのリクエストは V1 にのみルーティングされ、それ以外のすべてのリクエストは V2 にルーティングされるようになります。Istio CRD が Spring Cloud のトラフィックルーティングを引き継いだことが確認でき、ASM がサービスを管理していることが証明されます。curl <ingress-gateway-ip>/echo/helloHello Nacos Discovery From v1hello Hello Nacos Discovery From v1hello
よくある質問
トラフィックがメッシュにインターセプトされない
レジストリのポートまたは IP アドレスに対してトラフィックブロッキングが有効になっているかどうかを確認してください:
メソッド 1 (逆引き DNS):Pod の IP アドレスをブロックする必要があります。EnvoyFilter の
pod_cidrsの値が、ご利用の ACK クラスターの正しい Pod CIDR ブロックをカバーしていることを確認してください。メソッド 2 (Lua フィルター):Nacos サーバーの IP アドレスとクラスター IP アドレスをブロックする必要があります。
サービスが正しく登録されない
これは通常、サービスが開始される前に EnvoyFilter が配置されていなかった場合に発生します。フィルターは、登録プロセスを最初からインターセプトする必要があります。影響を受けるデプロイメントを再起動してください:
kubectl rollout restart deployment <deployment-name>また、各 Spring Cloud サービスに対応する、クラスター IP アドレスを持つ Kubernetes サービスリソースが存在することも確認してください。
ルーティングルールが有効にならない
一般的な原因は 2 つあります:
Nacos クライアント SDK のバージョン (メソッド 2 のみ):メソッド 2 では、2.0 より前の Nacos クライアント SDK が必要です。バージョン 2.0 以降は HTTP の代わりに gRPC を使用するため、Lua フィルターとは互換性がありません。Nacos クライアント SDK が 2.0 以降の場合は、メソッド 1 に切り替えてください。メソッド 1 はすべての Nacos バージョンで動作します。
サイドカーのバージョンが古い:サイドカーのイメージバージョンが 1.13.4.32 より前の場合、コントロールプレーンのアップグレード後にデータプレーンが更新されていない可能性があります。影響を受けるデプロイメントを再起動して、最新のサイドカーバージョンを取得してください。