When multiple versions of a service run in parallel, you need to control which version handles each request. A service mesh proxy evaluates each HTTP request URI against match rules defined in a VirtualService and routes traffic to specific service versions based on URI patterns. Three match types are supported: exact, prefix, and regular expression.
Match types
| Match type | Field | Behavior |
|---|---|---|
| Exact | exact | Case-sensitive full-string match. /hello matches only /hello, not /hello/ or /Hello. |
| Prefix | prefix | Case-sensitive prefix match. /api matches /api, /api/v1, and /api/users, but not /Api or /application. |
| Regular expression | regex | RE2 regex match. ^/api/v[0-9]+/.*$ matches /api/v1/users and /api/v2/items, but not /api/latest/users. |
Case sensitivity: exact and prefix matches are case-sensitive by default. For case-insensitive matching, use regex with the (?i) flag (for example, (?i)^/hello$), or set ignoreUriCase: true in the match block.
Prerequisites
Complete the preparations and deploy the helloworld and sleep services. For more information, see Preparations.
Step 1: Verify that the services are running
Before adding a match rule, confirm that requests reach the helloworld service.
Open a shell in the
sleeppod from the kubeconfig environment of your ACK cluster:kubectl exec -it deploy/sleep -- shSend a request to the
helloworldservice:Without any routing rules, either
helloworld-v1orhelloworld-v2responds at random:curl helloworld:5000/helloHello version: v2, instance: helloworld-v2-7d48f6b995-6**** Hello version: v1, instance: helloworld-v1-6986f64596-s****
Step 2: Create a VirtualService with a URI match rule
Apply a VirtualService that routes requests to helloworld-v1 based on the URI. The following examples show each match type. For more information about managing virtual services, see Manage virtual services.
Exact match
Route requests only when the URI is exactly /hello:
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: helloworld-vs
namespace: default
spec:
hosts:
- helloworld
http:
- match:
- uri:
exact: /hello
route:
- destination:
host: helloworld-v1Prefix match
Route all requests whose URI starts with /hello (including /hello, /hello/greeting, and /hello/v2):
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: helloworld-vs
namespace: default
spec:
hosts:
- helloworld
http:
- match:
- uri:
prefix: /hello
route:
- destination:
host: helloworld-v1Regular expression match
Route requests whose URI matches a regex pattern. This example matches paths such as /hello/v1 and /hello/v2:
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: helloworld-vs
namespace: default
spec:
hosts:
- helloworld
http:
- match:
- uri:
regex: ^/hello/v[0-9]+$
route:
- destination:
host: helloworld-v1ASM uses the RE2 regex engine. PCRE features such as lookaheads are not supported.
Combine multiple conditions
To match a URI and a header in the same request, add both conditions to the same match entry:
http:
- match:
- uri:
prefix: /hello
headers:
end-user:
exact: jason
route:
- destination:
host: helloworld-v1To match either of two URIs, add separate match entries:
http:
- match:
- uri:
exact: /hello
- uri:
prefix: /greeting
route:
- destination:
host: helloworld-v1Step 3: Verify the match rule
Open a shell in the
sleeppod:kubectl exec -it deploy/sleep -- shSend a request to the
/hellopath:With the exact match rule applied,
helloworld-v1always responds:curl helloworld:5000/helloHello version: v1, instance: helloworld-v1-6986f64596-s****
Rule evaluation order
Match rules in a VirtualService are evaluated top to bottom. The first matching rule wins. If no rule matches, the request falls through without a defined route.
Order matters. Place more specific rules (exact matches) above broader rules (prefix matches). A broad prefix rule placed above a specific exact rule intercepts requests before the exact rule is evaluated.
AND within a match block. Multiple conditions in the same
matchentry must all be true for the rule to match.OR across match blocks. Multiple
matchentries under the samehttprule are evaluated independently. A request that satisfies any one of them triggers the route.Always add a default route. Include a catch-all rule at the bottom of the VirtualService to handle unmatched requests. Without one, unmatched traffic has no explicit routing and may not reach the intended destination.
URI match field reference
Fields available in an HTTPMatchRequest for URI matching:
| Field | Type | Description |
|---|---|---|
uri.exact | string | Matches when the URI is identical to the specified value. Case-sensitive. |
uri.prefix | string | Matches when the URI starts with the specified value. Case-sensitive. |
uri.regex | string | Matches when the URI satisfies the specified RE2 regular expression. |
ignoreUriCase | bool | When set to true, URI matching becomes case-insensitive for exact and prefix. Default: false. |
Best practices
Start with the most specific rule. Place exact matches first, then prefix matches, and regex matches last.
Add a default catch-all route. Place a route without a
matchblock at the end of the VirtualService to handle any request that does not match a preceding rule.Keep regex patterns simple. Complex regular expressions increase proxy latency and are harder to debug. Prefer exact or prefix matches when possible.
Test incrementally. Apply one match rule at a time and verify the routing behavior before adding more rules.