mirror of https://github.com/istio/istio.io.git
Merge pull request #7 from rshriram/master
Moving content from istio/istio/doc to istio.github.io
This commit is contained in:
commit
0e57af2b3b
|
@ -9,7 +9,7 @@
|
|||
<li class="tab"><a href="{{ site.baseurl }}/docs/quickstart" {% if current[2] == 'quickstart' %}class='current'{% endif %}>Quick Start</a></li>
|
||||
<li class="tab"><a href="{{ site.baseurl }}/docs/guides" {% if current[2] == 'guides' %}class='current'{% endif %}>Guides</a></li>
|
||||
<li class="tab"><a href="{{ site.baseurl }}/docs/tutorials" {% if current[2] == 'tutorials' %}class='current'{% endif %}>Tutorials</a></li>
|
||||
<li class="tab"><a href="{{ site.baseurl }}/docs/reference" {% if current[2] == 'reference' %}class='current'{% endif %}>Reference API</a></li>
|
||||
<li class="tab"><a href="{{ site.baseurl }}/docs/reference" {% if current[2] == 'reference' %}class='current'{% endif %}>Reference</a></li>
|
||||
<li class="tab"><a href="{{ site.baseurl }}/docs/samples" {% if current[2] == 'samples' %}class='current'{% endif %}>Samples</a></li>
|
||||
</ul>
|
||||
{% include contribute-links.html %}
|
||||
|
|
|
@ -2,8 +2,7 @@
|
|||
{% assign current = page.url | downcase | split: '/' %}
|
||||
<li><h5 class="doc-side-nav-title">Guides</h5></li>
|
||||
<li class="doc-side-nav-list-item"><a href="{{ site.baseurl }}/docs/guides/index.html" {% if current[3] == 'index.html' %}class='current'{% endif %}>What is Istio?</a></li>
|
||||
<li class="doc-side-nav-list-item"><a href="{{ site.baseurl }}/docs/guides/concepts.html" {% if current[3] == 'concepts.html' %}class='current'{% endif %}>Istio Concepts</a></li>
|
||||
<li class="doc-side-nav-list-item"><a href="{{ site.baseurl }}/docs/guides/proxy.html" {% if current[3] == 'proxy.html' %}class='current'{% endif %}>Istio Proxy</a></li>
|
||||
<li class="doc-side-nav-list-item"><a href="{{ site.baseurl }}/docs/guides/manager.html" {% if current[3] == 'manager.html' %}class='current'{% endif %}>Istio Configuration Manager</a></li>
|
||||
<li class="doc-side-nav-list-item"><a href="{{ site.baseurl }}/docs/guides/mixer.html" {% if current[3] == 'mixer.html' %}class='current'{% endif %}>Istio Mixer</a></li>
|
||||
<li class="doc-side-nav-list-item"><a href="{{ site.baseurl }}/docs/guides/architecture.html" {% if current[3] == 'architecture.html' %}class='current'{% endif %}>Architecture</a></li>
|
||||
<li class="doc-side-nav-list-item"><a href="{{ site.baseurl }}/docs/guides/model.html" {% if current[3] == 'model.html' %}class='current'{% endif %}>Service Model</a></li>
|
||||
<li class="doc-side-nav-list-item"><a href="{{ site.baseurl }}/docs/guides/mixer.html" {% if current[3] == 'mixer.html' %}class='current'{% endif %}>Mixer</a></li>
|
||||
</ul>
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
<li><a href="{{ site.baseurl }}/docs/quickstart"><p>Quick Start</p></a></li>
|
||||
<li><a href="{{ site.baseurl }}/docs/guides"><p>Guides</p></a></li>
|
||||
<li><a href="{{ site.baseurl }}/docs/tutorials"><p>Tutorials</p></a></li>
|
||||
<li><a href="{{ site.baseurl }}/docs/reference"><p>Reference APIs</p></a></li>
|
||||
<li><a href="{{ site.baseurl }}/docs/reference"><p>Reference</p></a></li>
|
||||
<li><a href="{{ site.baseurl }}/docs/samples"><p>Samples</p></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
<a href="{{ site.baseurl }}/docs/quickstart" {% if current[2] == 'quickstart' %}class='current'{% endif %}><li class="nav-doc-tab">Quick Start</li></a>
|
||||
<a href="{{ site.baseurl }}/docs/guides" {% if current[2] == 'guides' %}class='current'{% endif %}><li class="nav-doc-tab">Guides</li></a>
|
||||
<a href="{{ site.baseurl }}/docs/tutorials" {% if current[2] == 'tutorials' %}class='current'{% endif %}><li class="nav-doc-tab">Tutorials</li></a>
|
||||
<a href="{{ site.baseurl }}/docs/reference" {% if current[2] == 'reference' %}class='current'{% endif %}><li class="nav-doc-tab">Reference API</li></a>
|
||||
<a href="{{ site.baseurl }}/docs/reference" {% if current[2] == 'reference' %}class='current'{% endif %}><li class="nav-doc-tab">Reference</li></a>
|
||||
<a href="{{ site.baseurl }}/docs/samples" {% if current[2] == 'samples' %}class='current'{% endif %}><li class="nav-doc-tab">Samples</li></a>
|
||||
</ul>
|
||||
</li>
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
<a href="{{ site.baseurl }}/docs/quickstart" {% if current[2] == 'quickstart' %}class='current'{% endif %}><li class="nav-doc-tab">Quick Start</li></a>
|
||||
<a href="{{ site.baseurl }}/docs/guides" {% if current[2] == 'guides' %}class='current'{% endif %}><li class="nav-doc-tab">Guides</li></a>
|
||||
<a href="{{ site.baseurl }}/docs/tutorials" {% if current[2] == 'tutorials' %}class='current'{% endif %}><li class="nav-doc-tab">Tutorials</li></a>
|
||||
<a href="{{ site.baseurl }}/docs/reference" {% if current[2] == 'reference' %}class='current'{% endif %}><li class="nav-doc-tab">Reference API</li></a>
|
||||
<a href="{{ site.baseurl }}/docs/reference" {% if current[2] == 'reference' %}class='current'{% endif %}><li class="nav-doc-tab">Reference</li></a>
|
||||
<a href="{{ site.baseurl }}/docs/samples" {% if current[2] == 'samples' %}class='current'{% endif %}><li class="nav-doc-tab">Samples</li></a>
|
||||
</ul>
|
||||
</li>
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
---
|
||||
bodyclass: docs
|
||||
headline: Architecture
|
||||
layout: docs
|
||||
sidenav: doc-side-guides-nav.html
|
||||
title: Architecture
|
||||
type: markdown
|
||||
---
|
||||
|
||||
The Istio service mesh consists of three major components:
|
||||
|
||||
## Proxy
|
||||
|
||||
The Istio proxy is designed to mediate inbound and outbound
|
||||
traffic for all Istio-managed services. The Istio proxy is based on
|
||||
[Envoy](https://lyft.github.io/envoy/). Istio leverages Envoy's features
|
||||
such as dynamic service discovery, load balancing, TLS termination, HTTP/2 & gRPC
|
||||
proxying, circuit breakers, health checks, staged rollouts with %-based
|
||||
traffic split, fault injection, and a rich set of metrics. In addition,
|
||||
Istio extends the proxy to interact with the mixer to enforce various
|
||||
access control policies rate limiting, ACLs, as well as telemetry
|
||||
reporting.
|
||||
|
||||
## Mixer
|
||||
|
||||
The Istio mixer is responsible for enforcing access control
|
||||
and usage policies across the service mesh and collects telemetry data from
|
||||
proxies and istio-managed services alike. The Istio proxy extracts request
|
||||
level attributes that are then evaluated by the mixer. More info on the
|
||||
attribute extraction and policy evaluation can be found
|
||||
[here](../reference/attributes.md). The mixer includes a flexible plugin model enabling
|
||||
it to interface to a variety of host environments and configured backends,
|
||||
abstracting the proxy and Istio-managed services from these details.
|
||||
|
||||
## Manager
|
||||
|
||||
The Istio manager serves as an interface between the user
|
||||
and Istio, collecting configuration, validating it and propagating it to
|
||||
various components. It abstracts platform-specific implementation details
|
||||
from the mixer and proxies, providing them with an
|
||||
[abstract representation](model.md) of user's services that is independent
|
||||
of the underlying platform. In addition, [traffic management rules](../reference/rule-dsl.md)
|
||||
(i.e. generic layer-4 rules and layer-7 HTTP/gRPC routing rules)
|
||||
can be programmed at runtime via the Istio Manager.
|
||||
|
||||
<img src="../../img/arch.svg" alt="The overall architecture of an Istio-based service.">
|
||||
|
||||
<div id="toc" class="toc mobile-toc"></div>
|
|
@ -7,6 +7,22 @@ title: Guides
|
|||
type: markdown
|
||||
---
|
||||
|
||||
This document introduces you to ...
|
||||
As enterprises migrate from traditional VM infrastructures to more agile
|
||||
microservice-based deployments on container platforms, there is a need for
|
||||
a simplifying technology that can take care of common cross-cutting
|
||||
capabilities around service communication and management such as secure
|
||||
interconnect, service discovery & load balancing, staged rollouts, A/B
|
||||
testing, intelligent rate limiting, authentication, access control,
|
||||
monitoring, logging, etc.
|
||||
|
||||
Towards this goal, we are designing Istio, an _open
|
||||
platform-independent service mesh_ that takes care of traffic management,
|
||||
policy enforcement, rate limiting, and telemetry collection.
|
||||
It allows application developers to focus on the
|
||||
business logic and iterate quickly on new features by managing how traffic
|
||||
flows across their services. And it simplifies the operators' job of enforcing
|
||||
various policies and monitor the mesh from a central control point,
|
||||
independent of the evolution of the application ensuring continuous
|
||||
compliance with policies of the organization/business unit.
|
||||
|
||||
<div id="toc" class="toc mobile-toc"></div>
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
---
|
||||
bodyclass: docs
|
||||
headline: Istio Mixer
|
||||
layout: docs
|
||||
sidenav: doc-side-guides-nav.html
|
||||
title: Istio Mixer
|
||||
type: markdown
|
||||
---
|
||||
|
||||
The mixer provides the control-plane abstractions necessary for most real-world multi-tenant services.
|
||||
The proxy delegates policy decisions to the mixer and dispatches its telemetry data to the mixer, which
|
||||
proceeds to repackage and redirect the data towards configured backends.
|
||||
|
||||
Services within the Istio mesh can also directly integrate with the mixer. For example, services may wish to provide rich telemetry for particular operations
|
||||
beyond what the proxy automatically collects. Or services may use the mixer for resource-oriented quota management. Services that leverage the mixer in this
|
||||
way are abstracted from environment-specific control plane details, greatly easing the process of hosting the code in
|
||||
different environments (different clouds & on-prem)
|
||||
|
||||
The mixer provides three core features:
|
||||
|
||||
**Precondition Checking**. Enables callers to verify a number of preconditions before responding to an incoming request from a service consumer.
|
||||
Preconditions can include whether the service consumer is properly authenticated, is on the service's whitelist, passes ACL checks, and more.
|
||||
|
||||
**Telemetry Reporting**. Enables services to produce logging, monitoring, tracing and billing streams intended for the service producer itself as well as
|
||||
for its consumers.
|
||||
|
||||
**Quota Management**. Enables services to allocate and free quota on a number of dimensions, Quotas are used as a relatively simple resource management
|
||||
tool to provide some fairness between service consumers when contending for limited resources.
|
||||
|
||||
## Mixer Adapters
|
||||
|
||||
Adapters are binary-level plugins to the mixer which make it possible to customize the mixer’s behavior. Adapters allow the mixer to interface
|
||||
to different backend systems that deliver core control-plane functionality, such as logging, monitoring, quotas, ACL checking, and more. Adapters
|
||||
enable the mixer to expose a single consistent control API, independent of the backends in use. The exact set of adapters
|
||||
used at runtime is determined through configuration.
|
||||
|
||||
<img src="../../img/adapters.svg" alt="Mixer and its adapters.">
|
||||
|
||||
<div id="toc" class="toc mobile-toc"></div>
|
|
@ -0,0 +1,82 @@
|
|||
---
|
||||
bodyclass: docs
|
||||
headline: Istio Service Model
|
||||
layout: docs
|
||||
sidenav: doc-side-guides-nav.html
|
||||
title: Istio Service Model
|
||||
type: markdown
|
||||
---
|
||||
|
||||
The Istio manager serves as an interface between the user and Istio,
|
||||
collecting configuration, validating it and propagating it to various
|
||||
components. It abstracts platform-specific implementation details from the
|
||||
mixer and proxies, providing them with an abstract representation of user's
|
||||
services that is independent of the underlying platform. The model
|
||||
described below assumes a microservice-based application owned by a single
|
||||
tenant.
|
||||
|
||||
**Istio-managed service:** Modern cloud applications are created by
|
||||
composing together independent sets of services. Individual services are
|
||||
referenced by their fully-qualified domain name (FQDN) and one or more
|
||||
ports where the service is listening for connections.
|
||||
|
||||
**Platform-agnostic internal representation:** The Istio model of a
|
||||
microservice is independent of how it is represented in the underlying
|
||||
platform (Kubernetes, Mesos, CloudFoundry, etc.). Platform-specific
|
||||
adapters are responsible for populating the internal model representation
|
||||
with various fields, from the metadata found in the platform.
|
||||
|
||||
## Multiple versions of a service
|
||||
|
||||
Istio introduces the concept of a service version, which is a finer-grained
|
||||
way to subdivide service instances by versions (`v1`, `v2`) or environment
|
||||
(`staging`, `prod`). These variants are not necessarily different API
|
||||
versions: they could be iterative changes to the same service, deployed in
|
||||
different environments (prod, staging, dev, etc.). Common scenarios where
|
||||
this occurs include A/B testing, canary rollouts, etc. Istio
|
||||
[routing rules](../reference/rule-dsl.md) can refer to the service versions, to provide
|
||||
additional control over traffic between services.
|
||||
|
||||
**Tags** Each version of a service can be differentiated by a unique set of
|
||||
tags associated with the version. Tags are simple key value pairs
|
||||
assigned to the instances of a particular service version, i.e., all
|
||||
instances of the same version must have the same tags.
|
||||
|
||||
## Populating the abstract service model
|
||||
|
||||
Where possible, Istio leverages the service registration and discovery
|
||||
mechanism provided by the underlying platform to populate its abstract
|
||||
service model. Most container platforms come built-in with a service
|
||||
registry (e.g., kubernetes, mesos) where a pod specification can contain
|
||||
all the version related tags. Upon launching the pod, the platform
|
||||
automatically registers the pod with the registry along with the tags. In
|
||||
other platforms, a dedicated service registration agent might be needed to
|
||||
automatically register the service with a service registration/discovery
|
||||
solution like Consul, etc.
|
||||
|
||||
At the moment, Istio integrates readily with the Kubernetes service registry
|
||||
and automatically discovers various services, their pods etc., and
|
||||
groups the pods into unique sets -- each set representing a service
|
||||
version. In future, Istio will add support for pulling in similar
|
||||
information from Mesos registry and *potentially* other registries.
|
||||
|
||||
## Communication between services
|
||||
|
||||
Clients of a service have no knowledge of different versions of the
|
||||
service. They can continue to access the services using the hostname/IP
|
||||
address of the service. The Istio Proxy intercepts and forwards all
|
||||
requests/responses between the client and the service.
|
||||
|
||||
The actual choice of the service version is determined dynamically by the
|
||||
Istio Proxy based on the routing rules set forth by the operator. This
|
||||
model enables the application code to decouple itself from the
|
||||
evolution of its dependent services, while providing other benefits as well
|
||||
(see [mixer](mixer.md)). Routing rules allow the proxy to select a version based on
|
||||
criterion such as (headers, url, etc.), tags associated with
|
||||
source/destination and/or by weights assigned to each version.
|
||||
|
||||
Note that Istio does not provide a DNS. Applications can try to resolve the
|
||||
FQDN using the DNS service present in the underlying platform (kube-dns,
|
||||
mesos-dns, etc.).
|
||||
|
||||
<div id="toc" class="toc mobile-toc"></div>
|
|
@ -0,0 +1,119 @@
|
|||
---
|
||||
bodyclass: docs
|
||||
headline: 'Mixer Attributes'
|
||||
layout: docs
|
||||
title: Mixer Attributes
|
||||
type: markdown
|
||||
---
|
||||
|
||||
Istio uses *attributes* to describe runtime behavior of services running in the mesh. Attributes are named and typed pieces of metadata
|
||||
describing ingress and egress traffic and the environment this traffic occurs in. An Istio attribute carries a specific piece
|
||||
of information such as the error code of an API request, the latency of an API request, or the
|
||||
original IP address of a TCP connection.
|
||||
|
||||
Istio's policy evaluation model operates on attributes. For example, access control is configured by
|
||||
specifying policies against particular attribute values.
|
||||
|
||||
A given Istio deployment has a fixed vocabulary of attributes that it understands. The specific vocabulary is
|
||||
determined by the set of attribute producers being used in the deployment. The primary attribute producer in Istio
|
||||
is the proxy, although the mixer and services can also introduce attributes.
|
||||
|
||||
Attribute producers declare the set of attributes they produce using the [`AttributeDescriptor`](https://raw.githubusercontent.com/istio/api/master/mixer/v1/config/descriptor/attribute_descriptor.proto)
|
||||
message:
|
||||
|
||||
message AttributeDescriptor {
|
||||
// The name of this descriptor, referenced from individual attribute instances and other
|
||||
// descriptors.
|
||||
string name = 1;
|
||||
|
||||
// An optional human-readable description of the attribute's purpose.
|
||||
string description = 2;
|
||||
|
||||
// The type of data carried by attributes
|
||||
ValueType value_type = 3;
|
||||
}
|
||||
|
||||
enum ValueType {
|
||||
// Invalid, default value.
|
||||
VALUE_TYPE_UNSPECIFIED = 0;
|
||||
|
||||
// An undiscriminated variable-length string.
|
||||
STRING = 1;
|
||||
|
||||
// An undiscriminated 64-bit signed integer.
|
||||
INT64 = 2;
|
||||
|
||||
// An undiscriminated 64-bit floating-point value.
|
||||
DOUBLE = 3;
|
||||
|
||||
// An undiscriminated boolean value.
|
||||
BOOL = 4;
|
||||
|
||||
// A point in time.
|
||||
TIMESTAMP = 5;
|
||||
|
||||
// An IP address.
|
||||
IP_ADDRESS = 6;
|
||||
|
||||
// An email address.
|
||||
EMAIL_ADDRESS = 7;
|
||||
|
||||
// A URI.
|
||||
URI = 8;
|
||||
|
||||
// A DNS name.
|
||||
DNS_NAME = 9;
|
||||
|
||||
// A span between two points in time.
|
||||
DURATION = 10;
|
||||
|
||||
// A map string -> string, typically used by headers.
|
||||
STRING_MAP = 11;
|
||||
}
|
||||
|
||||
When an attribute is used in Istio, its name is given along with a value. The value must be of the type declared by the corresponding descriptor. This
|
||||
type checking makes it possible for the Istio system to statically detect or prevent many configuration errors.
|
||||
|
||||
# Standard Istio Attribute Vocabulary
|
||||
|
||||
In a standard Istio deployment (using the Istio proxy), the system will produce the following set of attributes. This is considered the canonical attribute set for Istio.
|
||||
|
||||
| Name | Type | Description | Kubernetes Example |
|
||||
|------|------|-------------|--------------------|
|
||||
| source.ip | ip_address | The IP address of the client that sent the request. | 10.0.0.117 |
|
||||
| source.port | int64 | The port on the client that sent the request. | 9284 |
|
||||
| source.name | string | The fully qualified name of the application that sent the request. | redis-master.namespace.deps.cluster.local |
|
||||
| source.uid | string | A unique identifier for the particular instance of the application that sent the request. | redis-master-2353460263-1ecey.namespace.pods.cluster.local |
|
||||
| source.namespace | string | The namespace of the sender of the request. | namespace.cluster.local |
|
||||
| source.labels | map | A map of key-value pairs attached to the source. | |
|
||||
| source.user | string | The user running the target application. | service-account@namespace.cluster.local |
|
||||
| target.ip | ip_address | The IP address the request was sent to. | 10.0.0.104 |
|
||||
| target.port | int64 | The port the request was sent to. | 8080 |
|
||||
| target.service | dns_name | The hostname that was the target of the request. | my-svc.my-namespace.svc.cluster.local |
|
||||
| target.name | string | The fully qualified name of the application that was the target of the request. | |
|
||||
| target.uid | string | A unique identifier for the particular instance of the application that received the request. | |
|
||||
| target.namespace | string | The namespace of the receiver of the request. | |
|
||||
| target.labels | map | A map of key-value pairs attached to the target. | |
|
||||
| target.user | string | The user running the target application. | service-account@namespace.cluster.local |
|
||||
| origin.ip | ip_address | The IP address of the originating application | |
|
||||
| origin.name | string | The fully qualified name of the originating application | |
|
||||
| origin.uid | string | A unique identifier for the particular instance of the application that originated the request. This must be unique within the cluster. | for in cluster pod-id gives sufficient to ascertain all other attributes needed by the policy. |
|
||||
| origin.namespace | string | The namespace of the originator of the request. | |
|
||||
| origin.labels | map | A map of key-value pairs attached to the origin. | |
|
||||
| origin.user | string | The user running the originating application. | |
|
||||
| request.headers | map | A map of HTTP headers attached to the request. | |
|
||||
| request.id | string | A unique ID for the request, which can be propagated to downstream systems. This should be a guid or a psuedo-guid with a low probability of collision in a temporal window measured in days or weeks. | |
|
||||
| request.path | string | The HTTP URL path including query string | |
|
||||
| request.host | string | The HTTP Host header. | |
|
||||
| request.method | string | The HTTP method. | |
|
||||
| request.reason | string | The system parameter for auditing reason. It is required for cloud audit logging and GIN logging | |
|
||||
| request.referer | string | The HTTP referer header. | |
|
||||
| request.scheme | string | URI Scheme of the request | |
|
||||
| request.size | int64 | Size of the request in bytes. For HTTP requests this is equivalent to the Content-Length header. | |
|
||||
| request.time | timestamp | The timestamp when the target receives the request. This should be equivalent to Firebase "now". | |
|
||||
| request.user-agent | string | The HTTP User-Agent header. | |
|
||||
| response.headers | map | A map of HTTP headers attached to the response. | |
|
||||
| response.size | int64 | Size of the response body in bytes | |
|
||||
| response.time | timestamp | The timestamp when the target produced the response. | |
|
||||
| response.duration | duration | The amount of time the response took to generate. | |
|
||||
| response.code | int64 | The response's HTTP status code | |
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
bodyclass: docs
|
||||
headline: 'API Reference'
|
||||
headline: 'Reference'
|
||||
layout: docs
|
||||
title: Reference API
|
||||
title: Reference
|
||||
type: markdown
|
||||
---
|
|
@ -0,0 +1,100 @@
|
|||
---
|
||||
bodyclass: docs
|
||||
headline: 'Istioctl CLI'
|
||||
layout: docs
|
||||
title: Istioctl CLI
|
||||
type: markdown
|
||||
---
|
||||
|
||||
`istioctl` is a command line interface for managing an Istio service mesh. This overview covers
|
||||
synax, describes command operations, and provides examples.
|
||||
|
||||
# Syntax
|
||||
|
||||
Istioctl commands follow the syntax:
|
||||
|
||||
```
|
||||
istioctl <command> [targets] [flags]
|
||||
```
|
||||
|
||||
where `command`, `targets` and `flags` are:
|
||||
|
||||
* **command**: the operation to perform, such as `create`, `delete`, `replace`, or `list`.
|
||||
* **targets**: targets for commands such as delete
|
||||
* **flags**: Optional flags. For example specify `--file <filename>` to specify a configuration file to create from.
|
||||
|
||||
# Operations
|
||||
|
||||
* **create**: Create policies and rules
|
||||
* **delete**: Delete policies or rules
|
||||
* **get**: Retrieve policy/policies or rules
|
||||
* **replace**: Replace policies and rules
|
||||
* **version**: Display CLI version information
|
||||
|
||||
_kubernetes specific_
|
||||
* **kube-inject**: Inject istio runtime proxy into kubernetes
|
||||
resources. This command has been added to aid in `istiofying`
|
||||
services for kubernetes and should eventually go away once a proper
|
||||
istio admission controller for kubernetes is available.
|
||||
|
||||
# Policy and Rule types
|
||||
|
||||
* **route-rule** Describes a rule for routing network traffic. See [Route Rules](rule-dsl.md#route-rules) for details on routing rules.
|
||||
* **destination-policy** Describes a policy for traffic destinations. See [Destination Policies](rule-dsl.md#destination-policies) for details on destination policies.
|
||||
|
||||
# Examples of common operations
|
||||
|
||||
`istioctl create` - Create policies or rules from a file or stdin.
|
||||
|
||||
```
|
||||
// Create a rule using the definition in example-routing.yaml.
|
||||
$ istioctl create -f example-routing.yaml
|
||||
```
|
||||
|
||||
`istioctl delete` - Create policies or rules from a file or stdin.
|
||||
|
||||
```
|
||||
// Delete a rule using the definition in example-routing.yaml.
|
||||
$ istioctl delete -f example-routing.yaml
|
||||
```
|
||||
|
||||
`istioctl get` - List policies or rules in YAML format
|
||||
|
||||
```
|
||||
// List route rules
|
||||
istioctl get route-rules
|
||||
|
||||
// List destination policies
|
||||
istioctl get destination-policies
|
||||
```
|
||||
|
||||
# kube-inject
|
||||
|
||||
A short term workaround for the lack of a proper istio admision
|
||||
controller is client-side injection. Use `istioctl kube-inject` to add the
|
||||
necessary configurations to a kubernetes resource files.
|
||||
|
||||
istioctl kube-inject -f deployment.yaml -o deployment-with-istio.yaml
|
||||
|
||||
Or update the resource on the fly before applying.
|
||||
|
||||
kubectl create -f <(istioctl kube-inject -f depoyment.yaml)
|
||||
|
||||
Or update an existing deployment.
|
||||
|
||||
kubectl get deployment -o yaml | istioctl kube-inject -f - | kubectl apply -f -
|
||||
|
||||
`istioctl kube-inject` will update
|
||||
the [PodTemplateSpec](https://kubernetes.io/docs/api-reference/v1/definitions/#_v1_podtemplatespec) in
|
||||
kubernetes Job, DaemonSet, ReplicaSet, and Deployment YAML resource
|
||||
documents. Support for additional pod-based resource types can be
|
||||
added as necessary.
|
||||
|
||||
Unsupported resources are left unmodified so, for example, it is safe
|
||||
to run `istioctl kube-inject` over a single file that contains multiple
|
||||
Service, ConfigMap, and Deployment definitions for a complex
|
||||
application.
|
||||
|
||||
The Istio project is continually evolving so the low-level proxy
|
||||
configuration may change unannounced. When in doubt re-run `istioctl kube-inject`
|
||||
on your original deployments.
|
|
@ -0,0 +1,518 @@
|
|||
---
|
||||
bodyclass: docs
|
||||
headline: 'Routing & Traffic Management'
|
||||
layout: docs
|
||||
title: Routing & Traffic Management
|
||||
type: markdown
|
||||
---
|
||||
|
||||
* [Overview](#overview)
|
||||
* [Route Rules](#route-rules)
|
||||
* [destination](#destination)
|
||||
* [precedence](#precendence)
|
||||
* [match](#match)
|
||||
* [match.source](#match-source)
|
||||
* [match.sourceTags](#match-sourceTags)
|
||||
* [match.httpHeaders](#match-httpHeaders)
|
||||
* [match.tcp](#match-tcp)
|
||||
* [match.udp](#match-udp)
|
||||
* [route](#route)
|
||||
* [route.destination](#route-destination)
|
||||
* [route.tags](#route-tags)
|
||||
* [route.weight](#route-weight)
|
||||
* [httpReqTimeout](#httpReqTimeout)
|
||||
* [httpReqRetries](#httpReqRetries)
|
||||
* [httpFault](#httpFault)
|
||||
* [httpFault.delay](#httpFault-delay)
|
||||
* [httpFault.abort](#httpFault-abort)
|
||||
* [Route Rule Evaluation](#route-rule-evaluation)
|
||||
* [Destination Policies](#destination-policies)
|
||||
* [destination](#pdestination)
|
||||
* [tags](#tags)
|
||||
* [loadBalancing](#loadBalancing)
|
||||
* [circuitBreaker](#circuitBreaker)
|
||||
* [Destination Policy Evaluation](#destination-policy-evaluation)
|
||||
|
||||
## Overview <a id="overview"></a>
|
||||
|
||||
Istio provides a simple Domain-specific language (DSL) based on the proto3
|
||||
schema (documented
|
||||
[here](https://github.com/istio/api/blob/master/proxy/v1/config/cfg.md)) to
|
||||
control how API calls and layer-4 traffic flows across various
|
||||
microservices in the application deployment. The DSL allows the 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" microservice
|
||||
to version "v1" can be described using the Rules DSL as follows:
|
||||
|
||||
```yaml
|
||||
destination: reviews.default.svc.cluster.local
|
||||
route:
|
||||
- tags:
|
||||
version: v1
|
||||
weight: 100
|
||||
```
|
||||
|
||||
The destination is the name of the service (specified as a fully qualified
|
||||
domain name (FQDN)) to which the traffic is being routed. In a Kubernetes
|
||||
deployment of Istio, the route *tag*
|
||||
"version: v1" corresponds to a Kubernetes *label* "version: v1". The rule
|
||||
ensures that only Kubernetes pods containing the label "version: v1"
|
||||
will receive traffic.
|
||||
|
||||
There are two types of rules in Istio, **Route Rules**,
|
||||
which control request routing, and **Destination Policies**,
|
||||
which specify policies, for example, circuit breakers, that control requests for a destination service.
|
||||
|
||||
Istio rules can be set and displayed using the [istioctl CLI](istioctl.md).
|
||||
For example, the above rule can be set using the following command:
|
||||
```bash
|
||||
$ cat <<EOF | istioctl create
|
||||
type: route-rule
|
||||
name: reviews-default
|
||||
spec:
|
||||
destination: reviews.default.svc.cluster.local
|
||||
route:
|
||||
- tags:
|
||||
version: v1
|
||||
weight: 100
|
||||
EOF
|
||||
```
|
||||
|
||||
## Route Rules <a id="route-rules"></a>
|
||||
|
||||
The following subsections provide a overview of the basic fields of a route rule.
|
||||
A complete and detailed description of a route rule structure can be found
|
||||
[here](https://github.com/istio/api/blob/master/proxy/v1/config/cfg.md#route-rules).
|
||||
|
||||
#### Property: destination <a id="destination"></a>
|
||||
|
||||
Every rule corresponds to some destination microservice identified by a *destination* field in the
|
||||
rule. For example, all rules that apply to calls to the "reviews" microservice will include the following field.
|
||||
|
||||
```yaml
|
||||
destination: reviews.default.svc.cluster.local
|
||||
```
|
||||
|
||||
The *destination* value SHOULD be a fully qualified domain name (FQDN). It
|
||||
is used by the Istio runtime for matching rules to services. For example,
|
||||
in Kubernetes, a fully qualified domain name for a service can be
|
||||
constructed using the following format: *serviceName.namespace.dnsSuffix*.
|
||||
|
||||
#### Property: precedence <a id="precedence"></a>
|
||||
|
||||
The order of evaluation of rules corresponding to a given destination, when there is more than one, can be specified
|
||||
by setting the *precedence* field of the rule.
|
||||
|
||||
```yaml
|
||||
destination: reviews.default.svc.cluster.local
|
||||
precedence: 1
|
||||
```
|
||||
|
||||
The precedence field is an optional integer value, 0 by default.
|
||||
Rules with higher precedence values are evaluated first.
|
||||
If there is more than one rule with the same precedence value the order of evaluation is undefined.
|
||||
|
||||
For further details, see [Route Rule Evaluation](#route-rule-evaluation).
|
||||
|
||||
#### Property: match <a id="match"></a>
|
||||
|
||||
Rules can optionally be qualified to only apply to requests that match some specific criteria such
|
||||
as a specific request source and/or headers. An optional *match* field is used for this purpose.
|
||||
|
||||
The *match* field is an object with the following nested fields:
|
||||
|
||||
* **source** fully qualified domain name (FQDN)
|
||||
* **sourceTags** optional match qualifications
|
||||
* **httpHeaders** HTTP header qualifications
|
||||
* **tcp**
|
||||
* **udp**
|
||||
|
||||
#### Property: match.source <a id="match-source"></a>
|
||||
|
||||
The *source* field qualifies a rule to only apply to requests from a specific caller.
|
||||
For example,
|
||||
the following *match* clause qualifies the rule to only apply to calls from the "reviews" microservice.
|
||||
|
||||
```yaml
|
||||
destination: ratings.default.svc.cluster.local
|
||||
match:
|
||||
source: reviews.default.svc.cluster.local
|
||||
```
|
||||
|
||||
The *source* value, just like *destination*, is an FQDN of a service.
|
||||
|
||||
#### Property: match.sourceTags <a id="match-sourceTags"></a>
|
||||
|
||||
The *sourceTags* field can be used to further qualify a rule to only apply to specific instances of a
|
||||
calling service.
|
||||
For example,
|
||||
the following *match* clause refines the previous example to qualify the rule to only
|
||||
apply to calls from version "v2" of the "reviews" microservice.
|
||||
|
||||
```yaml
|
||||
destination: ratings.default.svc.cluster.local
|
||||
match:
|
||||
source: reviews.default.svc.cluster.local
|
||||
sourceTags:
|
||||
version: v2
|
||||
```
|
||||
|
||||
#### Property: match.httpHeaders <a id="match-httpHeaders"></a>
|
||||
|
||||
The *httpHeaders* field is a set of one or more property-value pairs where each property is an HTTP header name
|
||||
and the corresponding value is one of the following:
|
||||
|
||||
1. `exact: "value"`, where the header value must match *value* exactly
|
||||
2. `prefix: "value"`, where *value* must be a prefix of the header value
|
||||
3. `regex: "value"`, where *value* is a regular expression that matches the header value
|
||||
|
||||
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
|
||||
destination: reviews.default.svc.cluster.local
|
||||
match:
|
||||
httpHeaders:
|
||||
Cookie:
|
||||
regex: "^(.*?;)?(user=jason)(;.*)?$"
|
||||
```
|
||||
|
||||
If more than one property-value pair is provided, then all of the corresponding headers
|
||||
must match for the rule to apply.
|
||||
|
||||
The *source* and *httpHeaders* fields can both be set in the *match* object in which case both criteria must pass.
|
||||
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
|
||||
destination: ratings.default.svc.cluster.local
|
||||
match:
|
||||
source: reviews.default.svc.cluster.local
|
||||
sourceTags:
|
||||
version: v2
|
||||
httpHeaders:
|
||||
Cookie:
|
||||
regex: "^(.*?;)?(user=jason)(;.*)?$"
|
||||
```
|
||||
|
||||
#### Property: match.tcp <a id="match-tcp"></a>
|
||||
|
||||
TBD
|
||||
|
||||
#### Property: match.udp <a id="match-udp"></a>
|
||||
|
||||
TBD
|
||||
|
||||
#### Property: route <a id="route"></a>
|
||||
|
||||
The *route* field identifies a set of one or more weighted backends to call when the rule is activated.
|
||||
Each *route* backend is an object with the following fields:
|
||||
|
||||
* **tags**
|
||||
* **weight**
|
||||
* **destination**
|
||||
|
||||
Of these fields, *tags* is the only required one, the others are optional.
|
||||
|
||||
#### Property: route.tags <a id="route-tags"></a>
|
||||
|
||||
The *tags* field is a list of instance tags to identify the target instances (e.g., version) to route requests to.
|
||||
If there are multiple registered instances with the specified tag(s),
|
||||
they will be routed to based on the [load balancing policy](#loadBalancing) configured for the service,
|
||||
or round-robin by default.
|
||||
|
||||
#### Property: route.weight <a id="route-weight"></a>
|
||||
|
||||
The *weight* field is an optional value between 0 and 100 that represents the percentage of requests to route
|
||||
to instances associated with the corresponding backend. If not set, the *weight* is assumed to be 100.
|
||||
|
||||
The sum of all route weights in a rule SHOULD equal 100.
|
||||
For example, the following rule will route 25% of traffic for the "reviews" service to instances with
|
||||
the "v2" tag and the remaining traffic (i.e., 75%) to "v1".
|
||||
|
||||
```yaml
|
||||
destination: reviews.default.svc.cluster.local
|
||||
route:
|
||||
- tags:
|
||||
version: v2
|
||||
weight: 25
|
||||
- tags:
|
||||
version: v1
|
||||
weight: 75
|
||||
```
|
||||
|
||||
#### Property: route.destination <a id="route-destination"></a>
|
||||
|
||||
The *destination* field is optional and specifies the service name of the target instances.
|
||||
If not specified, it defaults to the value of the rule's *destination* field.
|
||||
|
||||
#### Property: httpReqTimeout <a id="httpReqTimeout"></a>
|
||||
|
||||
A timeout for http requests can be specified using the *httpReqTimeout* field.
|
||||
By default, the timeout is 15 seconds, but this can be overridden as follows:
|
||||
|
||||
```yaml
|
||||
destination: "ratings.default.svc.cluster.local"
|
||||
route:
|
||||
- tags:
|
||||
version: v1
|
||||
httpReqTimeout:
|
||||
simpleTimeout:
|
||||
timeoutSeconds: 10
|
||||
```
|
||||
|
||||
#### Property: httpReqRetries <a id="httpReqRetries"></a>
|
||||
|
||||
The *httpReqRetries* field can be used to control the number retries for a given http request.
|
||||
The maximum number of attempts, or as many as possible within the time period
|
||||
specified by *httpReqTimeout*, can be set as follows:
|
||||
|
||||
```yaml
|
||||
destination: "ratings.default.svc.cluster.local"
|
||||
route:
|
||||
- tags:
|
||||
version: v1
|
||||
httpReqRetries:
|
||||
simpleRetry:
|
||||
attempts: 3
|
||||
```
|
||||
|
||||
#### Property: httpFault <a id="httpFault"></a>
|
||||
|
||||
The *httpFault* field is used to specify one or more faults to inject
|
||||
while forwarding http requests to the rule's corresponding request destination.
|
||||
The faults injected depend on the following nested fields:
|
||||
|
||||
* **delay**
|
||||
* **abort**
|
||||
|
||||
#### Property: httpFault.delay <a id="httpFault-delay"></a>
|
||||
|
||||
The *delay* field is used to delay a request by a specified amount of time. Nested fields
|
||||
*percent* and one of either *fixedDelaySeconds* or *exponentialDelaySeconds* are used to specify the delay.
|
||||
|
||||
The *fixedDelaySeconds* field is used to indicate the amount of delay in seconds.
|
||||
|
||||
Alternatively, the *exponentialDelaySeconds* field can be used to specify the mean delay
|
||||
for values derived according to an exponential function.
|
||||
|
||||
An optional *percent* field, a value between 0 and 100, can be used to only delay a certain percentage of requests.
|
||||
All request are delayed by default.
|
||||
|
||||
The following example will introduce a 5 second delay in 10% of the requests to the "v1" version of the "reviews" microservice.
|
||||
|
||||
```yaml
|
||||
destination: reviews.default.svc.cluster.local
|
||||
route:
|
||||
- tags:
|
||||
version: v1
|
||||
httpFault:
|
||||
delay:
|
||||
percent: 10
|
||||
fixedDelaySeconds: 5
|
||||
```
|
||||
|
||||
#### Property: httpFault.abort <a id="httpFault-abort"></a>
|
||||
|
||||
An *abort* field is used to prematurely abort a request, usually to simulate a failure. Nested fields
|
||||
*percent* and one of *httpStatus*, *http2Error*, or *grpcStatus*, are used to specify the abort.
|
||||
|
||||
The optional *percent* field, a value between 0 and 100, is used to only abort a certain percentage of requests.
|
||||
All requests are aborted by default.
|
||||
|
||||
The *httpStatus* field is used to indicate a value to return from an HTTP request, instead of forwarding the request to the destination.
|
||||
Its value is an integer HTTP 2xx, 3xx, 4xx, or 5xx status code.
|
||||
|
||||
Similarly, to abort HTTP/2 or gRPC, the value to return
|
||||
can be specified using the *http2Error* or *grpcStatus*, respectively.
|
||||
|
||||
The following example will return an HTTP 400 error code for 10% of the requests to the "ratings" service "v1".
|
||||
|
||||
```yaml
|
||||
destination: "ratings.default.svc.cluster.local"
|
||||
route:
|
||||
- tags:
|
||||
version: v1
|
||||
httpFault:
|
||||
abort:
|
||||
percent: 10
|
||||
httpStatus: 400
|
||||
```
|
||||
|
||||
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
|
||||
destination: ratings.default.svc.cluster.local
|
||||
match:
|
||||
source: reviews.default.svc.cluster.local
|
||||
sourceTags:
|
||||
version: v2
|
||||
route:
|
||||
- tags:
|
||||
version: v1
|
||||
httpFault:
|
||||
delay:
|
||||
fixedDelaySeconds: 5
|
||||
abort:
|
||||
percent: 10
|
||||
httpStatus: 400
|
||||
```
|
||||
|
||||
## Route Rule Evaluation <a id="route-rule-evaluation"></a>
|
||||
|
||||
Whenever the routing story for a particular microservice is purely weight based,
|
||||
it can be specified in a single rule, as shown in the [route.weight](#route-weight) example.
|
||||
When, on the other hand, other crieria (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 *precedence* field must be set 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 use the *match* field (see [match](#match)) to provide specific rules,
|
||||
and then provide a single weight-based rule with no match criteria at the lowest priority to provide the
|
||||
weighted distribution of traffic for all other cases.
|
||||
|
||||
The following 2 rules, 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
|
||||
destination: reviews.default.svc.cluster.local
|
||||
precedence: 2
|
||||
match:
|
||||
httpHeaders:
|
||||
Foo:
|
||||
exact: bar
|
||||
route:
|
||||
- tags:
|
||||
version: v2
|
||||
---
|
||||
destination: reviews.default.svc.cluster.local
|
||||
precedence: 1
|
||||
route:
|
||||
- tags:
|
||||
version: v1
|
||||
weight: 100
|
||||
```
|
||||
|
||||
Notice that the header-based rule has the higher precedence (2 vs. 1). 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 Policies <a id="destination-policies"></a>
|
||||
|
||||
The following subsections provide a overview of the basic fields of a destination policy.
|
||||
A complete and detailed description of a destination policy structure can be found
|
||||
[here](https://github.com/istio/api/blob/master/proxy/v1/config/cfg.md#destination-policies).
|
||||
|
||||
#### Property: destination <a id="destination"></a>
|
||||
|
||||
Exactly the same as in a [route rule](#route-rules),
|
||||
every destination policy includes a *destination* field
|
||||
which identifies the destination microservice for the rule.
|
||||
For example, a destination policy for calls to the "reviews" microservice will include the following field.
|
||||
|
||||
```yaml
|
||||
destination: reviews.default.svc.cluster.local
|
||||
```
|
||||
|
||||
#### Property: tags <a id="tags"></a>
|
||||
|
||||
An optional field, *tags*, is a list of destination tags that can be used to only apply the policy
|
||||
to requests that are routed to backends with the specified tags.
|
||||
|
||||
The following policy will only apply to requests targetting the "v1" version of the "reviews" microserivice.
|
||||
|
||||
```yaml
|
||||
destination: reviews.default.svc.cluster.local
|
||||
tags:
|
||||
version: v1
|
||||
```
|
||||
|
||||
#### Property: loadBalancing <a id="loadBalancing"></a>
|
||||
|
||||
The *loadBalancing* field can be used to specify the load balancing policy for a destination service.
|
||||
The value can be one of `LEAST_CONN`, `RANDOM`, or `ROUND_ROBIN` (default).
|
||||
|
||||
The following destination policy specifies that RANDOM load balancing be used for balancing across
|
||||
instances of any version of the "reviews" microservice:
|
||||
|
||||
```yaml
|
||||
destination: reviews.default.svc.cluster.local
|
||||
loadBalancing: RANDOM
|
||||
```
|
||||
|
||||
#### Property: circuitBreaker <a id="circuitBreaker"></a>
|
||||
|
||||
The *circuitBreaker* field can be used to set a circuit breaker for a particular microservice.
|
||||
A simple circuit breaker can be set based on a number of criteria such as connection and request limits.
|
||||
|
||||
For example, the following destination policy
|
||||
sets a limit of 100 connections to "reviews" service version "v1" backends.
|
||||
|
||||
```yaml
|
||||
destination: reviews.default.svc.cluster.local
|
||||
tags:
|
||||
version: v1
|
||||
circuitBreaker:
|
||||
simpleCb:
|
||||
maxConnections: 100
|
||||
```
|
||||
|
||||
The complete set of simple circuit breaker fields can be found
|
||||
[here](https://github.com/rshriram/api/blob/master/proxy/v1/config/cfg.md#circuitbreakersimplecircuitbreakerpolicy).
|
||||
|
||||
## Destination Policy Evaluation <a id="destination-policy-evaluation"></a>
|
||||
|
||||
Similar to route rules, destination policies are associated with a particular *destination* however
|
||||
if they also include *tags* their activation depends on route rule evaluation results.
|
||||
|
||||
The first step in the rule evaluation process evaluates the route rules for a *destination*,
|
||||
if any are defined, to determine the tags (i.e., specific version) of the destination service
|
||||
that the current request will be routed to. Next, the set of destination policies, if any, are evaluated
|
||||
to determine if they apply.
|
||||
|
||||
One subtlety of the algorithm to keep in mind is that policies that are defined for specific
|
||||
tagged destinations will only be applied if the corresponding tagged instances are explicity
|
||||
routed to. For example, consider the following rule, as the one and only rule defined for
|
||||
the "reviews" microservice.
|
||||
|
||||
```yaml
|
||||
destination: reviews.default.svc.cluster.local
|
||||
tags:
|
||||
version: v1
|
||||
circuitBreaker:
|
||||
simpleCb:
|
||||
maxConnections: 100
|
||||
```
|
||||
|
||||
Since there is no specific route rule defined for the "reviews" microservice, default
|
||||
round-robin routing behavior will apply, which will persumably 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 destination policy to the request.
|
||||
|
||||
You can fix the above example in one of two ways. You can either remove the `tags:`
|
||||
from the rule, if "v1" is the only instance anyway, or, better yet, define proper route rules
|
||||
for the service. For example, you can add a simple route rule for "reviews:v1".
|
||||
|
||||
```yaml
|
||||
destination: reviews.default.svc.cluster.local
|
||||
route:
|
||||
- tags:
|
||||
version: v1
|
||||
```
|
||||
|
||||
Although the default Istio behavior conveniently sends traffic from all versions of a source service
|
||||
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 microservice, right from the start,
|
||||
is generally considered a best practice in Istio.
|
Binary file not shown.
After Width: | Height: | Size: 9.1 KiB |
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 27 KiB |
Binary file not shown.
After Width: | Height: | Size: 62 KiB |
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 348 KiB |
Binary file not shown.
After Width: | Height: | Size: 22 KiB |
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 89 KiB |
Loading…
Reference in New Issue