ASM支持通过TrafficLabel CRD设置流量标签,然后根据流量标签将流量路由到不同的工作负载。本文介绍流量标签和标签路由的功能。
背景信息
流量打标又称作流量染色,指对符合一定流量特征的请求打上具体的染色标记。Istio通过透明拦截的方式劫持了应用流量,基于此技术背景,Sidecar可以对应用流量进行染色标记。
ASM商业版(专业版)扩展了一个新的TrafficLabel CRD ,通过该CRD来定义具体的流量染色逻辑,实现命名空间、工作负载及接口级别的流量打标。
注意事项
仅ASM商业版(专业版)v1.10.5.40及以上版本支持流量打标和标签路由功能。
如何对工作负载进行流量打标
方式一:按照命名空间进行流量打标
对命名空间下的所有应用进行流量打标。
- 通过kubectl连接ASM实例。
- 使用以下内容,创建example1.yaml。
apiVersion: istio.alibabacloud.com/v1beta1
kind: TrafficLabel
metadata:
name: example1
namespace: default
spec:
rules:
- labels:
- name: userdefinelabel1
valueFrom:
- $getContext(x-request-id)
- $localLabel
attachTo:
- opentracing
# 表示生效的协议,空为都不生效,*为都生效。
protocols: "*"
hosts: # 表示生效的服务。
- "*"
参数 |
描述 |
namespace |
该CRD生效的命名空间。 |
labels参数下name |
标签名称。 |
labels参数下valueFrom |
标签值,取值:
说明 valueFrom的参数值采用自然顺序的优先级,例如以上配置表示优先从getContext(x-request-id)获取标签值,当通过getContext变量获取不到才会从localLabel变量获取标签值。
- getContext(x-request-id):从流量的上下文获取标签值。
- localLabel:从工作负载的业务Pod标签
ASM_TRAFFIC_TAG 获取标签值。
|
attachTo |
取值为opentracing,对应HTTP或GRPC协议,意味着会将该流量标识添加到header下。
|
getContext(xxx)和localLabel两个变量详细说明如下:
- getContext(x-request-id)
getContext(x-request-id)是个函数型变量,标明流量颜色需要从流量的上下文中获取,其中x-request-id为该函数参数,指代Trace ID。不同的Trace系统采用的Trace
ID不同。
说明 getContext仅针对Sidecar生效。
Sidecar包含入口和出口两种类型的流量,流量打标其实指的是对出口流量进行打标。

ASM商业版(专业版)的Sidecar默认试图通过x-asm-prefer-tag header从入口流量中获取流量tag,并以Trace ID为key记录到上下文
map<traceId, tag>
中。当业务容器发起的出口请求时,Sidecar会通过Trace ID查找上下文map。若找到关联tag,则Sidecar会附带x-asm-prefer-tag header(默认)以及TrafficLabel
CRD定义的标签名userdefinelabel1。
说明 业务应用采用不同的Trace系统则会有不同Trace ID。更多信息,请参见
Tracing。
若不定义getContext函数下的参数,Sidecar默认采用x-request-id为Trace ID。Trace ID需要业务应用进行Header propagation或Context propagation。若Header
Propagation逻辑缺失,则出口流量会因为找不到关联的Trace ID key,Sidecar将无法从map<traceId,tag>
找到对应的流量tag。
若业务应用有对接Trace系统,则Trace SDK会帮助业务代码进行Header propagation或Context propagation,例如采用接入ARMS进行trace。若业务有对接ARMS Prometheus,则只需要在TrafficLabel CRD中修改valueFrom为getContext(x-b3-traceid),其中参数x-b3-traceid为Zipkin系统的Trace header。
- localLabel
localLabel是从Sidecar对应的业务POD标签
ASM_TRAFFIC_TAG获取流量标识,并对出口流量打标。以下工作负载定义了
ASM_TRAFFIC_TAG为
test。
apiVersion: apps/v1
kind: Deployment
metadata:
name: productpage-v1
labels:
app: productpage
version: v1
spec:
replicas: 1
selector:
matchLabels:
app: productpage
version: v1
template:
metadata:
annotations:
sidecar.istio.io/logLevel: debug
labels:
app: productpage
version: v1
ASM_TRAFFIC_TAG: test
spec:
serviceAccountName: bookinfo-productpage
containers:
- name: productpage
image: docker.io/istio/examples-bookinfo-productpage-v1:1.16.2
imagePullPolicy: IfNotPresent
ports:
- containerPort: 9080
volumeMounts:
- name: tmp
mountPath: /tmp
volumes:
- name: tmp
emptyDir: {}
- 执行以下命令,使CRD生效。
kubectl apply -f example1.yaml
方式二:按照工作负载进行流量打标
对某个命名空间下某个应用进行流量打标。
- 通过kubectl连接ASM实例。
- 使用以下内容,创建example2.yaml。
apiVersion: istio.alibabacloud.com/v1beta1
kind: TrafficLabel
metadata:
name: example2
namespace: workshop
spec:
workloadSelector:
labels:
app: test
rules:
- labels:
- name: userdefinelabel1
valueFrom:
- $localLabel
- $getContext(x-request-id)
attachTo:
- opentracing
protocols: "*"
hosts:
- "*"
参数 |
描述 |
namespace |
该CRD生效的命名空间。 |
labels参数下name |
标签名称。 |
labels参数下valueFrom |
标签值,取值:
说明 valueFrom具有优先级,以上配置表示优先从getContext(x-request-id)获取标签值,当通过getContext变量获取不到才会从localLabel变量获取标签值。
- getContext(x-request-id):从流量的上下文获取标签值。
- localLabel:从工作负载的业务Pod标签
ASM_TRAFFIC_TAG 获取标签值。
|
workloadSelector参数下的app |
匹配工作负载的标签,例如本文的CRD只作用于带有test标签的工作负载。 |
attachTo |
取值为opentracing,对应HTTP或GRPC协议,意味着会将该流量标识添加到header下。
|
- 执行以下命令,使CRD生效。
kubectl apply -f example2.yaml
方式三:按照接口进行流量打标
对某个命名空间下某个应用接口进行流量打标。
- 通过kubectl连接ASM实例。
- 使用以下内容,创建example3.yaml。
apiVersion: istio.alibabacloud.com/v1beta1
kind: TrafficLabel
metadata:
name: example3
namespace: workshop
spec:
workloadSelector:
labels:
app: test
rules:
- match:
- headers:
end-user: "jason"
uri:
prefix: "/test"
labels:
- name: userdefinelabel1
valueFrom:
- $getContext(x-b3-traceid)
attachTo:
- opentracing
protocols: "*"
hosts:
- "*"
参数 |
描述 |
namespace |
该CRD生效的命名空间。 |
workloadSelector参数下的app |
匹配工作负载的标签,例如本文的CRD只作用于带有app: test 标签的工作负载。
|
match参数下headers |
请求头,本文设置请求头为jason用户 。
|
match参数下prefix |
请求URL,描述特定接口请求,本文设置为带有/test的请求URL。
|
labels参数下name |
标签名称。 |
labels参数下valueFrom |
标签值,取值:
说明 valueFrom具有优先级,以上配置表示优先从getContext(x-request-id)获取标签值,当通过getContext变量获取不到才会从localLabel变量获取标签值。
- getContext(x-request-id):从流量的上下文获取标签值。
- localLabel:从工作负载的业务Pod标签
ASM_TRAFFIC_TAG 获取标签值。
|
attachTo |
取值为opentracing,对应HTTP或GRPC协议,意味着会将该流量标识添加到header下。
|
- 执行以下命令,使CRD生效。
kubectl apply -f example3.yaml
基于流量标签进行标签路由
通过TrafficLabel定义了流量标签userdefinelabel1,其取值为test1、test2、test3等,您还需要创建DestinationRule和VirtualService,将流量根据标签路由到对应工作负载。
- 使用以下内容,创建example4.yaml。
使用以下内容将productpage分为test1 、test2 、test3等组。
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: productpage
spec:
host: productpage
subsets:
- name: test1
labels:
version: test1
- name: test2
labels:
version: test2
- name: test3
labels:
version: test3
...
- name: testn
labels:
version: testn
- name: base
labels:
version: base
- 执行以下命令,创建DestinationRule。
kubectl apply -f example4.yaml
- 使用以下内容,创建example5.yaml。
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: example-app
namespace: default
spec:
hosts:
- example
http:
- match:
- headers:
userdefinelabel1:
exact: test1
route:
- destination:
host: example
subset: test1
- match:
- headers:
userdefinelabel1:
exact: test2
route:
- destination:
host: example
subset: test2
- match:
- headers:
userdefinelabel1:
exact: test3
route:
- destination:
host: example
subset: test3
- route:
- destination:
host: example
subset: base
headers和subset决定了将流量根据标签路由到对应工作负载,例如本文将带有值为test1,名称为userdefinelabel1的标签的流量路由到test1组别的工作负载。参数解释如下:
参数 |
描述 |
headers参数下userdefinelabel1 |
流量标签名称。 |
headers参数下exact |
流量标签值。 |
subset |
路由到的目标工作负载的组别。 |
- 执行以下命令,创建VirtualService。
kubectl apply -f example5.yaml
其他操作:简化VirtualService变量配置方式
若工作负载的版本有很多个的时候,VirtualService配置会比较臃肿,您可以使用以下内容简化VirtualService变量配置方式,并且对流量降级。
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: example-app
namespace: default
spec:
hosts:
- example
http:
- route:
- destination:
host: example
subset: $userdefinelabel1
fallback:
case: noinstances|noavailabled
target:
host: example
subset: v1
其中
fallback
配置
spec
说明如下:
参数 |
描述 |
case |
以竖线(|)分隔的字符串,取值:
- noinstances:缺失实例
- noavailabled:后端实例不可用
- noisolationunit:后端分组不存在
|
target |
路由的目标服务。本文定义了当缺少实例或者实例不可用时,将流量理由到v1组别的工作负载。 |