Service Mesh (ASM) allows you to flexibly define various complex request routing rules by creating custom virtual services. Request routing rules can be used together with traffic lanes to implement comprehensive and multi-dimensional traffic management and maximizes the observability, operability, and user experience of applications. This topic describes how to create custom virtual services to route traffic for traffic lanes in permissive mode.
In this example, you can modify the steps in Scenario 1: Pass through trace IDs in traces and Scenario 2: Pass through custom request headers in traces to create custom virtual services and route traffic of traffic lanes in permissive mode. Make sure that you have read and understood the Use traffic lanes in permissive mode to manage end-to-end traffic topic and related content.
Scenarios
The ASM console has a built-in request routing rule creation feature. After you create virtual services on the ASM ingress gateway corresponding to traffic lanes, request routing rules are created for traffic lanes. This way, the ASM ingress gateway can forward requests to different traffic lanes.
Request routing rules of traffic lanes include matching rules for request headers and request paths. You can create custom virtual services to define more complex matching rules or create custom request routes.
When you use a custom virtual service to route traffic of a traffic lane, we recommend that you do not use the built-in request routing rule creation feature to create request routing rules for the traffic lane. This is because the custom virtual service may conflict with the request routing rules created by using the built-in request routing rule creation feature. As a result, abnormal or unexpected traffic distribution may occur.
Create a custom virtual service on an ASM ingress gateway
Scenario 1: Pass through trace IDs in traces is an example. In substep 3 Create drainage rules for the three lanes of Step 1, change the step of creating a traffic routing rule to the step of creating a virtual service by using the following content. For more information, see Manage virtual services.
apiVersion: networking.istio.io/v1beta1 kind: VirtualService metadata: name: swimlane-ingress-vs-custom namespace: istio-system spec: gateways: - istio-system/ingressgateway hosts: - '*' http: - match: # This matching rule exactly matches env: dev request headers. - headers: env: exact: dev name: dev-route route: - destination: host: mocka.default.svc.cluster.local # The destination service for traffic forwarding. subset: s2 # The name of a traffic lane. weight: 50 headers: request: set: x-asm-prefer-tag: s2 # Configure a request routing header for the traffic lane. - destination: host: mocka.default.svc.cluster.local # The destination service for traffic forwarding. subset: s3 # The name of a traffic lane. fallback: target: host: mocka.default.svc.cluster.local subset: s1 weight: 50 headers: request: set: x-asm-prefer-tag: s3 # Configure a request routing header for the traffic lane. - name: base-route route: - destination: host: mocka.default.svc.cluster.local # The destination service for traffic forwarding. subset: s1 # The name of a traffic lane. headers: request: set: x-asm-prefer-tag: s1 # Configure a request routing header for the traffic lane.
NoteWhen you create a custom virtual service, the value of
headers.request.set
in the preceding YAML file must be the same as the corresponding request routing header. For example, in Scenario 2: Pass through custom request headers in traces, the end-to-end pass-through request header is the same as the request routing header. Therefore, the values ofheaders.request.set
under the correspondingroute
fields are changed tomy-trace-id: s1
,my-trace-id: s2
, andmy-trace-id: s3
, respectively.Run the commands in Step 3: Verify that the end-to-end canary release feature takes effect. The following output is generated when you access services in the s1, s2, and s3 lanes:
-> mocka(version: v1, ip: 192.168.0.50)-> mockb(version: v1, ip: 192.168.0.46)-> mockc(version: v1, ip: 192.168.0.48)
Run the following command to check the result when you access services in the s1 lane with an
env: dev
request header:for i in {1..100}; do curl -H 'x-asm-prefer-tag: s1' -H 'env: dev' -H'my-trace-id: x000'$i http://${ASM_GATEWAY_IP}/mock ; echo ''; sleep 1; done;
Expected output:
The output indicates that when you access services in the s1 lane with an
env: dev
request header, two types of traces v1->v3->v1 and v2->v1->v2 are involved, and the ratio of requests in the two types of traces is about 50:50. That is, requests with theenv: dev
request headers are routed to the s2 and s3 lanes at a ratio of 50:50, and the remaining requests are routed to the s1 lane.
The preceding virtual service specifies a custom routing rule on the ASM gateway to forward traffic to different traffic lanes. When you create custom virtual services to route requests for traffic lanes in strict mode, if you want to route requests to a specific traffic lane, you need to only set the route.destination.subset
field to the name of the traffic lane. After a request is routed to a traffic lane, subsequent requests in the trace are always routed to the traffic lane.
Create custom virtual services on sidecar proxies
In addition to creating custom virtual services on an ASM ingress gateway, you can also specify request routing rules for applications in a cluster to access services in traffic lanes by creating virtual services on all sidecar proxies. Different from custom virtual services on an ASM ingress gateway, gateway
fields are no longer required for virtual services on sidecar proxies. You need to specify the cluster domain of the mocka
service In the hosts
field. Sample YAML file:
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: swimlane-ingress-vs-custom
namespace: istio-system
spec:
hosts:
- mocka.default.svc.cluster.local
http:
- match: # This matching rule exactly matches env: dev request headers.
- headers:
env:
exact: dev
name: dev-route
route:
- destination:
host: mocka.default.svc.cluster.local # The destination service for traffic forwarding.
subset: s2 # The name of a traffic lane.
weight: 50
headers:
request:
set:
x-asm-prefer-tag: s2 # Configure a request routing header for the traffic lane.
- destination:
host: mocka.default.svc.cluster.local # The destination service for traffic forwarding.
subset: s3 # The name of a traffic lane.
weight: 50
fallback:
target:
host: mocka.default.svc.cluster.local
subset: s1
headers:
request:
set:
x-asm-prefer-tag: s3 # Configure a request routing header for the traffic lane.
- name: base-route
route:
- destination:
host: mocka.default.svc.cluster.local # The destination service for traffic forwarding.
subset: s1 # The name of a traffic lane.
headers:
request:
set:
x-asm-prefer-tag: s1 # Configure a request routing header for the traffic lane.
Similar to the Create a custom virtual service on an ASM ingress gateway step, the value of headers.request.set
in the preceding YAML file must be the same as the corresponding request routing header.
Run the following three commands to access services in the s1, s2, and s3 lanes without the
env: dev
request header after you create custom virtual services on sidecar proxies:kubectl exec -it deploy/sleep -c sleep -- sh -c 'for i in $(seq 1 100); do curl -H "my-trace-id: s1" http://mocka:8000; echo ""; sleep 1; done;' kubectl exec -it deploy/sleep -c sleep -- sh -c 'for i in $(seq 1 100); do curl -H "my-trace-id: s2" http://mocka:8000; echo ""; sleep 1; done;' kubectl exec -it deploy/sleep -c sleep -- sh -c 'for i in $(seq 1 100); do curl -H "my-trace-id: s3" http://mocka:8000; echo ""; sleep 1; done;'
Expected output:
-> mocka(version: v1, ip: 192.168.0.50)-> mockb(version: v1, ip: 192.168.0.46)-> mockc(version: v1, ip: 192.168.0.48)
The output indicates that all requests without the
env: dev
request header are sent to the s1 lane.Run the following three commands to access services in the s1, s2, and s3 lanes with the
env: dev
request header after you create custom virtual services on sidecar proxies:kubectl exec -it deploy/sleep -c sleep -- sh -c 'for i in $(seq 1 100); do curl -H "my-trace-id: s1" -H "env: dev" http://mocka:8000; echo ""; sleep 1; done;' kubectl exec -it deploy/sleep -c sleep -- sh -c 'for i in $(seq 1 100); do curl -H "my-trace-id: s2" -H "env: dev" http://mocka:8000; echo ""; sleep 1; done;' kubectl exec -it deploy/sleep -c sleep -- sh -c 'for i in $(seq 1 100); do curl -H "my-trace-id: s3" -H "env: dev" http://mocka:8000; echo ""; sleep 1; done;'
Expected output:
The output is the same as that in Create a custom virtual service on an ASM ingress gateway. That is, when a service in a cluster calls the mocka service in a traffic lane, subsequent requests in the trace are always routed to the traffic lane.