您可以將Spring Cloud業務應用接入ASM,從而可以使用雲原生化的服務治理能力,不需要業務做任何代碼修改,即可管理Spring Cloud商務服務。本文介紹如何使用ASM管理Spring Cloud服務。
前提條件
已建立ASM企業版或旗艦版執行個體。具體操作,請參見建立ASM執行個體。
已建立Kubernetes託管版叢集。具體操作,請參見建立ACK託管叢集。
已添加叢集到ASM執行個體。具體操作,請參見添加叢集到ASM執行個體。
已部署入口網關。具體操作,請參見建立入口網關。
背景資訊
Spring Cloud是一個標準,有不同的實現,例如Spring Cloud Netflix、Spring Cloud Alibaba、Spring Cloud Consul 等。不同的Spring Cloud實現對於ASM來說核心區別主要在於採用了不同的服務發現,ASM針對這些不同的Spring Cloud版本遷移支援列表如下:
Spring Cloud版本 | 服務發現 | 遷移支援 (零代碼修改) |
Spring Cloud Alibaba | 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 |
Demo介紹
本文以Spring Cloud+Nacos為例進行說明,Demo範例程式碼可以通過此nacos-example下載。
Spring Cloud服務包含Consumer服務和Provider服務,其中Provider有v1和v2兩個版本,並且都註冊到Nacos註冊中心。Consumer從Nacos註冊中心同步Provider服務地址進行負載平衡發起請求,其中Consumer暴露一個8080連接埠,提供了一個echo介面,對應邏輯是將請求轉寄給Provider,並輸出Provider返回的結果,不同的Provider版本返回結果不同:
Provider v1版本收到echo請求會返回
Hello Nacos Discovery From v1xxx
。Provider v2版本收到echo請求會返回
Hello Nacos Discovery From v2xxx
。
其中返回結果中.xxx
為echo介面對應的具體參數,例如請求/echo/world發送到Provider v1版本,則會返回Hello Nacos Discovery From v1world
。
若Consumer、Provider不開啟Mesh能力,即業務POD不注入Sidecar的情況下,請求可以正常訪問,但缺少Istio提供的相關服務治理能力,本文通過以下步驟,驗證ASM管理Spring Cloud服務是否成功。
步驟一:ASM控制面開啟SpringCloud能力支援
方式一:適用於所有SpringCloud版本和註冊中心
ASM執行個體需為1.13.4.32及以上版本。
使用kubectl串連到控制面叢集。具體操作,請參見通過控制面kubectl訪問Istio資源。
在ASM叢集下建立EnvoyFilter。
使用以下內容,建立any-spring-cloud-support.yaml。
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: # reverse_dns filter specification 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"
YAML中的參數請您根據實際業務進行修改,部分參數說明如下:
portNumber
:SpringCloud服務的連接埠。若連接埠不統一,可以刪除該參數不進行配置;若連接埠可以收斂,可以配置多個該EnvoyFilter(每個EnvoyFilter綁定一個具體portNumber
。)pod_cidrs
:ACK或ACK Serverless叢集的Pod CIDR。您可以登入Container Service管理主控台,在叢集資訊頁面的叢集資源頁簽,查看Virtual Private Cloud絡 VPC下虛擬交換器對應的CIDR進行配置。
執行以下命令,對目標服務開啟
com.aliyun.reverse_dns filter
。kubectl apply -f any-spring-cloud-support.yaml
方式二:僅適用於Nacos註冊中心
使用kubectl串連到控制面叢集。具體操作,請參見通過控制面kubectl訪問Istio資源。
建立ServiceEntry。
使用以下內容,建立external-nacos-svc.yaml。
kind: ServiceEntry metadata: name: external-nacos-svc spec: hosts: - "NACOS_SERVER_HOST" ## 需要替換為您的Nacos Server HOST,例如"mse-xxx-p.nacos-ans.mse.aliyuncs.com"。 location: MESH_EXTERNAL ports: - number: 8848 name: http resolution: DNS
上述YAML中,
8848
為Nacos的預設連接埠。如果您是自建的Nacos Server且對連接埠有修改,則number
參數也需要對應修改。執行以下命令,建立ServiceEntry。
kubectl apply -f external-nacos-svc.yaml
建立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: # The first patch adds the lua filter to the listener/http connection manager. - 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: # lua filter specification 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() -- /nacos/v1/ns/instance/list?healthyOnly=false&namespaceId=public&clientIP=10.122.63.81&serviceName=DEFAULT_GROUP%40%40service-provider&udpPort=53174&encoding=UTF-8 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) end
執行以下命令,建立EnvoyFilter。
kubectl apply -f external-envoyfilter.yaml
步驟二:在ACK部署Spring Cloud服務
因為需要攔截註冊流程,EnvoyFilter需要先於業務工作負載Deployment之前建立。若某些業務Deployment先於EnvoyFilter建立,您需要變換該業務Deployment。
商務服務需要建立Kubernetes Service資源,並且需要有Cluster IP。
使用kubectl串連到資料面叢集。具體操作,請參見擷取叢集KubeConfig並通過kubectl工具串連叢集。
執行以下命令,部署Spring Cloud服務。
export NACOS_ADDRESS=xxxx # xxxx為MSE或自建的Nacos地址,建議使用VPC內網地址。 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 -
執行以下命令,查看Spring Cloud服務。
kubectl get pods
預期輸出:
consumer-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
步驟三:建立網關規則和虛擬服務
建立網關規則。
使用以下內容,建立test-gateway.yaml。
apiVersion: networking.istio.io/v1alpha3 kind: Gateway metadata: name: test-gateway spec: selector: istio: ingressgateway # use istio default controller servers: - port: number: 80 name: http protocol: HTTP hosts: - "*"
使用ASM的kubeconfig,執行以下命令,建立網關規則。
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
步驟四:驗證ASM管理Spring Cloud服務是否成功
查看Ingress Gateway的IP地址。
登入ASM控制台,在左側導覽列,選擇 。
在網格管理頁面,單擊目標執行個體名稱,然後在左側導覽列,選擇 。
在入口網關頁面,查看Ingress Gateway的服務地址。
執行以下命令,通過Ingress Gateway向Spring Cloud Consumer服務發起請求。
curl <Ingress Gateway的IP地址>/echo/world
預期輸出:
Hello Nacos Discovery From v1world Hello Nacos Discovery From v2world Hello Nacos Discovery From v1world Hello Nacos Discovery From v2world
可以看到Provider預設在v1、v2版本間輪詢訪問。
建立目標規則和虛擬服務。
使用以下內容,建立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
使用以下內容,建立service-provider1.yaml。
以下虛擬服務定義了/echo/hello的請求將被路由到Provider v1版本,其他請求將被路由到Provider v2版本。
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-provider1.yaml
執行以下命令,向Spring Cloud Consumer服務發起請求。
curl <Ingress Gateway的IP地址>/echo/hello
預期輸出:
Hello Nacos Discovery From v1hello Hello Nacos Discovery From v1hello
可以看到
/echo/hello
請求都被路由到Provider v1版本,其他請求則會路由到Provider v2版本。說明Spring Cloud流量被Istio接管,並可以支援使用Istio方式配置相關路由規則,管理Spring Cloud服務成功。
FAQ
為什麼部署的SpringCloud商務服務不生效?
檢查是否開啟了針對Nacos連接埠或者IP的流量攔截。
若採用reverse_dns方式,需要攔截Pod IP。
若採用Lua指令碼方式,需要攔截Nacos Server IP和Cluster IP。
因為需要攔截註冊流程,EnvoyFilter需要先於業務工作負載Deployment之前建立。若某些業務Deployment先於EnvoyFilter建立,您需要變換該業務Deployment。
檢查商務服務是否建立了Kubernetes Service資源,並且Type類型為Cluster IP。
查看ASM控制面開啟SpringCloud能力的方式。
檢查相關服務的Sidecar版本,若Sidecar鏡像版本低於v1.13.4.32,可能存在僅升級了ASM執行個體控制面,未升級資料面的情況,需要將對應服務的Deployment進行變換。