流量標(biāo)簽TrafficLabel說(shuō)明
在服務(wù)網(wǎng)格ASM中,流量標(biāo)簽(TrafficLabel)支持標(biāo)記流量,以便您更細(xì)致地進(jìn)行流量控制和管理。應(yīng)用服務(wù)之間的流量請(qǐng)求被打上特定的標(biāo)簽后,可以被劃分到不同的服務(wù)或者版本中。您可以根據(jù)標(biāo)簽來(lái)進(jìn)行流量控制、熔斷降級(jí)、限流等操作。ASM新增并擴(kuò)展了流量標(biāo)簽TrafficLabel自定義資源CRD,并通過(guò)該CRD定義具體的流量標(biāo)簽邏輯,為命名空間和工作負(fù)載設(shè)置流量標(biāo)簽。本文介紹流量標(biāo)簽的配置說(shuō)明、字段說(shuō)明和配置示例。
配置說(shuō)明
若ASM實(shí)例版本為1.17及以上,TrafficLabel CRD支持使用
apiVersion: istio.alibabacloud.com/v1
。若您在ACK集群進(jìn)行了TrafficLabel的相關(guān)配置,請(qǐng)將對(duì)應(yīng)的TrafficLabel CRD中的apiVersion: istio.alibabacloud.com/v1beta1
修改為apiVersion: istio.alibabacloud.com/v1
,再重新進(jìn)行部署。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實(shí)例版本為1.17以下,建議您將版本升級(jí)到1.17及以上,或提交工單獲取技術(shù)支持。
字段說(shuō)明
ASM實(shí)例版本為1.17及以上的字段說(shuō)明如下。
Spec
字段 | 類型 | 是否必選 | 說(shuō)明 |
workloadSelector | 否 | 作用的工作負(fù)載范圍。選擇器決定在哪里應(yīng)用該流量標(biāo)簽。 如果未設(shè)置,選擇器將匹配當(dāng)前命名空間下的所有工作負(fù)載。 | |
rules | 是 | 設(shè)置標(biāo)簽的規(guī)則定義。 |
WorkloadSelector
字段 | 類型 | 是否必選 | 說(shuō)明 |
labels | map<string, string> | 否 | 在工作負(fù)載上應(yīng)用的流量標(biāo)簽。支持配置一個(gè)或多個(gè)標(biāo)簽。 |
TrafficLabelRule
字段 | 類型 | 是否必選 | 說(shuō)明 |
labels | Label[] | 是 | 需要設(shè)置的標(biāo)簽名稱與值。 |
Label
字段 | 類型 | 是否必選 | 說(shuō)明 |
name | string | 是 | 標(biāo)簽名稱。該名稱需要符合HTTP請(qǐng)求頭的命名規(guī)范。 |
valueFrom | string[] | 是 | 標(biāo)簽值。取值采用自然順序的優(yōu)先級(jí),優(yōu)先從第一行獲取標(biāo)簽值,當(dāng)獲取不到時(shí)才會(huì)從第二行獲取標(biāo)簽值,以此類推。 更多信息,請(qǐng)參見valueFrom。 |
valueFrom
valueFrom支持以下四種變量。您可以展開表格下方的折疊面板,查看變量的詳細(xì)說(shuō)明。
變量 | 支持的工作負(fù)載類型 |
$getInboundRequestHeader(headerName) | 網(wǎng)關(guān) |
$getExternalInboundRequestHeader(headerName, contextId) | Sidecar代理 |
$getLocalOutboundRequestHeader(headerName) | Sidecar代理 |
$getLabel(labelName) | 網(wǎng)關(guān)或者Sidecar代理 |
表示從進(jìn)入網(wǎng)關(guān)的請(qǐng)求頭中獲取名稱為headerName的標(biāo)頭值。該變量是一個(gè)函數(shù)型變量,需要從入口請(qǐng)求頭中獲取。參數(shù)headerName是指請(qǐng)求頭的關(guān)鍵字Key。如果參數(shù)值為空,默認(rèn)為x-asm-prefer-tag。
如下圖所示,入口網(wǎng)關(guān)會(huì)為出口請(qǐng)求中附加一個(gè)新請(qǐng)求頭。該請(qǐng)求頭的名稱為流量標(biāo)簽TrafficLabel CRD中定義的標(biāo)簽名(例如userDefinedLabel),值為tagValue。
該變量?jī)H對(duì)網(wǎng)關(guān)生效,對(duì)Sidecar代理不生效。
表示從進(jìn)入Sidecar代理的請(qǐng)求中獲取名稱為headerName的標(biāo)頭值。該變量是一個(gè)函數(shù)型變量,需要從流量請(qǐng)求的上下文中獲取。參數(shù)說(shuō)明如下:
headerName:請(qǐng)求頭的關(guān)鍵字Key。該參數(shù)為必填項(xiàng),且值不能為空,例如x-asm-prefer-tag。
contextId:一個(gè)貫穿整個(gè)調(diào)用鏈路的請(qǐng)求頭字段,其值可配置為一個(gè)指定的入口請(qǐng)求頭或Tracing系統(tǒng)中的Trace ID。該參數(shù)為必填項(xiàng),且值不能為空。
Sidecar包含入口和出口兩種類型的流量。流量打標(biāo)的本質(zhì)是對(duì)出口流量設(shè)置標(biāo)簽。默認(rèn)情況下,Sidecar代理從入口請(qǐng)求頭(名稱為headerName)中獲取對(duì)應(yīng)的值,并以此作為流量打標(biāo)的標(biāo)簽值tagValue。
為了將標(biāo)簽值tagValue附加到出口流量請(qǐng)求中,在Sidecar代理的內(nèi)部邏輯中維持一個(gè)map<contextId, tagValue>。contextId是一個(gè)貫穿整個(gè)調(diào)用鏈路的請(qǐng)求頭字段,其值可配置為一個(gè)指定的入口請(qǐng)求頭或使用x-request-id作為contextId。
當(dāng)業(yè)務(wù)容器發(fā)起出口請(qǐng)求時(shí),Sidecar代理會(huì)通過(guò)contextId查找上下文Map。若找到關(guān)聯(lián)tagValue,則Sidecar代理會(huì)為出口請(qǐng)求中附加兩個(gè)新請(qǐng)求頭:
請(qǐng)求頭名稱為headerName,值為tagValue。
請(qǐng)求頭名稱為流量標(biāo)簽TrafficLabel CRD中定義的標(biāo)簽名(例如userDefinedLabel),值為tagValue。
該變量?jī)H對(duì)Sidecar代理生效,對(duì)網(wǎng)關(guān)不生效。
map<contextId, tagValue>
存儲(chǔ)在Envoy內(nèi)存中,默認(rèn)30秒過(guò)期。業(yè)務(wù)應(yīng)用接入Trace系統(tǒng)時(shí),TraceID會(huì)貫穿整個(gè)調(diào)用鏈路的請(qǐng)求,因此可以使用TraceID作為上述contextId。采用不同的Trace系統(tǒng)會(huì)有不同TraceID。更多信息,請(qǐng)參見Tracing。
雖然Istio代理能夠自動(dòng)發(fā)送Tracing Span信息,但是應(yīng)用程序仍然需要傳播相關(guān)的HTTP標(biāo)頭,以便在代理發(fā)送Span時(shí),可以將Span正確地關(guān)聯(lián)到單個(gè)跟蹤中。具體操作,請(qǐng)參見在ASM中實(shí)現(xiàn)分布式跟蹤。
若沒(méi)有傳播對(duì)應(yīng)的HTTP標(biāo)頭,則出口流量無(wú)法關(guān)聯(lián)的contextId。Sidecar代理將無(wú)法從
map<contextId,tagValue>
找到對(duì)應(yīng)的流量標(biāo)簽值。
表示從由應(yīng)用服務(wù)發(fā)出至Sidecar代理的請(qǐng)求中獲取名稱為headerName的標(biāo)頭值。該變量是一個(gè)函數(shù)型變量,需要從入口請(qǐng)求頭中獲取。參數(shù)headerName表示請(qǐng)求頭的關(guān)鍵字Key。您可以根據(jù)業(yè)務(wù)容器實(shí)際的請(qǐng)求頭進(jìn)行指定。
如下圖所示,當(dāng)注入Sidecar代理的業(yè)務(wù)容器發(fā)起出口請(qǐng)求時(shí),Sidecar代理會(huì)為出口請(qǐng)求中附加一個(gè)新請(qǐng)求頭。該請(qǐng)求頭的名稱為流量標(biāo)簽TrafficLabel CRD中定義的標(biāo)簽名(例如userDefinedLabel),值為tagValue。
該變量?jī)H對(duì)Sidecar代理生效,對(duì)網(wǎng)關(guān)不生效。
表示從網(wǎng)關(guān)Pod或Sidecar容器所屬Pod的標(biāo)簽中獲取名稱為labelName的標(biāo)簽值,并將該值附加到出口流量上。如果labelName為空,默認(rèn)從工作負(fù)載Pod上的標(biāo)簽ASM_TRAFFIC_TAG取值。
例如,以下工作負(fù)載定義ASM_TRAFFIC_TAG值為test
,通過(guò)$getLabel(ASM_TRAFFIC_TAG)可以獲取標(biāo)簽值為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: {}
配置示例
以下示例的ASM實(shí)例版本為1.17及以上。關(guān)于升級(jí)實(shí)例的具體操作,請(qǐng)參見升級(jí)ASM實(shí)例。
示例一:按照工作負(fù)載進(jìn)行流量打標(biāo)簽
通過(guò)定義workloadSelector
根據(jù)標(biāo)簽選擇對(duì)應(yīng)的工作負(fù)載,可以實(shí)現(xiàn)對(duì)某個(gè)命名空間下的工作負(fù)載進(jìn)行流量打標(biāo)簽。
部署bookinfo應(yīng)用。具體操作,請(qǐng)參見在ASM實(shí)例關(guān)聯(lián)的集群中部署應(yīng)用。
使用以下內(nèi)容,創(chuàng)建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)
執(zhí)行以下命令,對(duì)
productpage
工作負(fù)載進(jìn)行流量打標(biāo)簽。kubectl apply -n default -f productpage-trafficlabel.yaml
執(zhí)行以下命令,查看
productpage
工作負(fù)載對(duì)應(yīng)的代理配置。kubectl exec -it -n default deploy/productpage-v1 -c istio-proxy -- curl localhost:15000/config_dump
預(yù)期輸出:
{ "name": "com.aliyun.traffic_label", "typed_config": { "@type": "type.googleapis.com/envoy.config.filter.traffic_label.v3alpha.TrafficLabel", } },
在對(duì)應(yīng)的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
配置內(nèi)容,表明流量標(biāo)簽配置成功。執(zhí)行以下命令,查看其他工作負(fù)載(例如details Pod)對(duì)應(yīng)的代理配置。
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
返回結(jié)果為空,表明沒(méi)有相關(guān)的
filter
,符合預(yù)期。
示例二:按照命名空間進(jìn)行流量打標(biāo)簽
如果不定義workloadSelector
字段,將對(duì)命名空間下所有的工作負(fù)載進(jìn)行流量打標(biāo)簽。以下示例將對(duì)命名空間default下的所有工作負(fù)載進(jìn)行流量打標(biāo)簽。
使用以下內(nèi)容,創(chuàng)建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)
執(zhí)行以下命令,對(duì)命名空間default下的所有工作負(fù)載進(jìn)行流量打標(biāo)簽。
kubectl apply -n default -f all-workload-for-ns-trafficlabel.yaml
執(zhí)行以下命令,查看工作負(fù)載(例如details Pod)對(duì)應(yīng)的代理的配置。
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
預(yù)期輸出:
"@type": "type.googleapis.com/envoy.config.filter.traffic_label.v3alpha.TrafficLabel",
輸出如上內(nèi)容,表明流量標(biāo)簽配置成功。