新しいサービスバージョンをリリースしたり、システムを移行したりする際、合成データのみでの検証では、エッジケース入力や悪意のあるトークンといった実世界の条件を再現することはできません。Service Mesh (ASM) のトラフィックミラーリングは、本番リクエストをリアルタイムで個別のサービスまたはクラスターにコピーするため、本番環境に影響を与えることなく、実際のトラフィックパターンに対してテストできます。
トラフィックミラーリングの仕組み
トラフィックミラーリング (シャドウイングとも呼ばれます) は、受信リクエストを複製し、ミラーリングされた送信先に送信します。その動作は、次の 3 つのメカニズムによって定義されます。
帯域外処理: ミラーリングされたトラフィックは、プライマリリクエストパスの外部で処理されます。ミラーリングされた送信先での障害は、本番応答に影響を与えません。
ファイアアンドフォーゲット: ミラーリングされた送信先からの応答は破棄されます。プライマリサービスは、ミラーからの応答を待たずに自身の応答を返します。
ヘッダーの区別: ミラーリングされたリクエストには、Host/Authority ヘッダーに
-shadowが追加されるため、ログでミラーリングされたトラフィックと本番トラフィックを区別できます。
ユースケース
| ユースケース | 説明 |
|---|---|
| リリース前検証 | リリース前に本番トラフィックを新しいサービスバージョンにミラーリングします。サンプルデータに基づく手動ドリルとは異なり、ミラーリングされたトラフィックは、特殊文字や悪意のある入力などのエッジケースを含む実世界の条件を再現します。 |
| システム移行 | レガシーシステムを置き換えたり変換したりする前に、試行実行のために古いシステムから新しいシステムに本番トラフィックをミラーリングします。 |
| アーキテクチャ実験 | アーキテクチャ変更の影響をコミットする前にシミュレートするために、トラフィックをテスト環境にミラーリングします。 |
| データベース分離 | テストデータを空のデータベースにインポートし、本番トラフィックをそれにミラーリングして、テストデータを本番データから完全に分離します。 |
| ライブデバッグ | 一時的なサービスを開始し、実行中の本番サービスからトラフィックをミラーリングして、本番環境を中断することなく問題を再現およびデバッグします。 |
| ユーザー動作ログ記録 | レコメンデーションシステムのトレーニングまたはユーザー プロファイル分析のための、ミラー化されたトラフィックを通じた実際のユーザー動作データの収集。 |
VirtualService 構成例
トラフィックミラーリングルールは VirtualService で定義されます。次の例では、すべてのトラフィックを 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 # ミラー送信先リクエストが v1 サブセットに到達すると、同一のコピーが v1-mirroring に送信されます。ミラーリングされたサブセットのアプリケーションログをチェックして、リクエストが到着していることを確認します。
クラスター A からクラスター B への本番トラフィックのミラーリング
トラフィックミラーリングは、ほとんどの場合クラスターにまたがります。本番クラスターがトラフィックを個別のテストクラスターにミラーリングします。次の手順では、クラスター A (本番) がクラスター B (テスト) にトラフィックをミラーリングするように構成します。

事前準備として、以下を確認してください:
2 つの Kubernetes クラスター (クラスター A とクラスター B) がメッシュに追加された ASM インスタンス
両方のクラスターにアクセスできるように構成された
kubectl両方のクラスターにデプロイされたイングレスゲートウェイ
ステップ 1: クラスター B にサンプルアプリケーションをデプロイする
ミラーリングされたトラフィックを受信するために、クラスター B に httpbin サービスをデプロイします。
次の内容で httpbin.yaml という名前のファイルを作成します。
構成を適用します。
kubectl apply -f httpbin.yamlPod が実行中であることを確認します。
kubectl get pods -l app=httpbin出力には、
httpbin-v1Pod がRunningステータスで表示されるはずです。
ステップ 2: クラスター B のイングレスゲートウェイのルーティングルールを構成する
クラスター B のイングレスゲートウェイが受信リクエストを httpbin サービスにルーティングするように、Gateway と VirtualService をセットアップします。
次の内容で httpbin-gateway.yaml という名前のファイルを作成します。
構成を適用します。
kubectl apply -f httpbin-gateway.yamlイングレスゲートウェイを通じてサービスが到達可能であることを確認します。
curl http://<cluster-b-ingress-gateway-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" } }応答に
headersオブジェクトが含まれている場合、サービスは正しく動作しています。
ステップ 3: クラスター A からクラスター B へのトラフィックミラーリングを構成する
このステップでは、クラスター A がクラスター B にトラフィックをミラーリングするようにします。クラスター B を外部送信先として登録する ServiceEntry と、ミラーリングルールを定義する VirtualService の 2 つのリソースが必要です。
クラスター B の ServiceEntry を作成する
クラスター B のイングレスゲートウェイはクラスター A のメッシュの外にあります。ホスト名で到達可能にするために ServiceEntry を作成します。
次の内容で httpbin-cluster-b.yaml という名前のファイルを作成します。
<cluster-b-ingress-ip>をクラスター B のイングレスゲートウェイの実際の IP アドレスに置き換えます。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: <cluster-b-ingress-ip> # クラスター B のイングレスゲートウェイ IP に置き換えます構成を適用します。
kubectl apply -f httpbin-cluster-b.yaml
クラスター A にミラーリングルールを作成する
クラスター A の httpbin の v1 サブセットに本番トラフィックをルーティングし、そのトラフィックの一部をクラスター B にミラーリングする Gateway と VirtualService を構成します。
次の内容で httpbin-gateway.yaml という名前のファイルを作成します。
重要mirrorセクションのhostフィールドは、ミラーリングされたトラフィックの送信先を決定しますが、元の Host ヘッダーは変更しません。ミラーリングされたリクエストは、-shadowが追加された元の Host/Authority ヘッダーを保持します。たとえば、ミラーリングされたトラフィックの Host ヘッダーはhttpbin.mirror.cluster-bではなく、-shadowが追加された元のリクエストヘッダーです。構成を適用します。
kubectl apply -f httpbin-gateway.yaml
Envoy 構成の確認
クラスター A のイングレスゲートウェイ Pod の Envoy 構成ダンプを検査して、ミラーリングポリシーがアクティブであることを確認します。
ルート構成で、request_mirror_policies セクションを見つけます。
"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 | ミラーリングされたトラフィックの送信先クラスター (outbound|80||httpbin.mirror.cluster-b) |
runtime_fraction.numerator / denominator | ミラー比率。500000 / MILLION = トラフィックの 50% がミラーリングされます |
route.cluster | 本番トラフィックのプライマリ送信先 (outbound|8000|v1|httpbin.default.svc.cluster.local) |
request_mirror_policies セクションが正しいクラスターと比率の値で表示される場合、トラフィックミラーリングは正しく構成されています。