微服务提供了一些技术来实现对微服务的流量的管理,其中最典型的就是对流量进行拆分和转发。
具体体现在金丝雀发布(灰度发布)、ABTesting 以及流量染色 等策略方案上。
云原生基础场景下,如果想要实现流控和调度,需要具备以下几个条件:
所以,流控调度的本质上是通过在流量中携带一些特征(如流量的请求的Header、Cookies、queryParams等),而Mesh会根据这些请求的特征进行路由匹配,转发到对应的带有某些特征的服务实例上。
未匹配成功的流量则走到默认版本或者给定的具体版本中,从而实现多个版本和跟默认版本的业务隔离的目标。这种模式下,实现 灰度发布、ABTesting 以及流量染色 都是很方便的。
这边以Istio 实现的 Service-Mesh为案例
基于上述的策略模型,如果你想配置如下:请求的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 不匹配条件的流量路由到对应的服务上......
-
云原生基础平台上的服务遵循如下层级结构,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
-
规则下发之后,envoy存储在本地,当流量出去的时候,outbound 那边会做一个判断。
如果是header中带上 username = brand 或者 departname = hr ,流量转发到带有v1 标签的pod中,
否则流量转发到带有default标签的pod中。
丰富的流量管理策略为我们系统的稳定性,以及流量的多样化(金丝雀发布、ABTesting、分级扩散流量、流量染色)使用提供了保证。