微服務13:雲基礎場景下流量策略實現原理

2023-07-26 18:01:29

★微服務系列

微服務1:微服務及其演進史
微服務2:微服務全景架構
微服務3:微服務拆分策略
微服務4:服務註冊與發現
微服務5:服務註冊與發現(實踐篇)
微服務6:通訊之閘道器
微服務7:通訊之RPC
微服務8:通訊之RPC實踐篇(附原始碼)
微服務9:服務治理來保證高可用
微服務10:系統服務熔斷、限流
微服務11:熔斷、降級的Hystrix實現(附原始碼)
微服務12:流量策略

1 微服務的基本流量策略

微服務提供了一些技術來實現對微服務的流量的管理,其中最典型的就是對流量進行拆分和轉發。
具體體現在金絲雀釋出(灰度釋出)、ABTesting 以及流量染色 等策略方案上。

2 流量策略實現流控的本質

雲原生基礎場景下,如果想要實現流控和排程,需要具備以下幾個條件:

  • 請求的流量中,需要附帶某些特徵,如流量的請求的Header、Cookies、queryParams等 中帶有某些資訊。
  • 部署在kubernetes上的服務(svc)的範例(pod),打上版本標籤,如 label: default、label: version1、label:version2 等。
  • 在雲原生基礎元件(如 Service-Mesh平臺)上對相關的服務配上策略:當請求的流量帶有某些特徵(如header中帶有Dep=SO)時,流量路由到對應標籤(如 version = version1 )的服務範例Pod上。
  • 不符合條件的路由則預設走到預設版本中(如 version = default)。

所以,流控排程的本質上是通過在流量中攜帶一些特徵(如流量的請求的Header、Cookies、queryParams等),而Mesh會根據這些請求的特徵進行路由匹配,轉發到對應的帶有某些特徵的服務範例上。
未匹配成功的流量則走到預設版本或者給定的具體版本中,從而實現多個版本和跟預設版本的業務隔離的目標。這種模式下,實現 灰度釋出、ABTesting 以及流量染色 都是很方便的。

3 流量染色流轉的原理

這邊以Istio 實現的 Service-Mesh為案例

3.1 Istio支援的策略模型

基於上述的策略模型,如果你想設定如下:請求的header 帶有 username = brand 或者 departname = hr 的時候,將流量轉發到服務的v1版本,否著轉發到default版本。
則策略程式碼如下:

# 說明:VirtualService 流量染色,根據不同的條件將流量發往不同特徵的版本中,假設這邊有default、v1、v2 版本
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: test-service1-vs
spec:
  hosts:
  - test-service1  # 治理髮往test-service1服務的流量
  exportTo:
  - "."
  http:  # 加各種路由條件,比如匹配人員、部門進行路由
  - match  # 使用者匹配 brand,部門匹配 hr 部門時
    - headers:
        username:
          exact: brand
    - headers:
        departname:
          exact: hr
    route: 
      destination:
      # todo 匹配條件的流量路由到對應的服務上......
  - route: 
    - destination:
    # todo 不匹配條件的流量路由到對應的服務上......

3.2 Kubernetes中服務的部署模式

雲原生基礎平臺上的服務遵循如下層級結構,namespace對標應用,svc對標服務。

假設你給你的服務設定了多個版本,比如你釋出了default(預設版本)、v1版本。
檢查kubernetes的資訊會發現,service保持不變,這個命名為testsvc-admin-default的服務下,對應兩個deployment,兩個pod。

root@xxxxxxxxxxxxxx:~# kubectl -n testsvc-debug get deployments
NAME               READY   UP-TO-DATE   AVAILABLE   AGE
testsvc-admin-429mvh    1/1     1            1           18m
testsvc-admin-default   1/1     1            1           142m
root@xxxxxxxxxxxxxx:~# kubectl -n testsvc-debug get services
NAME               TYPE        CLUSTER-IP        EXTERNAL-IP   PORT(S)   AGE
testsvc-admin-default   ClusterIP   172.100.110.220   <none>        80/TCP    142m
root@xxxxxxxxxxxxxx:~# kubectl -n testsvc-debug get pods
NAME                                READY   STATUS    RESTARTS   AGE
testsvc-admin-429mvh-5b567969b4-nq4zp    2/2     Running   0          17m
testsvc-admin-default-85467f8f79-xzfgz   2/2     Running   0          23m

看看兩個deployment的資訊對比,labels中的app屬性一致,version屬性不一致。所以,服務按照同一個app定址,不同的version進行流量shift的方式進行。

root@xxxxxxxxxxxxxx:~# kubectl -n testsvc-debug get deployment testsvc-admin-default  -o yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  annotations:
    deployment.kubernetes.io/revision: "2"
  creationTimestamp: "2022-01-14T06:40:22Z"
  generation: 2
  labels:
    app: testsvc-admin-default
    appName: testsvc-admin
    appType: java
    projectName: testsvc-debug
    version: default
    workspaceName: SPACE_BASIC_SERVE  
  name: testsvc-admin-default
  namespace: testsvc-debug
  resourceVersion: "335716111"
  uid: 7531a9b3-53eb-475d-ae0b-75df957badb9

root@xxxxxxxxxxxxxx:~# kubectl -n testsvc-debug get deployment testsvc-admin-429mvh  -o yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  annotations:
    deployment.kubernetes.io/revision: "1"
  creationTimestamp: "2022-01-14T08:45:03Z"
  generation: 1
  labels:
    app: testsvc-admin-default
    appName: testsvc-admin
    appType: java
    projectName: testsvc-debug
    version: 429mvh
    workspaceName: SPACE_BASIC_SERVE
  name: testsvc-admin-429mvh
  namespace: testsvc-debug
  resourceVersion: "335719639"
  uid: 85c0e1f2-b56d-4afc-8c51-ccb887e420b6

現在,envoy的流轉規則有了,服務的特徵也有了,完整策略匹配程式碼如下:

# 說明:VirtualService 流量染色,根據不同的條件將流量發往不同特徵的版本中,假設這邊有default、v1、v2 版本
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: test-svc-vs
spec:
  hosts:
  - test-svc  # 治理髮往test-svc服務的流量
  exportTo:
  - "."
  http:  # 加各種路由條件,比如匹配人員、部門進行路由
  - match  # 使用者匹配 brand,部門匹配 hr 人事部時
    - headers:
        username:
          exact: brand
    - headers:
        departname:
          exact: hr
    route: 
      destination:
        host: test-svc
        subset: v1  # 匹配條件的流量路由到對應的服務的v1版本上
  - route: 
    - destination:
        host: test-svc  # 剩餘的流量走到default版本上
        subset: default

3.3 流量的解析和流轉

規則下發之後,envoy儲存在本地,當流量出去的時候,outbound 那邊會做一個判斷。
如果是header中帶上 username = brand 或者 departname = hr ,流量轉發到帶有v1 標籤的pod中,
否則流量轉發到帶有default標籤的pod中。

4 總結

豐富的流量管理策略為我們系統的穩定性,以及流量的多樣化(金絲雀釋出、ABTesting、分級擴散流量、流量染色)使用提供了保證。