深入剖析全鏈路灰度技術內(nèi)幕(3)
從 0 到 1 實踐全鏈路灰度
Cloud Native
前提條件
必備的資源列表
- 已擁有一個 MSE 云原生網(wǎng)關
- 已擁有一個 MSE Nacos 注冊中心
- 已擁有一個 ACK 運維集群
- 已開通 MSE 微服務治理專業(yè)版
部署 Demo 應用程序
將下面的文件保存到 ingress-gray.yaml 中,并執(zhí)行 kubectl apply -f ingress-gray.yaml 以部署應用,這里我們將要部署 A,B,C 三個應用,A 和 C 應用分別部署一個基線版本和一個灰度版本,B 應用部署一個基線版本。
-
全鏈路灰度能力是與注冊中心無關的,本文用例暫以 MSE Nacos 作為注冊中心,所以需要將 spring.cloud.nacos.discovery.server-addr 換成業(yè)務自己的 Nacos 注冊中心地址
- 接入云原生網(wǎng)關的服務,如果需要使用灰度發(fā)布,需要在發(fā)布服務時在元數(shù)據(jù)信息增加版本標。在我們的例子,服務 A 是需要暴露給網(wǎng)關,所以發(fā)布時為基線版本添加spring.cloud.nacos.discovery.metadata.version=base,為灰度版本添加 spring.cloud.nacos.discovery.metadata.version=gray。
# A 應用 base 版本---apiVersion: apps/v1kind: Deploymentmetadata: labels: app: spring-cloud-a name: spring-cloud-aspec: replicas: 2 selector: matchLabels: app: spring-cloud-a template: metadata: annotations: msePilotCreateAppName: spring-cloud-a labels: app: spring-cloud-a spec: containers: env: name: LANG value: C.UTF-8 name: JAVA_HOME value: /usr/lib/jvm/java-1.8-openjdk/jre name: spring.cloud.nacos.discovery.server-addr value: mse-455e0c20-nacos-ans.mse.aliyuncs.com:8848 name: spring.cloud.nacos.discovery.metadata.version value: base image: registry.cn-shanghai.aliyuncs.com/yizhan/spring-cloud-a:0.1-SNAPSHOT imagePullPolicy: Always name: spring-cloud-a ports: containerPort: 20001 protocol: TCP resources: requests: cpu: 250m memory: 512Mi # A 應用 gray 版本 apiVersion: apps/v1kind: Deploymentmetadata: labels: app: spring-cloud-a-new name: spring-cloud-a-newspec: replicas: 2 selector: matchLabels: app: spring-cloud-a-new strategy: template: metadata: annotations: gray : msePilotCreateAppName: spring-cloud-a labels: app: spring-cloud-a-new spec: containers: env: name: LANG value: C.UTF-8 name: JAVA_HOME value: /usr/lib/jvm/java-1.8-openjdk/jre name: profiler.micro.service.tag.trace.enable value: "true" name: spring.cloud.nacos.discovery.server-addr value: mse-455e0c20-nacos-ans.mse.aliyuncs.com:8848 name: spring.cloud.nacos.discovery.metadata.version value: gray image: registry.cn-shanghai.aliyuncs.com/yizhan/spring-cloud-a:0.1-SNAPSHOT imagePullPolicy: Always name: spring-cloud-a-new ports: containerPort: 20001 protocol: TCP resources: requests: cpu: 250m memory: 512Mi # B 應用 base 版本---apiVersion: apps/v1kind: Deploymentmetadata: labels: app: spring-cloud-b name: spring-cloud-bspec: replicas: 2 selector: matchLabels: app: spring-cloud-b strategy: template: metadata: annotations: msePilotCreateAppName: spring-cloud-b labels: app: spring-cloud-b spec: containers: env: name: LANG value: C.UTF-8 name: JAVA_HOME value: /usr/lib/jvm/java-1.8-openjdk/jre name: spring.cloud.nacos.discovery.server-addr value: mse-455e0c20-nacos-ans.mse.aliyuncs.com:8848 image: registry.cn-shanghai.aliyuncs.com/yizhan/spring-cloud-b:0.2-demo-SNAPSHOT imagePullPolicy: Always name: spring-cloud-b ports: containerPort: 8080 protocol: TCP resources: requests: cpu: 250m memory: 512Mi # C 應用 base 版本---apiVersion: apps/v1kind: Deploymentmetadata: labels: app: spring-cloud-c name: spring-cloud-cspec: replicas: 2 selector: matchLabels: app: spring-cloud-c template: metadata: annotations: msePilotCreateAppName: spring-cloud-c labels: app: spring-cloud-c spec: containers: env: name: LANG value: C.UTF-8 name: JAVA_HOME value: /usr/lib/jvm/java-1.8-openjdk/jre name: spring.cloud.nacos.discovery.server-addr value: mse-455e0c20-nacos-ans.mse.aliyuncs.com:8848 image: registry.cn-shanghai.aliyuncs.com/yizhan/spring-cloud-c:0.2-demo-SNAPSHOT imagePullPolicy: Always name: spring-cloud-c ports: containerPort: 8080 protocol: TCP resources: requests: cpu: 250m memory: 512Mi # C 應用 gray 版本---apiVersion: apps/v1kind: Deploymentmetadata: labels: app: spring-cloud-c-new name: spring-cloud-c-newspec: replicas: 2 selector: matchLabels: app: spring-cloud-c-new template: metadata: annotations: gray : msePilotCreateAppName: spring-cloud-c labels: app: spring-cloud-c-new spec: containers: env: name: LANG value: C.UTF-8 name: JAVA_HOME value: /usr/lib/jvm/java-1.8-openjdk/jre name: spring.cloud.nacos.discovery.server-addr value: mse-455e0c20-nacos-ans.mse.aliyuncs.com:8848 image: registry.cn-shanghai.aliyuncs.com/yizhan/spring-cloud-c:0.2-demo-SNAPSHOT imagePullPolicy: Always name: spring-cloud-c-new ports: containerPort: 8080 protocol: TCP resources: requests: cpu: 250m memory: 512Mi
完成云原生網(wǎng)關初步配置
第一步,為云原生網(wǎng)關添加 Nacos 服務來源,服務管理,來源管理,點擊創(chuàng)建來源,
選擇服務來源為 MSE Nacos,選擇服務 sc-A。
點擊服務 A 的策略配置,為入口服務 A 創(chuàng)建多版本,版本劃分依據(jù)服務注冊時所帶的元數(shù)據(jù)信息 version(注意,這里可以是任意可以區(qū)分服務版本的標簽值,取決于用戶注冊服務時所采用的元數(shù)據(jù)信息),創(chuàng)建以下兩個版本 base 和 gray。
路由配置
創(chuàng)建基線環(huán)境的路由匹配規(guī)則,關聯(lián)域名 base.example.com,路由到服務 sc-A 的 base 版本中。
創(chuàng)建灰度環(huán)境的路由匹配規(guī)則,關聯(lián)的域名與基線環(huán)境保持一致,注意此處增加了請求頭相關的配置,并且路由的目標服務為服務 sc-A 的 gray 版本。
這時,我們有了如下兩條路由規(guī)則,
此時,訪問 base.example.com 路由到基線環(huán)境
curl -H "Host: base.example.com" http://118.31.118.69/aA[172.21.240.105] -> B[172.21.240.106] -> C[172.21.240.46]
如何訪問灰度環(huán)境呢?只需要在請求中增加一個 header x-mse-tag: gray 即可。
curl -H "Host: base.example.com" -H "x-mse-tag: gray" http://118.31.118.69/aAgray[172.21.240.44] -> B[172.21.240.146] -> Cgray[172.21.240.147]
可以看到 云原生網(wǎng)關 將灰度流量路由到了 A 和 C 的灰度版本,由于B沒有指定的灰度版本,所以流量自動回退到基線版本。
3
分析
從上面可以看出,我們只需要開通 MSE 微服務治理專業(yè)版,在云原生網(wǎng)關配置入口服務的路由規(guī)則,并且對入口流量進行灰度染色,即可滿足我們對 A 和 C 全鏈路灰度的要求。另外還有一個很重要的點是,業(yè)務需要自行對節(jié)點打標并對入口服務開啟鏈路傳遞。為 Pod 模板的 Annotations添加 alicloud.service.tag 鍵值對完成節(jié)點打標,Java Agent 會在業(yè)務向注冊中心時登記節(jié)點時自動為其添加這個元數(shù)據(jù)信息,同時需要為入口服務的業(yè)務容器添加環(huán)境變量 profiler.micro.service.tag.trace.enable=true 開啟鏈路傳遞灰度標識。MSE 服務治理組件默認使用 x-mse-tag 來標識流量,并在整個調(diào)用鏈路中傳遞。
總結
Cloud Native
本文從單體架構向微服務架構演進過程中帶來的挑戰(zhàn)展開,著重對其子領域服務發(fā)布在單體架構和微服務架構體系下的形態(tài)進行分析,引出了分布式應用場景中特有的全鏈路灰度問題。針對業(yè)務對全鏈路能力的要求,介紹了基于物理環(huán)境隔離和基于邏輯環(huán)境隔離兩種方案,其中對基于邏輯環(huán)境隔離方案進行詳細分析,對涉及到的各個技術點也進行了很好的解釋,接著提出了三種基于邏輯環(huán)境隔離的落地方案,并進行了簡單的對比分析,最后引出了阿里云 MSE 云原生、MSE 服務治理和服務網(wǎng)格 ASM 是如何提供不限于全鏈路灰度的流量治理能力。
# A 應用 base 版本---apiVersion: apps/v1kind: Deploymentmetadata: labels: app: spring-cloud-a name: spring-cloud-aspec: replicas: 2 selector: matchLabels: app: spring-cloud-a template: metadata: annotations: msePilotCreateAppName: spring-cloud-a labels: app: spring-cloud-a spec: containers: env: name: LANG value: C.UTF-8 name: JAVA_HOME value: /usr/lib/jvm/java-1.8-openjdk/jre name: spring.cloud.nacos.discovery.server-addr value: mse-455e0c20-nacos-ans.mse.aliyuncs.com:8848 name: spring.cloud.nacos.discovery.metadata.version value: base image: registry.cn-shanghai.aliyuncs.com/yizhan/spring-cloud-a:0.1-SNAPSHOT imagePullPolicy: Always name: spring-cloud-a ports: containerPort: 20001 protocol: TCP resources: requests: cpu: 250m memory: 512Mi # A 應用 gray 版本 apiVersion: apps/v1kind: Deploymentmetadata: labels: app: spring-cloud-a-new name: spring-cloud-a-newspec: replicas: 2 selector: matchLabels: app: spring-cloud-a-new strategy: template: metadata: annotations: gray : msePilotCreateAppName: spring-cloud-a labels: app: spring-cloud-a-new spec: containers: env: name: LANG value: C.UTF-8 name: JAVA_HOME value: /usr/lib/jvm/java-1.8-openjdk/jre name: profiler.micro.service.tag.trace.enable value: "true" name: spring.cloud.nacos.discovery.server-addr value: mse-455e0c20-nacos-ans.mse.aliyuncs.com:8848 name: spring.cloud.nacos.discovery.metadata.version value: gray image: registry.cn-shanghai.aliyuncs.com/yizhan/spring-cloud-a:0.1-SNAPSHOT imagePullPolicy: Always name: spring-cloud-a-new ports: containerPort: 20001 protocol: TCP resources: requests: cpu: 250m memory: 512Mi # B 應用 base 版本---apiVersion: apps/v1kind: Deploymentmetadata: labels: app: spring-cloud-b name: spring-cloud-bspec: replicas: 2 selector: matchLabels: app: spring-cloud-b strategy: template: metadata: annotations: msePilotCreateAppName: spring-cloud-b labels: app: spring-cloud-b spec: containers: env: name: LANG value: C.UTF-8 name: JAVA_HOME value: /usr/lib/jvm/java-1.8-openjdk/jre name: spring.cloud.nacos.discovery.server-addr value: mse-455e0c20-nacos-ans.mse.aliyuncs.com:8848 image: registry.cn-shanghai.aliyuncs.com/yizhan/spring-cloud-b:0.2-demo-SNAPSHOT imagePullPolicy: Always name: spring-cloud-b ports: containerPort: 8080 protocol: TCP resources: requests: cpu: 250m memory: 512Mi # C 應用 base 版本---apiVersion: apps/v1kind: Deploymentmetadata: labels: app: spring-cloud-c name: spring-cloud-cspec: replicas: 2 selector: matchLabels: app: spring-cloud-c template: metadata: annotations: msePilotCreateAppName: spring-cloud-c labels: app: spring-cloud-c spec: containers: env: name: LANG value: C.UTF-8 name: JAVA_HOME value: /usr/lib/jvm/java-1.8-openjdk/jre name: spring.cloud.nacos.discovery.server-addr value: mse-455e0c20-nacos-ans.mse.aliyuncs.com:8848 image: registry.cn-shanghai.aliyuncs.com/yizhan/spring-cloud-c:0.2-demo-SNAPSHOT imagePullPolicy: Always name: spring-cloud-c ports: containerPort: 8080 protocol: TCP resources: requests: cpu: 250m memory: 512Mi # C 應用 gray 版本---apiVersion: apps/v1kind: Deploymentmetadata: labels: app: spring-cloud-c-new name: spring-cloud-c-newspec: replicas: 2 selector: matchLabels: app: spring-cloud-c-new template: metadata: annotations: gray : msePilotCreateAppName: spring-cloud-c labels: app: spring-cloud-c-new spec: containers: env: name: LANG value: C.UTF-8 name: JAVA_HOME value: /usr/lib/jvm/java-1.8-openjdk/jre name: spring.cloud.nacos.discovery.server-addr value: mse-455e0c20-nacos-ans.mse.aliyuncs.com:8848 image: registry.cn-shanghai.aliyuncs.com/yizhan/spring-cloud-c:0.2-demo-SNAPSHOT imagePullPolicy: Always name: spring-cloud-c-new ports: containerPort: 8080 protocol: TCP resources: requests: cpu: 250m memory: 512Mi