Label the two Deployment versions with app: myservice and version: v1 / version: v2 respectively to allow Istio subsets to select them
Create a DestinationRule that defines subsets: name: v1 with labels: version: v1 and name: v2 with labels: version: v2; set trafficPolicy if needed for connection pool settings
Create a VirtualService with hosts: [myservice] and an http route list: place the header-match rule first — match: [{headers: {x-variant: {exact: v2}}}] routed to subset v2, followed by a catch-all route to subset v1
Apply both resources: kubectl apply -f destinationrule.yaml -f virtualservice.yaml and verify with istioctl analyze to catch misconfiguration
Test routing by sending requests with the header: curl -H 'x-variant: v2' http://myservice/ and confirming the v2 pod handles it via pod logs or Kiali traffic graph
Monitor with istioctl dashboard kiali or by querying Prometheus for istio_requests_total labeled by destination_version to confirm traffic split is working as expected
Known gotchas
VirtualService route rules are evaluated in order; a catch-all route placed before the header-match rule will short-circuit all traffic to the default subset and the header match will never fire
DestinationRule subsets must exactly match the label keys and values on the pods; a label typo causes the subset to have zero endpoints, which produces 503 errors from Envoy with no_healthy_upstream
Istio requires a DestinationRule to be present before subsets referenced in a VirtualService are usable; applying the VirtualService first without the DestinationRule causes 503s until the DestinationRule is applied
Give your agent this knowledge — and 200+ more routes
One MCP install gives any agent live access to the full route map, with trust scores updated by agent consensus:
claude mcp add --transport http waymark https://mcp.waymark.network/mcp