istio.io/content/docs/concepts/traffic-management/rules-configuration.md

728 lines
21 KiB
Markdown

---
title: Rules Configuration
description: Provides a high-level overview of the configuration model used by Istio to configure traffic management rules in the service mesh.
weight: 50
---
Istio provides a simple configuration model to
control how API calls and layer-4 traffic flow across various
services in an application deployment. The configuration model allows an operator to
configure service-level properties such as circuit breakers, timeouts,
retries, as well as set up common continuous deployment tasks such as
canary rollouts, A/B testing, staged rollouts with %-based traffic splits,
etc.
For example, a simple rule to send 100% of incoming traffic for a *reviews*
service to version "v1" can be described using a configuration as
follows:
```yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: reviews
spec:
hosts:
- reviews
http:
- route:
- destination:
host: reviews
subset: v1
```
This configuration says that traffic sent to the *reviews* service
(specified in the `hosts` field) should be routed to the v1 subset
of the underlying *reviews* service instances.
The route `subset` specifies the name of a defined subset in
a corresponding destination rule configuration:
```yaml
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: reviews
spec:
host: reviews
subsets:
- name: v1
labels:
version: v1
- name: v2
labels:
version: v2
```
A subset specifies one or more labels that identify version-specific instances.
For example, in a Kubernetes deployment of Istio, "version: v1" indicates that
only pods containing the label "version: v1" will receive traffic.
Rules can be configured using the
[istioctl CLI](/docs/reference/commands/istioctl/), or in a Kubernetes
deployment using the `kubectl` command instead, although only `istioctl` will
perform model validation and is recommended. See the
[configuring request routing task](/docs/tasks/traffic-management/request-routing/)
for examples.
There are four traffic management configuration resources in Istio:
**VirtualService**, **DestinationRule**, **ServiceEntry**, and **Gateway**.
A few important aspects of these resources are described below.
See [networking reference](/docs/reference/config/istio.networking.v1alpha3/)
for detailed information.
## Virtual Services
A [VirtualService](/docs/reference/config/istio.networking.v1alpha3/#VirtualService)
defines the rules that control how requests for a service are routed within an Istio service mesh.
For example, a virtual service could route requests to different versions of a service or, in fact,
to a completely different service than was requested.
Requests can be routed based on the request source and destination, HTTP paths and
header fields, and weights associated with individual service versions.
### Rule destinations
Routing rules correspond to one or more request destination hosts that are specified in
a `VirtualService` configuration. These hosts may or may not be the same as the actual
destination workload and may not even correspond to an actual routable service in the mesh.
For example, to define routing rules for requests to the *reviews* service using its internal
mesh name `reviews` or via host `bookinfo.com`, a `VirtualService` could have a `hosts` field
something like this:
```yaml
hosts:
- reviews
- bookinfo.com
```
The `hosts` field specifies, implicitly or explicitly, one or more fully qualified
domain names (FQDN). The short name `reviews`, above, would implicitly
expand to an implementation specific FQDN. For example, in a Kubernetes environment
the full name is derived from the cluster and namespace of the `VirtualSevice`
(e.g., `reviews.default.svc.cluster.local`).
### Qualify rules by source/headers
Rules can optionally be qualified to only apply to requests that match some
specific criteria such as the following:
_1. Restrict to a specific caller_. For example, a rule
can indicate that it only applies to calls from workloads (pods) implementing
the *reviews* service.
```yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: ratings
spec:
hosts:
- ratings
http:
- match:
sourceLabels:
app: reviews
...
```
The value of `sourceLabels` depends on the implementation of the service.
In Kubernetes, for example, it would probably be the same labels that are used
in the pod selector of the corresponding Kubernetes service.
_2. Restrict to specific versions of the caller_. For example, the following
rule refines the previous example to only apply to calls from version "v2"
of the *reviews* service.
```yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: ratings
spec:
hosts:
- ratings
http:
- match:
- sourceLabels:
app: reviews
version: v2
...
```
_3. Select rule based on HTTP headers_. For example, the following rule will
only apply to an incoming request if it includes a "cookie" header that
contains the substring "user=jason".
```yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: reviews
spec:
hosts:
- reviews
http:
- match:
- headers:
cookie:
regex: "^(.*?;)?(user=jason)(;.*)?$"
...
```
If more than one header is provided, then all of the
corresponding headers must match for the rule to apply.
Multiple criteria can be set simultaneously. In such a case, AND or OR
semantics apply, depending on the nesting.
If multiple criteria are nested in a single match clause, then the conditions
are ANDed. For example, the following rule only applies if the source of the
request is "reviews:v2" AND the "cookie" header containing "user=jason" is
present.
```yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: ratings
spec:
hosts:
- ratings
http:
- match:
- sourceLabels:
app: reviews
version: v2
headers:
cookie:
regex: "^(.*?;)?(user=jason)(;.*)?$"
...
```
If instead, the criteria appear in separate match clauses, then only one
of the conditions must apply (OR semantics):
```yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: ratings
spec:
hosts:
- ratings
http:
- match:
- sourceLabels:
app: reviews
version: v2
- headers:
cookie:
regex: "^(.*?;)?(user=jason)(;.*)?$"
...
```
### Split traffic between service versions
Each route rule identifies one or more weighted backends to call when the rule is activated.
Each backend corresponds to a specific version of the destination service,
where versions can be expressed using _labels_.
If there are multiple registered instances with the specified label(s),
they will be routed to based on the load balancing policy configured for the service,
or round-robin by default.
For example, the following rule will route 25% of traffic for the *reviews* service to instances with
the "v2" label and the remaining traffic (i.e., 75%) to "v1".
```yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: reviews
spec:
hosts:
- reviews
http:
- route:
- destination:
host: reviews
subset: v1
weight: 75
- destination:
host: reviews
subset: v2
weight: 25
```
### Timeouts and retries
By default, the timeout for http requests is 15 seconds,
but this can be overridden in a route rule as follows:
```yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: ratings
spec:
hosts:
- ratings
http:
- route:
- destination:
host: ratings
subset: v1
timeout: 10s
```
The number of retries for a given http request can also be specified in a route rule.
The maximum number of attempts, or as many as possible within the default or overridden timeout period,
can be set as follows:
```yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: ratings
spec:
hosts:
- ratings
http:
- route:
- destination:
host: ratings
subset: v1
retries:
attempts: 3
perTryTimeout: 2s
```
Note that request timeouts and retries can also be
[overridden on a per-request basis](/docs/concepts/traffic-management/handling-failures#fine-tuning).
See the [request timeouts task](/docs/tasks/traffic-management/request-timeouts/) for a demonstration of timeout control.
### Injecting faults in the request path
A route rule can specify one or more faults to inject
while forwarding http requests to the rule's corresponding request destination.
The faults can be either delays or aborts.
The following example will introduce a 5 second delay in 10% of the requests to the "v1" version of the *ratings* microservice.
```yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: ratings
spec:
hosts:
- ratings
http:
- fault:
delay:
percent: 10
fixedDelay: 5s
route:
- destination:
host: ratings
subset: v1
```
The other kind of fault, abort, can be used to prematurely terminate a request,
for example, to simulate a failure.
The following example will return an HTTP 400 error code for 10%
of the requests to the *ratings* service "v1".
```yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: ratings
spec:
hosts:
- ratings
http:
- fault:
abort:
percent: 10
httpStatus: 400
route:
- destination:
host: ratings
subset: v1
```
Sometimes delays and abort faults are used together. For example, the following rule will delay
by 5 seconds all requests from the *reviews* service "v2" to the *ratings* service "v1" and
then abort 10 percent of them:
```yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: ratings
spec:
hosts:
- ratings
http:
- match:
- sourceLabels:
app: reviews
version: v2
fault:
delay:
fixedDelay: 5s
abort:
percent: 10
httpStatus: 400
route:
- destination:
host: ratings
subset: v1
```
To see fault injection in action, see the [fault injection task](/docs/tasks/traffic-management/fault-injection/).
### HTTP route rules have precedence
When there are multiple rules for a given destination,
they are evaluated in the order they appear
in the `VirtualService`, i.e., the first rule
in the list has highest priority.
**Why is priority important?** Whenever the routing story for a particular
service is purely weight based, it can be specified in a single rule.
When, on the other hand, other criteria
(e.g., requests from a specific user) are being used to route traffic, more
than one rule will be needed to specify the routing. This is where the
rule priority must be carefully considered to make sure that the rules are
evaluated in the right order.
A common pattern for generalized route specification is to provide one or
more higher priority rules that qualify rules by source/headers,
and then provide a single weight-based rule with no match
criteria last to provide the weighted distribution of
traffic for all other cases.
For example, the following `VirtualService` contains 2 rules that, together,
specify that all requests for the *reviews* service that includes a header
named "Foo" with the value "bar" will be sent to the "v2" instances.
All remaining requests will be sent to "v1".
```yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: reviews
spec:
hosts:
- reviews
http:
- match:
- headers:
Foo:
exact: bar
route:
- destination:
host: reviews
subset: v2
- route:
- destination:
host: reviews
subset: v1
```
Notice that the header-based rule has the higher priority. If
it was lower, these rules wouldn't work as expected since the weight-based
rule, with no specific match criteria, would be evaluated first which would
then simply route all traffic to "v1", even requests that include the
matching "Foo" header. Once a rule is found that applies to the incoming
request, it will be executed and the rule-evaluation process will
terminate. That's why it's very important to carefully consider the
priorities of each rule when there is more than one.
## Destination Rules
A [DestinationRule](/docs/reference/config/istio.networking.v1alpha3/#DestinationRule)
configures the set of policies to be applied to a request after `VirtualService` routing has occurred. They are
intended to be authored by service owners, describing the circuit breakers, load balancer settings, TLS settings, etc..
A `DestinationRule` also defines addressable `subsets` (i.e., named versions) of the corresponding destination host.
These subsets are used in `VirtualService` route specifications when sending traffic to specific versions of the service.
The following `DestinationRule` configures policies and subsets for the reviews service:
```yaml
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: reviews
spec:
host: reviews
trafficPolicy:
loadBalancer:
simple: RANDOM
subsets:
- name: v1
labels:
version: v1
- name: v2
labels:
version: v2
trafficPolicy:
loadBalancer:
simple: ROUND_ROBIN
- name: v3
labels:
version: v3
```
Notice that multiple policies (e.g., default and v2-specific) can be
specified in a single `DestinationRule` configuration.
### Circuit breakers
A simple circuit breaker can be set based on a number of criteria such as connection and request limits.
For example, the following `DestinationRule`
sets a limit of 100 connections to *reviews* service version "v1" backends.
```yaml
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: reviews
spec:
host: reviews
subsets:
- name: v1
labels:
version: v1
trafficPolicy:
connectionPool:
tcp:
maxConnections: 100
```
See the [circuit-breaking task](/docs/tasks/traffic-management/circuit-breaking/) for a demonstration of circuit breaker control.
### DestinationRule evaluation
Similar to route rules, policies are associated with a
particular *host* however if they are subset specific,
activation depends on route rule evaluation results.
The first step in the rule evaluation process evaluates the route rules in
the `VirtualService` corresponding to the requested *host*, if there are any defined,
to determine the subset (i.e., specific
version) of the destination service that the current request will be routed
to. Next, the set of policies corresponding to the selected subset, if any,
are evaluated to determine if they apply.
**NOTE:** One subtlety of the algorithm to keep in mind is that policies
that are defined for specific subsets will only be applied if
the corresponding subset is explicitly routed to. For example,
consider the following configuration, as the one and only rule defined for the
*reviews* service (i.e., there are no route rules in a corresponding `VirtualService`.
```yaml
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: reviews
spec:
host: reviews
subsets:
- name: v1
labels:
version: v1
trafficPolicy:
connectionPool:
tcp:
maxConnections: 100
```
Since there is no specific route rule defined for the *reviews*
service, default round-robin routing behavior will apply, which will
presumably call "v1" instances on occasion, maybe even always if "v1" is
the only running version. Nevertheless, the above policy will never be
invoked since the default routing is done at a lower level. The rule
evaluation engine will be unaware of the final destination and therefore
unable to match the subset policy to the request.
You can fix the above example in one of two ways. You can either move the
traffic policy up a level to make it apply to any version:
```yaml
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: reviews
spec:
host: reviews
trafficPolicy:
connectionPool:
tcp:
maxConnections: 100
subsets:
- name: v1
labels:
version: v1
```
or, better yet, define proper route rules for the service.
For example, you can add a simple route rule for "reviews:v1".
```yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: reviews
spec:
hosts:
- reviews
http:
- route:
- destination:
host: reviews
subset: v1
```
Although the default Istio behavior conveniently sends traffic from any
source to all versions of a destination service
without any rules being set, as soon as version discrimination is desired
rules are going to be needed.
Therefore, setting a default rule for every service, right from the
start, is generally considered a best practice in Istio.
## Service Entries
A [ServiceEntry](/docs/reference/config/istio.networking.v1alpha3/#ServiceEntry)
is used to add additional entries into the service registry that Istio maintains internally.
It is most commonly used to enable requests to services outside of an Istio service mesh.
For example, the following `ServiceEntry` can be used to allow external calls to services hosted
under the `*.foo.com` domain.
```yaml
apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
name: foo-ext-svc
spec:
hosts:
- *.foo.com
ports:
- number: 80
name: http
protocol: HTTP
- number: 443
name: https
protocol: HTTPS
```
The destination of a `ServiceEntry` is specified using the `hosts` field, which
can be either a fully qualified or wildcard domain name.
It represents a white listed set of one or more services that services
in the mesh are allowed to access.
A `ServiceEntry` is not limited to external service configuration,
it can be of two types: mesh-internal or mesh-external.
Mesh-internal entries are like all other internal services but are used to explicitly add services
to the mesh. They can be used to add services as part of expanding the service mesh to include unmanaged infrastructure
(e.g., VMs added to a Kubernetes-based service mesh).
Mesh-external entries represent services external to the mesh.
For them, mTLS authentication is disabled and policy enforcement is performed on the client-side,
instead of on the usual server-side for internal service requests.
Service entries work well in conjunction with virtual services
and destination rules as long as they refer to the services using matching
`hosts`. For example, the following rule can be used in conjunction with
the above `ServiceEntry` rule to set a 10s timeout for calls to
the external service at `bar.foo.com`.
```yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: bar-foo-ext-svc
spec:
hosts:
- bar.foo.com
http:
- route:
- destination:
host: bar.foo.com
timeout: 10s
```
Rules to redirect and forward traffic, to define retry,
timeout and fault injection policies are all supported for external destinations.
Weighted (version-based) routing is not possible, however, since there is no notion
of multiple versions of an external service.
See the [egress task](/docs/tasks/traffic-management/egress/) for a more
about accessing external services.
## Gateways
A [Gateway](/docs/reference/config/istio.networking.v1alpha3/#Gateway)
configure a load balancer for HTTP/TCP traffic, most commonly operating at the edge of the
mesh to enable ingress traffic for an application.
Unlike Kubernetes Ingress, Istio `Gateway` only configures the L4-L6 functions
(e.g., ports to expose, TLS configuration). Users then can use standard Istio rules
to control HTTP requests as well as TCP traffic entering a `Gateway` by binding a
`VirtualService` to it.
For example, the following simple `Gateway` configures a load balancer
to allow external https traffic for host `bookinfo.com` into the mesh:
```yaml
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: bookinfo-gateway
spec:
servers:
- port:
number: 443
name: https
protocol: HTTPS
hosts:
- bookinfo.com
tls:
mode: SIMPLE
serverCertificate: /tmp/tls.crt
privateKey: /tmp/tls.key
```
To configure the corresponding routes, a `VirtualService`
must be defined for the same host and bound to the `Gateway` using
the `gateways` field in the configuration:
```yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: bookinfo
spec:
hosts:
- bookinfo.com
gateways:
- bookinfo-gateway # <---- bind to gateway
http:
- match:
- uri:
prefix: /reviews
route:
...
```
See the [ingress task](/docs/tasks/traffic-management/ingress/) for a
complete ingress gateway example.
Although primarily used to manage ingress traffic, a `Gateway` can also be used to model
a purely internal or egress proxy. Irrespective of the location, all gateways
can be configured and controlled in the same way. Refer to the
[gateway reference](/docs/reference/config/istio.networking.v1alpha3/#Gateway)
for details.