當您需要對微服務應用中的工作負載進行更精細化的管理和路由控制時,可以使用動態子集路由功能。在多應用多版本發布的情境下,ASM會自動根據應用特徵將工作負載劃分至對應的動態子集,減輕營運人員的手動設定負擔。ASM還支援通過請求的特定Header與子集特徵匹配,實現更靈活的請求路由。
前提條件
已添加叢集到ASM執行個體,且ASM執行個體版本為1.18及以上。
功能介紹
ASM支援通過目標規則DestinationRule將服務下的工作負載通過標籤劃分為不同的子集,並支援聲明路由規則,指向特定的子集。這種使用方式較為簡明,也可以滿足絕大多數情況下的需求。但在一些情境中,這種靜態分組並靜態路由的方式可能不夠便利。例如,在以版本將工作負載劃分為不同的子集的情境中,版本可能是不斷增長的。這要求營運人員在新版本發布或舊版本下線時,新增或移除在DestinationRule中相應的子集配置。在多應用多版本頻繁發布的情境下,這項工作會給營運人員增加一些額外的負擔。
為了提高使用體驗,ASM自1.18版本起,支援動態子集路由。您可以通過指定維度(例如版本),動態地將指定維度值相同的工作負載劃分至同一個動態子集。使用動態子集應對上述情境則無需營運人員手動為每個新版本靜態配置子集。部署工作負載時,ASM會自動地根據應用特徵將其劃分至對應動態子集。同時,ASM支援配置通過請求的特定Header與子集特徵進行匹配,根據請求攜帶的Header將請求路由到指定動態子集。
步驟一:部署應用樣本
本文以hashicorp/http-echo應用為例,部署dev和prod兩套環境,分別類比開發環境和生產環境。在dev環境下部署v1、v2、v3版本,在prod環境下只部署v2、v3版本。helloworld監聽在5678連接埠,收到請求會回複自己的環境和版本。同時,部署服務helloworld,暴露8000連接埠,選中app
為helloworld
的工作負載。
在ACK叢集對應的KubeConfig環境下,使用以下YAML分別部署helloworld應用dev環境v1、v2和v3版本、prod環境v2和v3版本、helloworld服務以及用於發起測試的sleep應用。關於如何部署應用,請參見在ASM執行個體關聯的叢集中部署應用。
步驟二:訪問指定環境的指定版本
部署目標規則和虛擬服務。
使用以下內容,為helloworld服務配置目標規則。具體操作,請參見管理目標規則。
Helloworld應用部署完畢後,在預設情況下,訪問helloworld服務的請求將被K8s負載平衡分配到任意一個helloworld應用Pod。本文為helloworld應用部署2個環境多個版本(dev環境v1、v2和v3版本、prod環境v2和v3版本)。要訪問指定環境和版本,需要為helloworld服務配置目標規則DestinationRule。
apiVersion: networking.istio.io/v1beta1 kind: DestinationRule metadata: name: helloworld namespace: default spec: host: helloworld.default.svc.cluster.local trafficPolicy: loadBalancer: dynamicSubset: subsetSelectors: - keys: - stage - version
以上目標規則為helloworld服務配置了一個以stage和version標籤進行分組的規則。本例中部署的工作負載將被該規則分為以下幾個分組。
分組
Pod
地址
stage = dev
version = v1
helloworld-dev-v1-67b6876778-nf7pz
192.168.0.5
stage = dev
version = v2
helloworld-dev-v2-68f65bbc99-v957l
192.168.0.1
stage = dev
version = v3
helloworld-dev-v3-7f6978bc56-hqzgg
192.168.0.252
stage = prod
version = v2
helloworld-prod-v2-b5745b949-p8rc4
192.168.0.103
stage = prod
version = v3
helloworld-prod-v3-6768bf56f8-6bd6h
192.168.0.104
helloworld-prod-v3-6768bf56f8-6bd6h
192.168.0.6
使用以下內容,為helloworld服務建立虛擬服務,建立請求到動態分組
key
之間的映射關係。具體操作,請參見管理虛擬服務。以上虛擬服務指定:
將請求中名為
x-version
的Header的值對應到分組名為version
的分組key
。若請求未攜帶x-version
Header,則使用預設值v3
。將請求中名為
x-stage
的Header的值對應到名為stage
的分組key
。若請求未攜帶x-stage
Header,則使用預設值prod
。
在ACK叢集對應的KubeConfig環境下,執行以下命令,從sleep應用發起對helloworld應用dev環境的v1版本的訪問。
關於如何通過kubectl管理叢集,請參見擷取叢集KubeConfig並通過kubectl工具串連叢集。
kubectl exec -it deploy/sleep -c sleep -- curl -H 'x-stage: dev' -H 'x-version: v1' helloworld:8000
預期輸出:
Welcome to helloworld stage: dev, version: v1, ip: 192.168.0.5
由預期輸出得到,請求被正確地路由至
stage
標籤為dev
、version
標籤為v1
的Pod。
步驟三:為分組配置回退策略
prod環境中未部署v1版本,若嘗試訪問prod環境的v1版本,會因為該分組不存在而報錯。
kubectl exec -it deploy/sleep -c sleep -- curl -H 'x-stage: prod' -H 'x-version: v1' helloworld:8000
預期輸出:
no healthy upstream # 由於分組不存在,產生報錯。
為了避免分組不存在時訪問失敗,您可以為動態分組規則配置回退策略。下文介紹ASM動態分組支援的三種回退策略:NO_FALLBACK、ANY_ENDPOINT、DEFAULT_SUBSET。
NO_FALLBACK
為動態分組規則使用該策略,當無法匹配任何分組時,請求將會報no healthy upstream
錯誤。
使用如下目標規則,為
stage
、version
分組規則指定fallbackPolicy
為NO_FALLBACK
。具體操作,請參見管理目標規則。apiVersion: networking.istio.io/v1beta1 kind: DestinationRule metadata: name: helloworld namespace: default spec: host: helloworld.default.svc.cluster.local trafficPolicy: loadBalancer: dynamicSubset: subsetSelectors: - fallbackPolicy: NO_FALLBACK keys: - stage - version
執行以下命令,訪問
stage
為prod
、version
為v1
的helloworld應用。kubectl exec -it deploy/sleep -c sleep -- curl -H 'x-stage: prod' -H 'x-version: v1' helloworld:8000
預期輸出:
no healthy upstream # 由於分組不存在,產生報錯。
ANY_ENDPOINT
為動態分組規則使用該策略,當無法匹配任何分組時,請求將被路由至服務下的任意端點。
使用如下目標規則,為
stage
、version
分組規則指定fallbackPolicy
為ANY_ENDPOINT
。具體操作,請參見管理目標規則。apiVersion: networking.istio.io/v1beta1 kind: DestinationRule metadata: name: helloworld namespace: default spec: host: helloworld.default.svc.cluster.local trafficPolicy: loadBalancer: dynamicSubset: subsetSelectors: - fallbackPolicy: ANY_ENDPOINT keys: - stage - version
執行以下命令,訪問
stage
為prod
、version
為v1
的helloworld應用。第一次訪問:
kubectl exec -it deploy/sleep -c sleep -- curl -H 'x-stage: prod' helloworld:8000
預期輸出:
Welcome to helloworld stage: prod, version: v2, ip: 192.168.0.103 # 第一次訪問被路由至prod, v2。
第二次訪問:
kubectl exec -it deploy/sleep -c sleep -- curl -H 'x-stage: prod' -H 'x-version: v1' helloworld:8000
預期輸出:
Welcome to helloworld stage: dev, version: v2, ip: 192.168.0.1 # 第二次訪問被路由至dev, v2。
由預期輸出得到,請求被路由至helloworld服務下的隨機Pod。
DEFAULT_SUBSET
為動態分組規則使用該策略,當無法匹配任何分組時,請求將被路由至defaultSubset
指定的key
匹配的分組。
使用如下目標規則,為
stage
、version
分組規則指定fallbackPolicy
為DEFAULT_SUBSET
,並配置defaultSubset
的key
和value
。具體操作,請參見管理目標規則。key
value
stage
prod
version
v3
apiVersion: networking.istio.io/v1beta1 kind: DestinationRule metadata: name: helloworld namespace: default spec: host: helloworld.default.svc.cluster.local trafficPolicy: loadBalancer: dynamicSubset: defaultSubset: stage: prod version: v3 subsetSelectors: - fallbackPolicy: DEFAULT_SUBSET keys: - stage - version
執行以下命令,訪問
stage
為prod
、version
為v1
的分組。第一次訪問:
kubectl exec -it deploy/sleep -c sleep -- curl -H 'x-stage: prod' -H 'x-version: v1' helloworld:8000
預期輸出:
Welcome to helloworld stage: prod, version: v3, ip: 192.168.0.6
第二次訪問:
kubectl exec -it deploy/sleep -c sleep -- curl -H 'x-stage: prod' -H 'x-version: v1' helloworld:8000
預期輸出:
Welcome to helloworld stage: prod, version: v3, ip: 192.168.0.104
由預期輸出得到,由於分組不存在,觸發回退,使用
stag
為prod
、version
為v3
匹配分組,符合預期。
步驟四:訪問指定Pod
若您需要訪問到指定Pod,可以通過ASM動態分組內建keys
為%ip%
進行分組,將每個Pod劃分獨立分組。
使用以下目標規則,新增一個以Pod IP維度進行分組的分組規則。具體操作,請參見管理目標規則。
apiVersion: networking.istio.io/v1beta1 kind: DestinationRule metadata: name: helloworld namespace: default spec: host: helloworld.default.svc.cluster.local trafficPolicy: loadBalancer: dynamicSubset: defaultSubset: stage: prod version: v3 subsetSelectors: - keys: - '%ip%'
使用如下虛擬服務,將請求的
x-ip
Header映射到%ip%
分組的規則,使請求可以通過x-ip
指定希望訪問的Pod IP。具體操作,請參見管理虛擬服務。apiVersion: networking.istio.io/v1beta1 kind: VirtualService metadata: name: helloworld namespace: default spec: hosts: - helloworld.default.svc.cluster.local http: - headerToDynamicSubsetKey: - header: x-ip key: '%ip%' name: default route: - destination: host: helloworld.default.svc.cluster.local port: number: 8000
執行以下命令,對Pod helloworld-prod-v3-6768bf56f8-6bd6h進行訪問,指定Pod地址
192.168.0.6
,進行多次訪問。第一次訪問:
kubectl exec -it deploy/sleep -c sleep -- curl -H 'x-ip: 192.168.0.6' helloworld:8000
預期輸出:
Welcome to helloworld stage: prod, version: v3, ip: 192.168.0.6
第二次訪問:
kubectl exec -it deploy/sleep -c sleep -- curl -H 'x-ip: 192.168.0.6' helloworld:8000
預期輸出:
Welcome to helloworld stage: prod, version: v3, ip: 192.168.0.6
第三次訪問:
kubectl exec -it deploy/sleep -c sleep -- curl -H 'x-ip: 192.168.0.6' helloworld:8000
預期輸出:
Welcome to helloworld stage: prod, version: v3, ip: 192.168.0.6
由預期輸出得到,請求都被路由至指定的Pod地址
192.168.0.6
,符合預期。
CRD說明
VirtualService
HTTPRoute
ASM對HTTPRoute進行擴充,增加headerToDynamicSubsetKey欄位。
欄位
類型
說明
headerToDynamicSubsetKey
用於配置請求Header到動態子集key的映射。數組中的每一個元素為一個Header到一個key的映射。
HeaderToMetadataSubsetKey
配置請求Header到動態子集key的映射關係或預設值。
欄位
類型
說明
header
string
要求標頭名稱。
key
string
動態子集key名稱,其中%開頭結尾的表示工作負載內建屬性。
defaultValue
string
若請求沒有攜帶key指定的Header,則使用該預設值。如果不配置預設值,則在請求未攜帶該Header時視作該維度缺失,該維度不參與匹配。
DestinationRule
ASM對trafficPolicy結構進行擴充,增加dynamicSubset欄位。
TrafficPolicy
欄位
類型
說明
dynamicSubset
用於配置動態分組規則。
DyunamicSubsetLB
欄位
類型
說明
defaultSubset
map[string]string
用於配置預設分組,當請求無法匹配任何動態分組,且分組規則的回退策略為DEFAULT_SUBSET時,使用該配置聲明的維度值選擇分組。
subsetSelectors
用於配置動態分組規則,數組中每一項為一個獨立的分組規則。
fallbackPolicy
指定無法匹配動態子集時的回退策略。若不指定該配置,則預設為NO_FALLBACK。
SubsetSelector
欄位
類型
說明
keys
string[]
分組維度列表,值對應至工作負載標籤。例如,version表示以工作負載的名為version的標籤作為分組維度。除標籤外,還支援以工作負載內建屬性作為維度。更多資訊,請參見工作負載內建屬性。
fallbackPolicy
指定無法匹配動態子集時的回退策略。若不指定該配置,則使用DyunamicSubsetLB中指定的fallbackPolicy。
DynamicSubsetLB_FallbackPolicy
表示動態子集路由回退策略的枚舉類型,支援的值如下:
值
說明
NO_FALLBACK
不進行回退。
ANY_ENDPOINT
使用服務下任意端點。
DEFAULT_SUBSET
使用聲明的預設子集進行回退。
工作負載內建屬性
屬性 | 類型 | 說明 |
%ip% | string | 工作負載的Pod地址。 |
相關文檔
您可以啟用控制平面日誌採集和日誌警示,及時發現和解決潛在的風險。具體操作,請參見啟用控制平面日誌採集和日誌警示。
您可以安裝診斷工具asmctl,檢測ASM存在的配置問題。具體操作,請參見安裝和使用診斷工具asmctl。
您可以為ASM資源(VirtualService、DestinationRule等)的變更行為添加審計警示能力,在重要資源變動時及時發出警示通知到警示連絡人。具體操作,請參見為網格資源操作配置審計警示。
您可以基於VirtualService和DestinationRule等流量規則實現流量泳道,同時通過配置流量降級,在某個版本(或者其他特徵)的應用不可用時,將流量發往一個指定的降級版本(或其他特徵)的應用。具體操作,請參見基於流量規則配置實現流量泳道和流量降級。
如果您需要在用戶端對一個目標服務的訪問過程中,使流量儘可能的在同一個可用性區域內流轉,以保證服務間的調用延遲最低,可以使用同可用性區域優先路由功能。具體操作,請參見使用網格拓撲觀測同可用性區域優先路由。