トラフィックミラーリング機能を使用して、本番トラフィックをテスト クラスターまたはテスト サービス バージョンにミラーリングできます。ミラーリングされた本番トラフィックを使用したテストは、本番環境に影響を与えることなく、バージョンの変更に伴うリスクを軽減します。このトピックでは、トラフィックミラーリングとは何か、サービスメッシュ層でクラスターをまたいでこの機能を使用する方法について説明します。
トラフィックミラーリングとは
マイクロサービス アーキテクチャは、アプリケーションの開発とデプロイを高速化しますが、サービス バージョンの変更にはリスクが伴います。Service Mesh (ASM) は、リスクを軽減するためにトラフィックミラーリング機能を提供します。トラフィックシャドーイングとも呼ばれるこの機能は、本番トラフィックをリアルタイムでミラーリングされたサービスに送信します。ミラーリングされたトラフィックは、本番サービスのクリティカルなリクエスト パスの帯域外で発生します。トラフィックがミラーリングされると、ミラーリングされたサービス バージョンに送信されるリクエストの Host/Authority ヘッダーに -shadow が追加されます。これにより、本番トラフィックとミラーリングされたトラフィックが区別されます。この機能を使用して、クラスターまたはサービス バージョンが本番環境で実行される前に、本番トラフィックをテスト クラスターまたはテスト サービス バージョンにミラーリングできます。これにより、バージョンの変更に伴うリスクが軽減されます。
利点
利点 | 説明 |
本番環境に近いテスト環境でのリスクの少ないバージョンのデプロイ | 本番トラフィックをテスト クラスターまたはテスト サービス バージョンにコピーし、ミラーリングされたユースケースとトラフィックを使用してテストを実行できます。より正確なテスト結果により、本番環境でのデプロイのリスクが軽減されます。 |
本番環境への影響なし |
|
シナリオ
トラフィックミラーリングを使用すると、エンドユーザーに影響を与えることなく、本番環境で実行されているサービスをテストできます。2 つのバージョンのサービスのベンチマーク テストを実行して、新しいバージョンが既存のバージョンと同じ方法で受信リクエストを処理できるかどうかを判断できます。
次の表に、トラフィックミラーリングを使用できる典型的なシナリオを示します。
シナリオ | 説明 |
試運転とシミュレーション テストのための本番トラフィック ミラーリング | テストのために、本番クラスターからテスト クラスターにトラフィックをミラーリングできます。これは、本番環境のクリティカルなリクエスト パスには影響しません。古いシステムを新しいシステムに置き換えたり、変換したりするとします。試運転のために、古いシステムの本番トラフィックをミラーリングして新しいシステムにインポートできます。実験的なアーキテクチャ調整を実行する場合は、シミュレーション テストのために本番トラフィックをミラーリングすることもできます。 |
新しいバージョンの検証 | 本番トラフィックとミラーリングされたトラフィックの出力結果をリアルタイムで比較できます。新しいサービスをリリースする前に、ミラーリングされたトラフィックをドリルで使用できます。すべての本番トラフィックをミラーリングできます。従来の手動ドリルは、サンプル データに基づいて実行されます。(サービスが本番トラフィックにどのように応答するかを予測することは困難です。) ミラーリングされた本番トラフィックを使用すると、悪意のある攻撃を受ける例外的な特殊文字やトークンなど、本番環境のすべての状況をシミュレートできます。これにより、リリースされるサービスの処理能力とトラブルシューティング能力を理解するのに役立ちます。 |
データベース データとテスト データの分離 | データ処理パフォーマンスをテストする場合は、テスト データを空のデータベースにインポートし、本番トラフィックをこのテスト データベースにミラーリングできます。これにより、テスト データが本番データベースのデータから分離されます。 |
実行中のサービスのトラブルシューティング | 実行中のサービスに予期しない問題が発生した場合、オンプレミス ネットワークで問題を再現することは困難です。この場合、一時的なサービスを開始し、実行中のサービスから一時的なサービスにトラフィックをミラーリングしてデバッグできます。このトラブルシューティング方法は、実行中のサービスには影響しません。 |
ユーザー行動のログ記録 | サンプルとデータは、レコメンデーション システム アルゴリズムにとって重要です。アルゴリズム依存アプリケーションの従来の自動テストの最大の課題は、現実世界のユーザー行動データの不足です。トラフィックミラーリングを使用すると、ユーザー行動データをログに保存できます。ログ データは、レコメンデーション システム アルゴリズムを構築するためのシミュレーション テストで使用できます。また、ユーザー プロファイル分析のためのビッグ データ ソースとしても使用できます。 |
トラフィックミラーリングを使用するためのサンプル コード
次の YAML ファイルの例は、Istio でトラフィックミラーリングを使用する方法を示しています。この例では、VirtualService はすべてのトラフィックを v1 サブセットにルーティングし、トラフィックを v1-mirroring サブセットにミラーリングします。リクエストが v1 サブセットに送信されると、リクエストがコピーされ、v1-mirroring サブセットに送信されます。
v1-mirroring サブセットがアプリケーションの v1 バージョンにリクエストを送信した後、アプリケーション ログを表示できます。アプリケーションが呼び出されると、レスポンスは v1 サブセットからのものであることがわかります。また、リクエストが v1-mirroring サブセットにミラーリングされていることもわかります。
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: myapp-traffic-mirroring
spec:
hosts:
- myapp
http:
- route:
- destination:
host: myapp.default.svc.cluster.local
port:
number: 8000
subset: v1
weight: 100
mirror:
host: myapp.default.svc.cluster.local
port:
number: 8000
subset: v1-mirroring
クラスターをまたいでトラフィックミラーリングを有効にする
サービスメッシュ層でのトラフィックミラーリングは、主に、本番トラフィックをリリースされる環境にミラーリングする必要があるシナリオで使用されます。したがって、クロス クラスター トラフィック ミラーリングは一般的です。この例では、クラスター A は本番環境、クラスター B はテスト環境です。リクエストはクラスター A に送信され、クラスター A のイングレス ゲートウェイはトラフィックをクラスター B にミラーリングします。
手順 1: クラスター B にサンプル アプリケーション サービスをデプロイする
次の内容を含む httpbin.yaml ファイルを作成します。
apiVersion: v1 kind: ServiceAccount metadata: name: httpbin --- apiVersion: v1 kind: Service metadata: name: httpbin labels: app: httpbin service: httpbin spec: ports: - name: http port: 8000 targetPort: 80 selector: app: httpbin --- apiVersion: apps/v1 kind: Deployment metadata: name: httpbin-v1 spec: replicas: 1 selector: matchLabels: app: httpbin version: v1 template: metadata: labels: app: httpbin version: v1 spec: serviceAccountName: httpbin containers: - image: docker.io/kennethreitz/httpbin imagePullPolicy: IfNotPresent name: httpbin ports: - containerPort: 80 ---
次のコマンドを実行して、v1 バージョンの
httpbin
アプリケーション サービスをデプロイします。kubectl apply -f httpbin.yaml
手順 2: クラスター B のイングレス ゲートウェイのルーティング ルールを構成する
次の内容を含む httpbin-gateway.yaml ファイルを作成します。
apiVersion: networking.istio.io/v1alpha3 kind: Gateway metadata: name: httpbin-gateway spec: selector: istio: ingressgateway servers: - port: number: 80 name: http protocol: HTTP hosts: - "*" --- apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: httpbin spec: hosts: - "*" gateways: - httpbin-gateway http: - match: - uri: prefix: /headers route: - destination: host: httpbin port: number: 8000
次のコマンドを実行して、ルーティング ルールをデプロイします。
kubectl apply -f httpbin-gateway.yaml
次のコマンドを実行して、クラスター B のイングレス ゲートウェイにアクセスし、サービスが期待どおりに動作するかどうかを確認します。
curl http://{クラスター B のイングレス ゲートウェイの IP アドレス}/headers
出力例:
{ "headers": { "Accept": "*/*", "Host": "47.99.XX.XX", "User-Agent": "curl/7.79.1", "X-Envoy-Attempt-Count": "1", "X-Envoy-External-Address": "120.244.XXX.XXX", "X-Forwarded-Client-Cert": "By=spiffe://cluster.local/ns/default/sa/httpbin;Hash=158e4ef69876550c34d10e3bfbd8d43f5ab481b16ba0e90b4e38a2d53ac****;Subject=\"\";URI=spiffe://cluster.local/ns/istio-system/sa/istio-ingressgateway-service-account" } }
上記の結果が返された場合、サービスは期待どおりに動作しています。
手順 3: クラスター A のサービスメッシュで外部アクセス ルールを構成する
ミラーリングされたサービスのホストは、外部ドメイン名を使用します。ホストの DNS 解決方法を指定するために、サービス エントリを作成する必要があります。
次の内容を含む httpbin-cluster-b.yaml ファイルを作成します。
apiVersion: networking.istio.io/v1alpha3 kind: ServiceEntry metadata: name: httpbin-cluster-b spec: hosts: - httpbin.mirror.cluster-b location: MESH_EXTERNAL ports: - number: 80 # クラスター B のイングレス ゲートウェイのポートを指定します。 name: http protocol: HTTP resolution: STATIC endpoints: - address: 47.95.XX.XX # クラスター B のイングレス ゲートウェイの IP アドレスを指定します。
次のコマンドを実行して、サービス エントリを作成します。
kubectl apply -f httpbin-cluster-b.yaml
次の内容を含む httpbin-gateway.yaml ファイルを作成します。
YAML 構成は、すべてのトラフィックをクラスター A の
httpbin
サービスの v1 バージョンにルーティングし、トラフィックをクラスター B の httpbin サービスにミラーリングします。httpbin.mirror.cluster-b
は、外部サービスにアクセスするために使用されるアドレスです。apiVersion: networking.istio.io/v1alpha3 kind: Gateway metadata: name: httpbin-gateway spec: selector: istio: ingressgateway servers: - port: number: 80 name: http protocol: HTTP hosts: - "*" --- apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: httpbin spec: gateways: - httpbin-gateway hosts: - '*' http: - match: - uri: prefix: /headers mirror: host: httpbin.mirror.cluster-b port: number: 80 mirrorPercentage: value: 50 route: - destination: host: httpbin port: number: 8000 subset: v1
注: httpbin.mirror.cluster-b 宛てのトラフィックは、元の宛先へのトラフィックと同じです。唯一の違いは、Host/Authority ヘッダーに
-shadow
が追加されていることです。上記の YAML 構成では、ミラーリングされたトラフィックの Host/Authority ヘッダーはhttpbin.mirror.cluster-b
ではなく、-shadow
サフィックスが付いた元の要求ヘッダーです。mirror セクションの host フィールドは、トラフィックの転送先アドレスを見つけるためだけに使用され、元の Host ヘッダーは変更しません。次のコマンドを実行して、ルーティング ルールをデプロイします。
kubectl apply -f httpbin-gateway.yaml
クラスター A のイングレス ゲートウェイ ポッドの Envoy config dump を表示します。
"routes": [ { "match": { "prefix": "/headers", "case_sensitive": true }, "route": { "cluster": "outbound|8000|v1|httpbin.default.svc.cluster.local", "timeout": "0s", "retry_policy": { "retry_on": "connect-failure,refused-stream,unavailable,cancelled,retriable-status-codes", "num_retries": 2, "retry_host_predicate": [ { "name": "envoy.retry_host_predicates.previous_hosts", "typed_config": { "@type": "type.googleapis.com/envoy.extensions.retry.host.previous_hosts.v3.PreviousHostsPredicate" } } ], "host_selection_retry_max_attempts": "5", "retriable_status_codes": [ 503 ] }, "request_mirror_policies": [ { "cluster": "outbound|80||httpbin.mirror.cluster-b", "runtime_fraction": { "default_value": { "numerator": 500000, "denominator": "MILLION" } }, "trace_sampled": false } ],
上記のサンプル コードでは、
request_mirror_policies
フィールドはリクエスト トラフィック ミラーリングのポリシーを指定し、cluster
フィールドはミラーリングされたトラフィックの送信先サービスを指定し、runtime_fraction
フィールドはミラーリングされるトラフィックの比率を指定します。numerator
フィールドは 500000 に設定され、denominator
フィールドは MILLION に設定されており、これは 50% を示します。