マイクロサービスが Service Mesh を介して相互に通信する際、カナリアリリース、A/B テスト、または環境隔離などの目的で、特定のリクエストを特定のサービスバージョンにルーティングする必要があります。Alibaba Cloud Service Mesh (ASM) のトラフィックラベリング機能では、リクエストがメッシュ内を通過する際にカスタムタグを付与し、そのタグに基づいて下流のルーティングルール、速度制限ポリシー、およびサーキットブレーカーが動作します。
ASM は、ラベリングルールを定義するための TrafficLabel カスタムリソース定義 (CRD) を提供します。TrafficLabel リソースを名前空間または特定のワークロードに適用すると、ASM が自動的に Envoy プロキシフィルターにラベリングロジックを挿入します。
適用範囲
カナリアリリース — ヘッダー値をマッチさせることで、一定割合のトラフィックを新バージョンにルーティングします。
A/B テスト — タグベースのルーティングルールを用いて、トラフィックを複数のバリエーション間で分割します。
環境隔離 — トラフィックに
stagingまたはproductionといったラベルを付与し、対応するバックエンドにルーティングします。
前提条件
開始する前に、以下の条件を満たしていることを確認してください。
バージョン 1.17 以降で実行中の ASM インスタンス
ASM インスタンスに関連付けられた Kubernetes クラスター
kubectlがクラスターへの接続に正しく設定されていること
ASM 1.17 では、TrafficLabel CRD に apiVersion: istio.alibabacloud.com/v1 が導入されました。以前に Container Service for Kubernetes (ACK) クラスターで apiVersion: istio.alibabacloud.com/v1beta1 を使用して TrafficLabel を設定していた場合、apiVersion を istio.alibabacloud.com/v1 に変更し、リソースを再適用してください。ASM インスタンスのアップグレードについては、「ASM インスタンスの更新」をご参照ください。それより前の ASM バージョンをご利用の場合、サポートを受けるには チケットを送信 してください。
トラフィックラベリングの仕組み
TrafficLabel リソースは、以下の 2 つの要素を定義します。
適用範囲 — どのワークロードにラベルを付与するか(名前空間内のすべてのワークロード、または Pod ラベルで選択されたサブセット)。
ルール — ラベル値をどこから抽出するか(リクエストヘッダー、Pod ラベル、またはトレースコンテキスト)。
リクエストがゲートウェイまたはサイドカープロキシに入ると、プロキシは TrafficLabel ルールを評価し、ラベル値を解決して、アウトバウンドリクエストに新しいヘッダーとして付与します。その後、下流のサービスはこのヘッダーをマッチさせることでルーティング判断を行います。
CRD 構造の概要
以下は、TrafficLabel の各フィールドがどのようにネストされるかを示すスケルトンです。
apiVersion: istio.alibabacloud.com/v1
kind: TrafficLabel
metadata:
name: <label-name> # この TrafficLabel リソースの名前
namespace: <namespace> # このリソースが適用される名前空間
spec:
workloadSelector: # (任意)省略した場合は、名前空間内のすべてのワークロードに適用
labels:
<key>: <value> # ラベルでワークロードをマッチ(例:app: productpage)
rules:
- labels:
- name: <traffic-label-name> # ラベルのヘッダー名(HTTP ヘッダーの命名規則に準拠する必要があります)
valueFrom:
- <variable-1> # ラベル値の主なソース
- <variable-2> # variable-1 が空の場合のフォールバックフィールドリファレンス
spec
| フィールド | 型 | 必須 | 説明 |
|---|---|---|---|
workloadSelector | WorkloadSelector | いいえ | ラベルを付与するワークロードを選択します。省略した場合は、名前空間内のすべてのワークロードにラベルが付与されます。 |
rules | TrafficLabelRule[] | はい | 1 つ以上のラベリングルール。 |
WorkloadSelector
| フィールド | 型 | 必須 | 説明 |
|---|---|---|---|
labels | map<string, string> | いいえ | ワークロードラベルと一致するキーと値のペア。 |
TrafficLabelRule
| フィールド | 型 | 必須 | 説明 |
|---|---|---|---|
labels | Label[] | はい | 付与するトラフィックラベル。 |
Label
| フィールド | 型 | 必須 | 説明 |
|---|---|---|---|
name | string | はい | トラフィックラベル名。HTTP リクエストヘッダーの命名規則に準拠する必要があります。 |
valueFrom | string[] | はい | 順序付きの変数リスト。プロキシは変数を順に評価し、最初に空でない結果をラベル値として使用します。「valueFrom 変数」をご参照ください。 |
valueFrom 変数
valueFrom フィールドには、順序付きの変数リストを指定できます。プロキシは変数を順に評価し、最初に空でない結果をラベル値として使用します。
4 つの変数は、適用対象によって以下の 2 つのグループに分けられます。
| 変数 | 適用対象 | ラベル値のソース |
|---|---|---|
$getInboundRequestHeader(headerName) | ゲートウェイのみ | ゲートウェイへのインバウンドリクエストヘッダー |
$getExternalInboundRequestHeader(headerName, contextId) | サイドカープロキシのみ | インバウンドリクエストヘッダー(コールチェーン全体でコンテキストマップにより相関付け) |
$getLocalOutboundRequestHeader(headerName) | サイドカープロキシのみ | アプリケーションが設定したアウトバウンドリクエストヘッダー |
$getLabel(labelName) | ゲートウェイおよびサイドカープロキシ | ゲートウェイまたはワークロード Pod の Pod ラベル |
ゲートウェイ変数
$getInboundRequestHeader(headerName)
ゲートウェイへ到達するインバウンドリクエストから headerName ヘッダーを読み取ります。ゲートウェイは、TrafficLabel CRD で定義されたラベル名をキー、抽出された値を値として、新しいアウトバウンドヘッダーを追加します。
headerName を空欄のままにした場合、デフォルトで x-asm-prefer-tag ヘッダーが読み取られます。
データフロー:
クライアントリクエスト ゲートウェイ 上流サービス
| | |
|-- headerName: tagValue ----->| |
| |-- userDefinedLabel: tagValue ---->|
| | |
サイドカープロキシ変数
$getExternalInboundRequestHeader(headerName, contextId)
サイドカープロキシへ到達するインバウンドリクエストから headerName ヘッダーを読み取り、その値を contextId をキーとする内部コンテキストマップに格納します。このマップは Envoy のメモリ上にデフォルトで 30 秒間保持されます。
パラメーター(両方とも必須):
| パラメーター | 説明 | 例 |
|---|---|---|
headerName | 読み取るリクエストヘッダーのキー。 | x-asm-prefer-tag |
contextId | コールチェーン全体で継承されるヘッダー項目。インバウンドおよびアウトバウンドトラフィックの相関付けに使用されます。通常はトレース ID です。 | x-request-id |
コンテキストマップの動作:
インバウンドリクエストがサイドカープロキシに到達します。プロキシは
headerNameを読み取り、tagValueを取得して、map<contextId, tagValue>として格納します。アプリケーションがアウトバウンドリクエストを開始すると、プロキシはコンテキストマップ内で
contextIdを検索します。一致が見つかった場合、プロキシはアウトバウンドリクエストに以下の 2 つのヘッダーを追加します。
headerName: tagValueuserDefinedLabel: tagValue(TrafficLabel CRD で定義されたラベル名を使用)
データフロー:
インバウンドリクエスト サイドカープロキシ(コンテキストマップ) アウトバウンドリクエスト
| | |
|-- headerName: tagValue | |
|-- contextId: ctx123 --->| store: ctx123 -> tagValue |
| | |
| アプリケーションがアウトバウンドリクエストを開始 |
| |-- contextId: ctx123 ----------->|
| | (検索:ctx123 -> tagValue) |
| |-- headerName: tagValue -------->|
| |-- userDefinedLabel: tagValue -->|
コンテキストマップ (
map<contextId, tagValue>) は、デフォルトで Envoy プロキシのメモリ上に 30 秒間保持されます。アプリケーションがトレーシングシステムと接続されている場合、
contextIdとしてトレース ID を使用します。異なるトレーシングシステムでは、トレース ID が異なります。詳細については、「Tracing」をご参照ください。Istio プロキシがスパンを完全なトレースに相関付けるには、アプリケーションが関連する HTTP ヘッダーを伝搬させる必要があります。「ASM における分散トレーシングの有効化」をご参照ください。
アプリケーションが
contextIdを伝搬しない場合、サイドカープロキシはコンテキストマップからラベル値を検索できず、アウトバウンドリクエストにはラベルが付与されません。
$getLocalOutboundRequestHeader(headerName)
アプリケーションがサイドカープロキシに送信するアウトバウンドリクエストから headerName ヘッダーを読み取ります。プロキシは、TrafficLabel CRD で定義されたラベル名をキー、抽出された値を値として、新しいアウトバウンドヘッダーを追加します。
アプリケーション自体がアウトバウンドリクエストにヘッダーを設定する場合に、この変数を使用します。
データフロー:
アプリケーションコンテナ サイドカープロキシ 上流サービス
| | |
|-- headerName: tagValue ----->| |
| |-- userDefinedLabel: tagValue -->|
| | |
Pod ラベル変数
$getLabel(labelName)
ゲートウェイ Pod またはサイドカープロキシワークロード Pod の labelName ラベルを読み取り、その値をアウトバウンドトラフィックに付与します。labelName を空欄のままにした場合、プロキシはデフォルトで ASM_TRAFFIC_TAG ラベルを読み取ります。
例: Deployment Pod に ASM_TRAFFIC_TAG: test というラベルが設定されている場合、変数 $getLabel(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 # $getLabel(ASM_TRAFFIC_TAG) で読み取られる値
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: {}特定のワークロードに対するトラフィックのラベル付け
この例では、productpage ワークロードのトラフィックにラベルを付与します。ラベル値は、インバウンドリクエストヘッダー header1(x-request-id で相関付け)から解決され、フォールバックとして Pod ラベル header2 が使用されます。
このページの両方の例では、ASM 1.17 以降が必要であり、Bookinfo サンプルアプリケーションを使用します。
Bookinfo アプリケーションをデプロイします。「ASM インスタンスへのアプリケーションのデプロイ」をご参照ください。
以下の YAML を
productpage-trafficlabel.yamlとして保存します。apiVersion: istio.alibabacloud.com/v1 kind: TrafficLabel metadata: name: productpage namespace: default spec: workloadSelector: labels: app: productpage # productpage ワークロードにのみ適用 rules: - labels: - name: asm-labels-test-a # ラベルのアウトバウンドヘッダー名 valueFrom: - $getExternalInboundRequestHeader(header1, x-request-id) # 主要ソース:インバウンドヘッダーから読み取り - $getLabel(header2) # フォールバック:Pod ラベルから読み取りリソースを適用します。
kubectl apply -n default -f productpage-trafficlabel.yamlEnvoy フィルターが
productpageプロキシに注入されたことを確認します。com.aliyun.traffic_labelフィルターがdynamic_listenersまたはhttp_filters内に存在することを確認します。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", ... } }選択されていないワークロードが影響を受けないことを確認します。
detailsPod に対して同様のチェックを実行します。空の結果が出力された場合、ラベリングフィルターが注入されていないことが確認でき、期待通りの動作です。kubectl exec -it -n default deploy/details-v1 -c istio-proxy -- \ curl localhost:15000/config_dump | grep traffic_label
名前空間レベルでのトラフィックのラベル付け
workloadSelector を省略することで、名前空間内のすべてのワークロードにトラフィックラベルを付与できます。この例では、default 名前空間内のすべてのワークロードにラベルを付与します。
以下の YAML を
all-workload-for-ns-trafficlabel.yamlとして保存します。apiVersion: istio.alibabacloud.com/v1 kind: TrafficLabel metadata: name: all-workload-for-ns namespace: default spec: rules: # workloadSelector なし:「default」名前空間内のすべてのワークロードに適用 - labels: - name: asm-labels-test-b valueFrom: - $getExternalInboundRequestHeader(header1, x-request-id) - $getLabel(header2)リソースを適用します。
kubectl apply -n default -f all-workload-for-ns-trafficlabel.yamlラベリングフィルターがすべてのワークロードに注入されたことを確認します。
detailsPod をチェックします。期待される出力:名前空間内のすべてのワークロードにフィルターが注入されています。kubectl exec -it -n default deploy/details-v1 -c istio-proxy -- \ curl localhost:15000/config_dump | grep traffic_label"@type": "type.googleapis.com/envoy.config.filter.traffic_label.v3alpha.TrafficLabel",
関連トピック
ASM インスタンスへのアプリケーションのデプロイ — トラフィックラベルの設定前に、メッシュ内にワークロードをセットアップします。
ASM における分散トレーシングの有効化 —
$getExternalInboundRequestHeaderで必要なトレースヘッダーを伝搬します。ASM インスタンスの更新 — 古いバージョンをご利用の場合、ASM 1.17 以上へアップグレードします。