流量标签TrafficLabel说明

在服务网格ASM中,流量标签(TrafficLabel)支持标记流量,以便您更细致地进行流量控制和管理。应用服务之间的流量请求被打上特定的标签后,可以被划分到不同的服务或者版本中。您可以根据标签来进行流量控制、熔断降级、限流等操作。ASM新增并扩展了流量标签TrafficLabel自定义资源CRD,并通过该CRD定义具体的流量标签逻辑,为命名空间和工作负载设置流量标签。本文介绍流量标签的配置说明、字段说明和配置示例。

配置说明

  • 若ASM实例版本为1.17及以上,TrafficLabel CRD支持使用apiVersion: istio.alibabacloud.com/v1。若您在ACK集群进行了TrafficLabel的相关配置,请将对应的TrafficLabel CRD中的apiVersion: istio.alibabacloud.com/v1beta1修改为apiVersion: istio.alibabacloud.com/v1,再重新进行部署。

    展开查看1.17版本TrafficLabel YAML示例

    apiVersion: istio.alibabacloud.com/v1
    kind: TrafficLabel
    metadata:
      name: example
      namespace: default
    spec:
      workloadSelector:
        labels:
          app: httpbin
      rules:
      - labels:
          - name: asm-labels-test-a
            valueFrom:
            - $getInboundRequestHeader(headerName)
            - $getExternalInboundRequestHeader(contextId, headerName) 
            - $getLocalOutboundRequestHeader(headerName)
            - $getLabel(labelName)  
  • 若ASM实例版本为1.17以下,建议您将版本升级到1.17及以上,或提交工单获取技术支持。

字段说明

ASM实例版本为1.17及以上的字段说明如下。

Spec

字段

类型

是否必选

说明

workloadSelector

WorkloadSelector

作用的工作负载范围。选择器决定在哪里应用该流量标签。

如果未设置,选择器将匹配当前命名空间下的所有工作负载。

rules

TrafficLabelRule[]

设置标签的规则定义。

WorkloadSelector

字段

类型

是否必选

说明

labels

map<string, string>

在工作负载上应用的流量标签。支持配置一个或多个标签。

TrafficLabelRule

字段

类型

是否必选

说明

labels

Label[]

需要设置的标签名称与值。

Label

字段

类型

是否必选

说明

name

string

标签名称。该名称需要符合HTTP请求头的命名规范。

valueFrom

string[]

标签值。取值采用自然顺序的优先级,优先从第一行获取标签值,当获取不到时才会从第二行获取标签值,以此类推。

更多信息,请参见valueFrom

valueFrom

valueFrom支持以下四种变量。您可以展开表格下方的折叠面板,查看变量的详细说明。

变量

支持的工作负载类型

$getInboundRequestHeader(headerName)

网关

$getExternalInboundRequestHeader(headerName, contextId)

Sidecar代理

$getLocalOutboundRequestHeader(headerName)

Sidecar代理

$getLabel(labelName)

网关或者Sidecar代理

展开查看$getInboundRequestHeader(headerName)详细说明

表示从进入网关的请求头中获取名称为headerName的标头值。该变量是一个函数型变量,需要从入口请求头中获取。参数headerName是指请求头的关键字Key。如果参数值为空,默认为x-asm-prefer-tag

如下图所示,入口网关会为出口请求中附加一个新请求头。该请求头的名称为流量标签TrafficLabel CRD中定义的标签名(例如userDefinedLabel),值为tagValue$getInboundRequestHeader(headerName)..png

说明

该变量仅对网关生效,对Sidecar代理不生效。

展开查看$getExternalInboundRequestHeader(headerName, contextId)详细说明

表示从进入Sidecar代理的请求中获取名称为headerName的标头值。该变量是一个函数型变量,需要从流量请求的上下文中获取。参数说明如下:

  • headerName:请求头的关键字Key。该参数为必填项,且值不能为空,例如x-asm-prefer-tag

  • contextId:一个贯穿整个调用链路的请求头字段,其值可配置为一个指定的入口请求头或Tracing系统中的Trace ID。该参数为必填项,且值不能为空。

Sidecar包含入口和出口两种类型的流量。流量打标的本质是对出口流量设置标签。默认情况下,Sidecar代理从入口请求头(名称为headerName)中获取对应的值,并以此作为流量打标的标签值tagValue$getExternalInboundRequestHeader(headerName, contextId)..png

为了将标签值tagValue附加到出口流量请求中,在Sidecar代理的内部逻辑中维持一个map<contextId, tagValue>contextId是一个贯穿整个调用链路的请求头字段,其值可配置为一个指定的入口请求头或使用x-request-id作为contextId

当业务容器发起出口请求时,Sidecar代理会通过contextId查找上下文Map。若找到关联tagValue,则Sidecar代理会为出口请求中附加两个新请求头:

  • 请求头名称为headerName,值为tagValue

  • 请求头名称为流量标签TrafficLabel CRD中定义的标签名(例如userDefinedLabel),值为tagValue

说明
  • 该变量仅对Sidecar代理生效,对网关不生效。

  • map<contextId, tagValue>存储在Envoy内存中,默认30秒过期。

  • 业务应用接入Trace系统时,TraceID会贯穿整个调用链路的请求,因此可以使用TraceID作为上述contextId。采用不同的Trace系统会有不同TraceID。更多信息,请参见Tracing

  • 虽然Istio代理能够自动发送Tracing Span信息,但是应用程序仍然需要传播相关的HTTP标头,以便在代理发送Span时,可以将Span正确地关联到单个跟踪中。具体操作,请参见在ASM中实现分布式跟踪

  • 若没有传播对应的HTTP标头,则出口流量无法关联的contextId。Sidecar代理将无法从map<contextId,tagValue>找到对应的流量标签值。

展开查看$getLocalOutboundRequestHeader(headerName)详细说明

表示从由应用服务发出至Sidecar代理的请求中获取名称为headerName的标头值。该变量是一个函数型变量,需要从入口请求头中获取。参数headerName表示请求头的关键字Key。您可以根据业务容器实际的请求头进行指定。

如下图所示,当注入Sidecar代理的业务容器发起出口请求时,Sidecar代理会为出口请求中附加一个新请求头。该请求头的名称为流量标签TrafficLabel CRD中定义的标签名(例如userDefinedLabel),值为tagValue$getLocalOutboundRequestHeader(headerName)..png

说明

该变量仅对Sidecar代理生效,对网关不生效。

展开查看$getLabel(labelName)详细说明

表示从网关Pod或Sidecar容器所属Pod的标签中获取名称为labelName的标签值,并将该值附加到出口流量上。如果labelName为空,默认从工作负载Pod上的标签ASM_TRAFFIC_TAG取值。

例如,以下工作负载定义ASM_TRAFFIC_TAG值为test,通过$getLabel(ASM_TRAFFIC_TAG)可以获取标签值为test

展开查看YAML示例

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: {}

配置示例

以下示例的ASM实例版本为1.17及以上。关于升级实例的具体操作,请参见升级ASM实例

示例一:按照工作负载进行流量打标签

通过定义workloadSelector根据标签选择对应的工作负载,可以实现对某个命名空间下的工作负载进行流量打标签。

  1. 部署bookinfo应用。具体操作,请参见在ASM实例关联的集群中部署应用

  2. 使用以下内容,创建productpage-trafficlabel.yaml文件。

    apiVersion: istio.alibabacloud.com/v1
    kind: TrafficLabel
    metadata:
      name: productpage
      namespace: default
    spec:
      workloadSelector:
        labels:
          app: productpage
      rules:
      - labels:
          - name: asm-labels-test-a
            valueFrom:
            - $getExternalInboundRequestHeader(header1, x-request-id)
            - $getLabel(header2)
  3. 执行以下命令,对productpage工作负载进行流量打标签。

     kubectl apply -n default  -f productpage-trafficlabel.yaml
  4. 执行以下命令,查看productpage工作负载对应的代理配置。

    kubectl exec -it -n default deploy/productpage-v1 -c istio-proxy -- curl localhost:15000/config_dump

    预期输出:

    {
                  "name": "com.aliyun.traffic_label",
                  "typed_config": {
                   "@type": "type.googleapis.com/envoy.config.filter.traffic_label.v3alpha.TrafficLabel",
                   
                  }
                 },

    在对应的Listener Config(type.googleapis.com/envoy.admin.v3.ListenersConfigDump)/dynamic_listeners下的type.googleapis.com/envoy.config.listener.v3.Listener/envoy.filters.network.http_connection_manager/http_filters,可以看到上述的filter配置内容,表明流量标签配置成功。

  5. 执行以下命令,查看其他工作负载(例如details Pod)对应的代理配置。

    kubectl exec -it -n default deploy/details-v1 -c istio-proxy -- curl localhost:15000/config_dump |grep type.googleapis.com/envoy.config.filter.traffic_label.v3alpha.TrafficLabel

    返回结果为空,表明没有相关的filter,符合预期。

示例二:按照命名空间进行流量打标签

如果不定义workloadSelector字段,将对命名空间下所有的工作负载进行流量打标签。以下示例将对命名空间default下的所有工作负载进行流量打标签。

  1. 使用以下内容,创建all-workload-for-ns-trafficlabel.yaml文件。

    apiVersion: istio.alibabacloud.com/v1
    kind: TrafficLabel
    metadata:
      name: all-workload-for-ns
      namespace: default
    spec:
      rules:
      - labels:
          - name: asm-labels-test-b
            valueFrom:
            - $getExternalInboundRequestHeader(header1, x-request-id)
            - $getLabel(header2)
  2. 执行以下命令,对命名空间default下的所有工作负载进行流量打标签。

     kubectl apply -n default -f all-workload-for-ns-trafficlabel.yaml

  3. 执行以下命令,查看工作负载(例如details Pod)对应的代理的配置。

    kubectl exec -it -n default deploy/details-v1 -c istio-proxy -- curl localhost:15000/config_dump |grep type.googleapis.com/envoy.config.filter.traffic_label.v3alpha.TrafficLabel

    预期输出:

     "@type": "type.googleapis.com/envoy.config.filter.traffic_label.v3alpha.TrafficLabel",

    输出如上内容,表明流量标签配置成功。