このトピックでは、Baggage ヘッダーがエンドツーエンド ( E2E ) パススルーリクエストヘッダーとして使用される場合に、仮想サービスと ASMHeaderPropagation CustomResourceDefinitions ( CRD ) を構成して、許可モードでトラフィックレーンとトラフィックシフトを実装する方法について説明します。
機能紹介
Baggage は、OpenTelemetry によって開発された標準化されたメカニズムであり、分散システムのトレースにおいてプロセス間でコンテキスト情報を伝播するために使用されます。これを行うには、Baggage という名前の HTTP ヘッダーを HTTP ヘッダーに追加します。Baggage ヘッダーの値は、キーと値のペアの形式です。Baggage ヘッダーを使用して、テナント ID、トレース ID、セキュリティ資格情報などのコンテキストデータを転送できます。このようにして、コードを変更することなく、トレース分析とログ関連付け機能を使用できます。例:
baggage: userId=alice,serverNode=DF%2028,isProduction=false
Baggage ヘッダーのコンテキスト情報に基づいて、ASM は ASMHeaderPropagation CRD を使用して、サービス呼び出しチェーン上の任意のリクエストヘッダーをパススルーし、Baggage ヘッダーに基づいて許可モードでトラフィックレーンを実装できます。許可モードでのトラフィックレーンの詳細については、「トラフィックレーンの概要」をご参照ください。
手順 1 : サービスの Pod が Baggage ヘッダーを透過的に送信できるようにする機能を構成する
このセクションでは、OpenTelemetry Operator の自動インストゥルメンテーション機能を使用して、Kubernetes クラスタ内のサービスの Pod が Baggage ヘッダーを透過的に送信できるようにする方法を示します。
OpenTelemetry Operator をデプロイします。
kubectl クライアントを使用して、ASM インスタンスに追加されている Kubernetes クラスタに接続します。次のコマンドを実行して、opentelemetry-operator-system という名前のネームスペースを作成します。
kubectl create namespace opentelemetry-operator-system
次のコマンドを実行して、Helm を使用して opentelemetry-operator-system ネームスペースに OpenTelemetry Operator をインストールします。Helm のインストール方法の詳細については、Install Helm を参照してください。
helm repo add open-telemetry https://open-telemetry.github.io/opentelemetry-helm-charts
helm install \
--namespace=opentelemetry-operator-system \
--version=0.46.0 \
--set admissionWebhooks.certManager.enabled=false \
--set admissionWebhooks.certManager.autoGenerateCert=true \
--set manager.image.repository="registry-cn-hangzhou.ack.aliyuncs.com/acs/opentelemetry-operator" \
--set manager.image.tag="0.92.1" \
--set kubeRBACProxy.image.repository="registry-cn-hangzhou.ack.aliyuncs.com/acs/kube-rbac-proxy" \
--set kubeRBACProxy.image.tag="v0.13.1" \
--set manager.collectorImage.repository="registry-cn-hangzhou.ack.aliyuncs.com/acs/opentelemetry-collector" \
--set manager.collectorImage.tag="0.97.0" \
--set manager.opampBridgeImage.repository="registry-cn-hangzhou.ack.aliyuncs.com/acs/operator-opamp-bridge" \
--set manager.opampBridgeImage.tag="0.97.0" \
--set manager.targetAllocatorImage.repository="registry-cn-hangzhou.ack.aliyuncs.com/acs/target-allocator" \
--set manager.targetAllocatorImage.tag="0.97.0" \
--set manager.autoInstrumentationImage.java.repository="registry-cn-hangzhou.ack.aliyuncs.com/acs/autoinstrumentation-java" \
--set manager.autoInstrumentationImage.java.tag="1.32.1" \
--set manager.autoInstrumentationImage.nodejs.repository="registry-cn-hangzhou.ack.aliyuncs.com/acs/autoinstrumentation-nodejs" \
--set manager.autoInstrumentationImage.nodejs.tag="0.49.1" \
--set manager.autoInstrumentationImage.python.repository="registry-cn-hangzhou.ack.aliyuncs.com/acs/autoinstrumentation-python" \
--set manager.autoInstrumentationImage.python.tag="0.44b0" \
--set manager.autoInstrumentationImage.dotnet.repository="registry-cn-hangzhou.ack.aliyuncs.com/acs/autoinstrumentation-dotnet" \
--set manager.autoInstrumentationImage.dotnet.tag="1.2.0" \
--set manager.autoInstrumentationImage.go.repository="registry-cn-hangzhou.ack.aliyuncs.com/acs/opentelemetry-go-instrumentation" \
--set manager.autoInstrumentationImage.go.tag="v0.10.1.alpha-2-aliyun" \
opentelemetry-operator open-telemetry/opentelemetry-operator
次のコマンドを実行して、OpenTelemetry Operator が正しく動作しているかどうかを確認します。
kubectl get pod -n opentelemetry-operator-system
期待される出力:
NAME READY STATUS RESTARTS AGE
opentelemetry-operator-854fb558b5-pvllj 2/2 Running 0 1m
自動インストゥルメンテーションを構成します。
次の内容を含む instrumentation.yaml ファイルを作成します。
重要 OpenTelemetry Collector がデプロイされていない場合、自動インストゥルメンテーションの構成時にメトリック収集とトレース分析を有効にすることはできません。 OpenTelemetry Collector がデプロイされていて、ASM トレースデータを Managed Service for OpenTelemetry Collector に収集する場合は、OpenTelemetry Collector がデプロイされている場合の自動インストゥルメンテーション構成を参照できます。
OpenTelemetry Collector がデプロイされていない場合
apiVersion: opentelemetry.io/v1alpha1
kind: Instrumentation
metadata:
name: demo-instrumentation
spec:
env:
- name: OTEL_METRICS_EXPORTER
value: none
propagators:
- baggage
sampler:
argument: "1"
type: always_off
OpenTelemetry Collector がデプロイされている場合
apiVersion: opentelemetry.io/v1alpha1
kind: Instrumentation
metadata:
name: demo-instrumentation
spec:
propagators:
- baggage
sampler:
type: parentbased_traceidratio
argument: "1"
次のコマンドを実行して、default ネームスペースで自動インストゥルメンテーションを宣言します。
kubectl apply -f instrumentation.yaml
説明 OpenTelemetry フレームワークの場合、可観測性データを収集するために OpenTelemetry Collector をデプロイすることがベストプラクティスの 1 つです。 OpenTelemetry Collector のデプロイ手順については、ここでは説明しません。ASM トレースデータを Managed Service for OpenTelemetry に収集する方法の詳細については、「ASM トレースデータを Managed Service for OpenTelemetry に収集する」をご参照ください。
手順 2 : サンプルサービスをデプロイする
default ネームスペースに対して自動サイドカープロキシインジェクションを有効にします。詳細については、「グローバルネームスペースを管理する」をご参照ください。
次の内容を含む mock.yaml ファイルを作成します。
mock.yaml ファイルを表示
apiVersion: v1
kind: Service
metadata:
name: mocka
labels:
app: mocka
service: mocka
spec:
ports:
- port: 8000
name: http
selector:
app: mocka
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: mocka-v1
labels:
app: mocka
version: v1
spec:
replicas: 1
selector:
matchLabels:
app: mocka
version: v1
ASM_TRAFFIC_TAG: v1
template:
metadata:
labels:
app: mocka
version: v1
ASM_TRAFFIC_TAG: v1
annotations:
instrumentation.opentelemetry.io/inject-java: "true"
instrumentation.opentelemetry.io/container-names: "default"
spec:
containers:
- name: default
image: registry-cn-hangzhou.ack.aliyuncs.com/acs/asm-mock:v0.1-java
imagePullPolicy: IfNotPresent
env:
- name: version
value: v1
- name: app
value: mocka
- name: upstream_url
value: "http://mockb:8000/"
ports:
- containerPort: 8000
---
apiVersion: v1
kind: Service
metadata:
name: mockb
labels:
app: mockb
service: mockb
spec:
ports:
- port: 8000
name: http
selector:
app: mockb
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: mockb-v1
labels:
app: mockb
version: v1
spec:
replicas: 1
selector:
matchLabels:
app: mockb
version: v1
ASM_TRAFFIC_TAG: v1
template:
metadata:
labels:
app: mockb
version: v1
ASM_TRAFFIC_TAG: v1
annotations:
instrumentation.opentelemetry.io/inject-java: "true"
instrumentation.opentelemetry.io/container-names: "default"
spec:
containers:
- name: default
image: registry-cn-hangzhou.ack.aliyuncs.com/acs/asm-mock:v0.1-java
imagePullPolicy: IfNotPresent
env:
- name: version
value: v1
- name: app
value: mockb
- name: upstream_url
value: "http://mockc:8000/"
ports:
- containerPort: 8000
---
apiVersion: v1
kind: Service
metadata:
name: mockc
labels:
app: mockc
service: mockc
spec:
ports:
- port: 8000
name: http
selector:
app: mockc
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: mockc-v1
labels:
app: mockc
version: v1
spec:
replicas: 1
selector:
matchLabels:
app: mockc
version: v1
ASM_TRAFFIC_TAG: v1
template:
metadata:
labels:
app: mockc
version: v1
ASM_TRAFFIC_TAG: v1
annotations:
instrumentation.opentelemetry.io/inject-java: "true"
instrumentation.opentelemetry.io/container-names: "default"
spec:
containers:
- name: default
image: registry-cn-hangzhou.ack.aliyuncs.com/acs/asm-mock:v0.1-java
imagePullPolicy: IfNotPresent
env:
- name: version
value: v1
- name: app
value: mockc
ports:
- containerPort: 8000
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: mocka-v2
labels:
app: mocka
version: v2
spec:
replicas: 1
selector:
matchLabels:
app: mocka
version: v2
ASM_TRAFFIC_TAG: v2
template:
metadata:
labels:
app: mocka
version: v2
ASM_TRAFFIC_TAG: v2
annotations:
instrumentation.opentelemetry.io/inject-java: "true"
instrumentation.opentelemetry.io/container-names: "default"
spec:
containers:
- name: default
image: registry-cn-hangzhou.ack.aliyuncs.com/acs/asm-mock:v0.1-java
imagePullPolicy: IfNotPresent
env:
- name: version
value: v2
- name: app
value: mocka
- name: upstream_url
value: "http://mockb:8000/"
ports:
- containerPort: 8000
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: mockb-v2
labels:
app: mockb
version: v2
spec:
replicas: 1
selector:
matchLabels:
app: mockb
version: v2
ASM_TRAFFIC_TAG: v2
template:
metadata:
labels:
app: mockb
version: v2
ASM_TRAFFIC_TAG: v2
annotations:
instrumentation.opentelemetry.io/inject-java: "true"
instrumentation.opentelemetry.io/container-names: "default"
spec:
containers:
- name: default
image: registry-cn-hangzhou.ack.aliyuncs.com/acs/asm-mock:v0.1-java
imagePullPolicy: IfNotPresent
env:
- name: version
value: v2
- name: app
value: mockb
- name: upstream_url
value: "http://mockc:8000/"
ports:
- containerPort: 8000
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: mockc-v2
labels:
app: mockc
version: v2
spec:
replicas: 1
selector:
matchLabels:
app: mockc
version: v2
ASM_TRAFFIC_TAG: v2
template:
metadata:
labels:
app: mockc
version: v2
ASM_TRAFFIC_TAG: v2
annotations:
instrumentation.opentelemetry.io/inject-java: "true"
instrumentation.opentelemetry.io/container-names: "default"
spec:
containers:
- name: default
image: registry-cn-hangzhou.ack.aliyuncs.com/acs/asm-mock:v0.1-java
imagePullPolicy: IfNotPresent
env:
- name: version
value: v2
- name: app
value: mockc
ports:
- containerPort: 8000
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: mocka-v3
labels:
app: mocka
version: v3
spec:
replicas: 1
selector:
matchLabels:
app: mocka
version: v3
ASM_TRAFFIC_TAG: v3
template:
metadata:
labels:
app: mocka
version: v3
ASM_TRAFFIC_TAG: v3
annotations:
instrumentation.opentelemetry.io/inject-java: "true"
instrumentation.opentelemetry.io/container-names: "default"
spec:
containers:
- name: default
image: registry-cn-hangzhou.ack.aliyuncs.com/acs/asm-mock:v0.1-java
imagePullPolicy: IfNotPresent
env:
- name: version
value: v3
- name: app
value: mocka
- name: upstream_url
value: "http://mockb:8000/"
ports:
- containerPort: 8000
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: mockb-v3
labels:
app: mockb
version: v3
spec:
replicas: 1
selector:
matchLabels:
app: mockb
version: v3
ASM_TRAFFIC_TAG: v3
template:
metadata:
labels:
app: mockb
version: v3
ASM_TRAFFIC_TAG: v3
annotations:
instrumentation.opentelemetry.io/inject-java: "true"
instrumentation.opentelemetry.io/container-names: "default"
spec:
containers:
- name: default
image: registry-cn-hangzhou.ack.aliyuncs.com/acs/asm-mock:v0.1-java
imagePullPolicy: IfNotPresent
env:
- name: version
value: v3
- name: app
value: mockb
- name: upstream_url
value: "http://mockc:8000/"
ports:
- containerPort: 8000
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: mockc-v3
labels:
app: mockc
version: v3
spec:
replicas: 1
selector:
matchLabels:
app: mockc
version: v3
ASM_TRAFFIC_TAG: v3
template:
metadata:
labels:
app: mockc
version: v3
ASM_TRAFFIC_TAG: v3
annotations:
instrumentation.opentelemetry.io/inject-java: "true"
instrumentation.opentelemetry.io/container-names: "default"
spec:
containers:
- name: default
image: registry-cn-hangzhou.ack.aliyuncs.com/acs/asm-mock:v0.1-java
imagePullPolicy: IfNotPresent
env:
- name: version
value: v3
- name: app
value: mockc
ports:
- containerPort: 8000
アノテーション instrumentation.opentelemetry.io/inject-java: "true" と instrumentation.opentelemetry.io/container-names: "default" は、対応するサービスが Java で実装されていることを宣言するために各サービス Pod に追加され、OpenTelemetry Operator は default という名前のコンテナを自動インストゥルメントするために必要です。
次のコマンドを実行して、サービスをデプロイします。
kubectl apply -f mock.yaml
OpenTelemetry の自動インストゥルメンテーションメカニズムに基づいて、サービスの Pod はトレース内の Baggage ヘッダーを自動的にパススルーできます。
手順 3 : デスティネーションルールと ASMHeaderPropagation CRD を作成して、許可モードでトラフィックレーンを実装する
デスティネーションルールを作成します。
次の内容を含む dr-mock.yaml ファイルを作成します。
YAML ファイルを表示
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: dr-mock-default-mocka
spec:
host: mocka.default.svc.cluster.local
subsets:
- labels:
version: v1
name: v1
- labels:
version: v2
name: v2
- labels:
version: v3
name: v3
---
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: dr-mock-default-mockb
spec:
host: mockb.default.svc.cluster.local
subsets:
- labels:
version: v1
name: v1
- labels:
version: v3
name: v3
---
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: dr-mock-default-mockc
spec:
host: mockc.default.svc.cluster.local
subsets:
- labels:
version: v1
name: v1
- labels:
version: v2
name: v2
上記の YAML ファイルは、サービス mocka、mockb、および mockc が、サービスの Pod の version ラベルに基づいてバージョン v1、v2、および v3 に分類されることを示しています。 サービス mocka にはバージョン v1、v2、および v3 があり、mockb サービスにはバージョン v1 と v3 があり、mockc サービスにはバージョン v1 と v2 があります。
kubectl を使用して ASM インスタンスに接続し、次のコマンドを実行してデスティネーションルールを作成します。
kubectl apply -f dr-mock.yaml
ASMHeaderPropagation CRD を作成します。 サービスの Pod が Baggage ヘッダーをパススルーできる場合は、ASMHeaderPropagation CRD を使用して、Baggage ヘッダーのコンテキストで呼び出しチェーン上でパススルーするカスタムリクエストヘッダーを指定できます。
次の内容を含む propagation.yaml ファイルを作成します。 次のファイルは、version という名前のリクエストヘッダーが呼び出しチェーン上でパススルーされることを示しています。
apiVersion: istio.alibabacloud.com/v1beta1
kind: ASMHeaderPropagation
metadata:
name: version-propagation
spec:
headers:
- version
kubectl を使用して ASM インスタンスに接続し、次のコマンドを実行して ASMHeaderPropagation CRD を作成します。
kubectl apply -f propagation.yaml
仮想サービスを作成します。
次の内容を含む vs-mock.yaml ファイルを作成します。
YAML ファイルを表示
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: vs-mock-default-mocka
spec:
hosts:
- mocka.default.svc.cluster.local
http:
- match:
- headers:
version:
exact: v1
route:
- destination:
host: mocka.default.svc.cluster.local
subset: v1
fallback:
target:
host: mocka.default.svc.cluster.local
subset: v1
- match:
- headers:
version:
exact: v2
route:
- destination:
host: mocka.default.svc.cluster.local
subset: v2
fallback:
target:
host: mocka.default.svc.cluster.local
subset: v1
- match:
- headers:
version:
exact: v3
route:
- destination:
host: mocka.default.svc.cluster.local
subset: v3
fallback:
target:
host: mocka.default.svc.cluster.local
subset: v1
---
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: vs-mock-default-mockb
spec:
hosts:
- mockb.default.svc.cluster.local
http:
- match:
- headers:
version:
exact: v1
route:
- destination:
host: mockb.default.svc.cluster.local
subset: v1
fallback:
target:
host: mockb.default.svc.cluster.local
subset: v1
- match:
- headers:
version:
exact: v2
route:
- destination:
host: mockb.default.svc.cluster.local
subset: v2
fallback:
target:
host: mockb.default.svc.cluster.local
subset: v1
- match:
- headers:
version:
exact: v3
route:
- destination:
host: mockb.default.svc.cluster.local
subset: v3
fallback:
target:
host: mockb.default.svc.cluster.local
subset: v1
---
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: vs-mock-default-mockc
spec:
hosts:
- mockc.default.svc.cluster.local
http:
- match:
- headers:
version:
exact: v1
route:
- destination:
host: mockc.default.svc.cluster.local
subset: v1
fallback:
target:
host: mockc.default.svc.cluster.local
subset: v1
- match:
- headers:
version:
exact: v2
route:
- destination:
host: mockc.default.svc.cluster.local
subset: v2
fallback:
target:
host: mockc.default.svc.cluster.local
subset: v1
- match:
- headers:
version:
exact: v3
route:
- destination:
host: mockc.default.svc.cluster.local
subset: v3
fallback:
target:
host: mockc.default.svc.cluster.local
subset: v1
上記の YAML ファイルは、mocka -> mockb -> mockc の呼び出しチェーンのレーンにルーティングルールを作成します。 具体的には、呼び出しチェーン上でパススルーされる version リクエストヘッダーの内容を照合することにより、リクエストが対応するバージョンに転送されます。 たとえば、version: v2 ヘッダーを持つリクエストは、バージョン v2 のサービスに送信されます。 さらに、仮想サービスは次のトラフィックシフトルールも指定します。呼び出しチェーン内のサービスの対応するバージョンが存在しない場合、リクエストはサービスのバージョン v1 にシフトされます。
kubectl を使用して ASM インスタンスに接続し、次のコマンドを実行して仮想サービスを作成します。
kubectl apply -f vs-mock.yaml
イングレスゲートウェイにトラフィックルーティングルールを作成します。
次の内容を含む gw-mock.yaml ファイルを作成します。
YAML ファイルを表示
apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
name: mockgw
namespace: default
spec:
selector:
istio: ingressgateway
servers:
- hosts:
- '*'
port:
name: http
number: 80
protocol: HTTP
---
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: swimlane-ingress-vs-weighted-mock
namespace: default
spec:
gateways:
- default/mockgw
hosts:
- '*'
http:
- name: mock-weighted
route:
- destination:
host: mocka.default.svc.cluster.local
subset: v1
headers:
request:
set:
version: v1
weight: 40
- destination:
host: mocka.default.svc.cluster.local
subset: v2
headers:
request:
set:
version: v2
weight: 30
- destination:
host: mocka.default.svc.cluster.local
subset: v3
headers:
request:
set:
version: v3
weight: 30
上記の YAML ファイルは、mocka -> mockb -> mockc の呼び出しチェーンのイングレスゲートウェイに作成されたトラフィックルーティングルールを示しています。 トラフィックは重みによってルーティングされます。 イングレスゲートウェイに送信されたトラフィックは、4:3:3 の比率で mocka サービスのバージョン v1、v2、および v3 に転送されます。 イングレスゲートウェイがリクエストを mocka サービスに転送すると、イングレスゲートウェイは宛先サービスのバージョンに基づいてリクエストに version ヘッダーを追加し、レーン内のサービスの対応するバージョンが呼び出しチェーンに存在することを保証します。
kubectl を使用して ASM インスタンスに接続し、次のコマンドを実行してトラフィックルーティングルールを作成します。
kubectl apply -f gw-mock.yaml
手順 4 : トラフィックレーンが有効になっていることを確認する
イングレスゲートウェイのパブリック IP アドレスを取得します。 詳細については、「手順 2 : ASM イングレスゲートウェイの IP アドレスを取得する」をご参照ください。
次のコマンドを実行して、環境変数を構成します。 xxx.xxx.xxx.xxx は前の手順で取得した IP アドレスです。
export ASM_GATEWAY_IP=xxx.xxx.xxx.xxx
エンドツーエンドカナリアリリース機能が有効になっているかどうかを確認します。
次のコマンドを実行して、バージョン v1 のサービスのレーンが有効になっているかどうかを確認します。
for i in {1..100}; do curl http://${ASM_GATEWAY_IP} ; echo ''; sleep 1; done;
期待される出力:
-> mocka(version: v1, ip: 192.168.1.27)-> mockb(version: v1, ip: 192.168.1.30)-> mockc(version: v1, ip: 192.168.1.14)
-> mocka(version: v1, ip: 192.168.1.27)-> mockb(version: v1, ip: 192.168.1.30)-> mockc(version: v1, ip: 192.168.1.14)
-> mocka(version: v2, ip: 192.168.1.28)-> mockb(version: v1, ip: 192.168.1.30)-> mockc(version: v2, ip: 192.168.1.1)
-> mocka(version: v3, ip: 192.168.1.26)-> mockb(version: v3, ip: 192.168.1.29)-> mockc(version: v1, ip: 192.168.1.14)
...
出力は、トラフィックが呼び出しチェーン内のサービスのバージョン v1、v2、および v3 に約 4:3:3 の比率で送信され、v1 がベースラインバージョンとして使用されていることを示しています。 呼び出しチェーンにサービスの特定のバージョンが存在しない場合、このサービスのバージョン v1 が呼び出されます。