继续上篇文章:[服务网格Istio系列]--非侵入的流量管理-1
Istio路由规则配置:VirtualService
VirtualService
是Istio流量治理的一个核心配置,可以说是Istio流量治理中最重要,最复杂的规则。
官网参考:https://istio.io/docs/reference/config/networking/virtual-service/#VirtualService
路由规则配置示例
示例:
apiVersion: networking.istio.io/v1alpha3 |
规则意思:对于forecast的访问,如果在请求的Header中location取值是north,则将该请求转发到服务的v2版本上,将其他请求都转发到服务的v1版本上。
路由规则定义
VirtualService
定义了对特定目标服务的一组流量规则。VirtualService
在形式上表示一个虚拟服务,将满足条件的流量都转发到对应的服务后端,这个服务后端可以是一个服务,也可以是在DestnationRule
中定义的服务的子集。
VirtualService
描述了一个具体的服务对象,在该服务内包含了对流量的各种处理,其主体是一个服务而不是一组规则。
VirtualService
中的一些术语如下:
- Service:服务。服务应用程序行为的单元,绑定到服务注册表中的唯一名称。服务由多个endpoints组成,由运行在pod、容器、vm等上的工作负载实例实现。
- Service Version:服务版本,一般是服务的子集。
- Source:发起调用的服务
- Host:服务调用方连接和调用目标服务时使用的地址
通过VirtualService
的配置,应用在访问目标服务时,只需要指定目标服务的地址即可,不需要额外指定其他目标资源的信息。在实际请求中到底将流量路由到哪种特性的后端上,则基于在VirtualService
中配置的路由规则执行。
下图为VirtualService
的第一级的定义,除了hosts、gateways等通用字段,规则的主体是http、tcp和tls,都是复合字段,分别对应HTTPRoute、TCPRoute、TLSRoute,表示istio支持的HTTP、TCP和TLS协议的流量规则。
图片右键在新窗口打开,或者复制图片路径,可以查看原图。
非复合字段hosts和gateways是每种协议都要用到的公共字段。
hosts
hosts表示流量发送的目标。可以将其理解为VirtualService
定义的路由规则的标识,用于匹配访问地址,可以是一个DNS名称或者IP地址。DNS名称可以使用通配符前缀,也可以只使用短域名,也就是说若不用全限定域名FQDN,则一般的运行平台都会把短域名解析成FQDN。
对于Kubernetes平台来说,在Hosts中一般都是Service的短域名。如forecast这种短域名在Kubernetes平台上对应的完整域名是“forecast.weather.svc.cluster.local”,其中weather是forecast服务部署的命名空间。而在Istio中,这种短域名的解析基于VirtualService
这个规则所在的命名空间。建议在规则中明确写完整域名。
注意:VirtualService 的 hosts 的短域名解析到的完整域名时,补齐的 Namespace 是VirtualService
的Namespace,而不是Service的Namespace。
hosts一般建议用字母的域名而不是一个IP地址。IP地址等多用在以Gateway方式发布一个服务的场景,这是hosts匹配Gateway的外部访问地址,当没有做外部域名解析时,可以是外部的IP地址。
gateways
表示应用这些流量规则的Gateway。VirtualService
描述的规则可以作用到网格里的Sidecar和入口处的Gateway,表示将路由规则用于网格内的访问还是网格外经过Gateway的访问。注意以下场景:
- 服务只在网格内访问的,gateways字段可以省略,实际上在
VirtualService
的定义中都不会出现这个字段,一切都很正常,定义的规则作用到网格内的Sidecar。 - 服务只在网格外部访问的。配置要关联的Gateway,表示对应的Gateway进来的流量执行在这个
VirtualService
上定义的流量规则。 - 在网格内核网格外都需要访问的。这里要给这个数组字段至少写两个元素,一个是外部访问的Gateway,另一个是保留关键字
mesh
。
http
是一个与HTTPRoute类型的路由集合,列表形式,用于处理HTTP的流量。
tls
是一个TLSRoute类型的路由集合,列表形式,用于处理非终结的TLS和HTTPS的流量。
tcp
是一个TCPRoute类型的路由集合,列表形式,用于处理TCP的流量,应用于所有其他非HTTP和TLS端口的流量。如果在VirtualService
中对HTTPS和TLS没有定义对应的TLSRoute,则所有流量都被当成TCP流量来处理,都会走到TCP路由集合上。
以上3个字段(http、tls、tcp)在定义上都是数组(列表形式),可以定义多个元素;在使用上都是一个有序列表,在应用时请求匹配的第一个规则生效。
注意:VirtualService中的路由规则是一个数组,在应用时匹配的第1个规则生效就跳出,不会检查后面的规则。
exportTo
用于控制VirtualService
跨命名空间的可见性,这样就可以控制一个在命名空间下定义的VirtualService
是否可以被其他命名空间下的Sidecar和Gateway使用了。如果未赋值,则默认全局可见。点“.”表示仅应用到当前命名空间,星号“”表示应用到所有命名空间。在Istio中只支持“.”和“\”这两种配置。
一级字段官网解释:VirtualService.
https://istio.io/docs/reference/config/networking/virtual-service/#VirtualService
Field | Type | Description | Required |
---|---|---|---|
hosts |
string[] |
The destination hosts to which traffic is being sent. Could be a DNS name with wildcard prefix or an IP address. Depending on the platform, short-names can also be used instead of a FQDN (i.e. has no dots in the name). In such a scenario, the FQDN of the host would be derived based on the underlying platform.A single VirtualService can be used to describe all the traffic properties of the corresponding hosts, including those for multiple HTTP and TCP ports. Alternatively, the traffic properties of a host can be defined using more than one VirtualService, with certain caveats. Refer to the Operations Guide for details.Note for Kubernetes users: When short names are used (e.g. “reviews” instead of “reviews.default.svc.cluster.local”), Istio will interpret the short name based on the namespace of the rule, not the service. A rule in the “default” namespace containing a host “reviews” will be interpreted as “reviews.default.svc.cluster.local”, irrespective of the actual namespace associated with the reviews service. To avoid potential misconfigurations, it is recommended to always use fully qualified domain names over short names.The hosts field applies to both HTTP and TCP services. Service inside the mesh, i.e., those found in the service registry, must always be referred to using their alphanumeric names. IP addresses are allowed only for services defined via the Gateway. | Yes |
gateways |
string[] |
The names of gateways and sidecars that should apply these routes. A single VirtualService is used for sidecars inside the mesh as well as for one or more gateways. The selection condition imposed by this field can be overridden using the source field in the match conditions of protocol-specific routes. The reserved word mesh is used to imply all the sidecars in the mesh. When this field is omitted, the default gateway (mesh ) will be used, which would apply the rule to all sidecars in the mesh. If a list of gateway names is provided, the rules will apply only to the gateways. To apply the rules to both gateways and sidecars, specify mesh as one of the gateway names. |
No |
http |
HTTPRoute[] |
An ordered list of route rules for HTTP traffic. HTTP routes will be applied to platform service ports named ‘http-’/‘http2-’/‘grpc-*’, gateway ports with protocol HTTP/HTTP2/GRPC/ TLS-terminated-HTTPS and service entry ports using HTTP/HTTP2/GRPC protocols. The first rule matching an incoming request is used. | No |
tls |
TLSRoute[] |
An ordered list of route rule for non-terminated TLS & HTTPS traffic. Routing is typically performed using the SNI value presented by the ClientHello message. TLS routes will be applied to platform service ports named ‘https-’, ‘tls-’, unterminated gateway ports using HTTPS/TLS protocols (i.e. with “passthrough” TLS mode) and service entry ports using HTTPS/TLS protocols. The first rule matching an incoming request is used. NOTE: Traffic ‘https-’ or ‘tls-’ ports without associated virtual service will be treated as opaque TCP traffic. | No |
tcp |
TCPRoute[] |
An ordered list of route rules for opaque TCP traffic. TCP routes will be applied to any port that is not a HTTP or TLS port. The first rule matching an incoming request is used. | No |
exportTo |
string[] |
A list of namespaces to which this virtual service is exported. Exporting a virtual service allows it to be used by sidecars and gateways defined in other namespaces. This feature provides a mechanism for service owners and mesh administrators to control the visibility of virtual services across namespace boundaries.If no namespaces are specified then the virtual service is exported to all namespaces by default.The value “.” is reserved and defines an export to the same namespace that the virtual service is declared in. Similarly the value “” is reserved and defines an export to all namespaces.NOTE: in the current release, the exportTo value is restricted to “.” or “” (i.e., the current namespace or all namespaces). |
No |
HTTP路由 HTTPRoute VirtualService.http.
VirtualService
中的http是一个HTTPRoute类型的路由集合,用于处理HTTP的流量。
- 服务的端口协议是HTTP、HTTP2、GRPC,即在服务的端口名中包含http-、http2-、grpc-等。
- Gateway的端口协议是HTTP、HTTP2、GRPC,或者Gateway是终结TLS,即Gateway外部是HTTPS,但内部还是HTTP。
- ServiceEntry的端口协议是HTTP、HTTP2、GRPC。
HTTPRoute规则解析
HTTPRoute的规则定义如下图:
图片右键在新窗口打开,或者复制图片路径,可以查看原图。
HTTPRoute规则的功能是:满足HTTPMatchRequest条件的流量都被路由到HTTPRouteDestination,执行重定向HTTPRedirect、重写HTTPRewrite、重试HTTPRetry、故障注入HTTPFaultInjection、跨站CorsPolicy策略等。HTTP不仅可以做路由匹配,还可以做一些写操作来修改请求本身,非常的灵活:
authority
英 /ɔːˈθɒrəti/ 美 /əˈθɔːrəti/ 全球(加拿大)
n. 权威;权力;当局
复数 authorities
HTTPRoute字段官网解释:VirtualService.http
https://istio.io/docs/reference/config/networking/virtual-service/#HTTPRoute
Describes match conditions and actions for routing HTTP/1.1, HTTP2, and gRPC traffic. See VirtualService for usage examples.
Field | Type | Description | Required |
---|---|---|---|
name |
string |
The name assigned to the route for debugging purposes. The route’s name will be concatenated with the match’s name and will be logged in the access logs for requests matching this route/match. | No |
match |
HTTPMatchRequest[] |
Match conditions to be satisfied for the rule to be activated. All conditions inside a single match block have AND semantics, while the list of match blocks have OR semantics. The rule is matched if any one of the match blocks succeed. | No |
route |
HTTPRouteDestination[] |
A http rule can either redirect or forward (default) traffic. The forwarding target can be one of several versions of a service (see glossary in beginning of document). Weights associated with the service version determine the proportion of traffic it receives. | No |
redirect |
HTTPRedirect |
A http rule can either redirect or forward (default) traffic. If traffic passthrough option is specified in the rule, route/redirect will be ignored. The redirect primitive can be used to send a HTTP 301 redirect to a different URI or Authority. | No |
rewrite |
HTTPRewrite |
Rewrite HTTP URIs and Authority headers. Rewrite cannot be used with Redirect primitive. Rewrite will be performed before forwarding. | No |
timeout |
Duration |
Timeout for HTTP requests. | No |
retries |
HTTPRetry |
Retry policy for HTTP requests. | No |
fault |
HTTPFaultInjection |
Fault injection policy to apply on HTTP traffic at the client side. Note that timeouts or retries will not be enabled when faults are enabled on the client side. | No |
mirror |
Destination |
Mirror HTTP traffic to a another destination in addition to forwarding the requests to the intended destination. Mirrored traffic is on a best effort basis where the sidecar/gateway will not wait for the mirrored cluster to respond before returning the response from the original destination. Statistics will be generated for the mirrored destination. | No |
mirrorPercent |
UInt32Value |
Percentage of the traffic to be mirrored by the mirror field. If this field is absent, all the traffic (100%) will be mirrored. Max value is 100. |
No |
corsPolicy |
CorsPolicy |
Cross-Origin Resource Sharing policy (CORS). Refer to CORS for further details about cross origin resource sharing. | No |
headers |
Headers |
Header manipulation rules | No |
HTTP匹配规则 HTTPMatchRequest VirtualService.http.match.
位置:
在HTTPRoute中最重要的字段是条件字段match,为一个HTTPMatchRequest类型的数组,表示HTTP请求满足的条件,支持将HTTP属性如:uri、method、authority、port等作为条件来匹配请求。一个URI的完整格式是:URI=scheme:[//authority]path[?query][#fragment],如下所示:
fragment
英 /‘frægmənt/ 美 /‘fræɡmənt/ 全球(美国)
n. 碎片;片段或不完整部分
vt. 使成碎片
vi. 破碎或裂开
Authority的定义与Host的定义容易混淆,都是类似于“weather.com”这样的服务主机名,差别在于:
Authority的标准定义是:authority=[userinfo@]host[:port],如下图:
authority标准定义中的字段:
- uri、scheme、method、authority:4个字段都是StringMatch类型,在匹配请求时都支持exact、prefix和regex三种模式的匹配,分别表示完全匹配输入的字符串(exact)、前缀方式匹配(prefix)和正则表达式匹配(regex)。
exact
英 /ɪɡˈzækt/ 美 /ɪɡˈzækt/ 全球(法国)
adj. 准确的,精密的;精确的
vt. 要求;强求;急需
vi. 勒索钱财
比较级 more exact最高级 exactest或most exact
headers:匹配请求中的Header,是一个Map类型。Map的Key是字符串类型,Value仍然是StringMatch类型。即对于每一个Header的值,都可以使用精确、前缀和正则三种方式进行匹配。
例如:自定义headers中source的取值是“north”,并且uri以“/advertisement”开头的请求:
- match
- headers:
source:
exact: north
uri:
prefix: "/advertisement"port:表示请求的服务端口。大部分服务只开放了一个端口,这也是在微服务实战中推荐的做法,在这种场景下可以不用指定port
sourceLabels:是一个map类型的键值对,表示请求涞源的负载匹配标签。在很多时候非常有用,可以对一组服务都打上一个相同的标签,然后使用sourceLabels字段对这些服务实施相同的流量规则。在Kubernetes平台上,这里的Label就是pod上的标签。
例如:表示请求来源是frontend服务的v2版本的负载:
http:
- match:
- sourceLabels:
app: frontend
version: v2gateways:表示规则应用的Gateway名称,语义同
VirtualService
上面的gateways定义,是一个更细的Match条件,会覆盖在VirtualService
上配置的gateways。
注意1:在HTTPRoute的匹配条件中,每个HTTPMatchRequest中的诸多属性都是“与”逻辑,几个HTTPMatchRequest元素间的关系是“或”逻辑。
注意2:在VirtualService
中match字段都是数组类型。HTTPMatchRequest中的诸多属性如uri、headers、method等是“与”逻辑,而数组中几个元素的关系是“或”逻辑。
例如:match包含两个HTTPMatchRequest元素,其条件的语义是:headers中的source取值为north,并且uri以/advertisement开头的请求,或者uri以/forecast开头的请求。
- match |
match 官网说明:
https://istio.io/docs/reference/config/networking/virtual-service/#HTTPMatchRequest
Field | Type | Description | Required |
---|---|---|---|
name |
string |
The name assigned to a match. The match’s name will be concatenated with the parent route’s name and will be logged in the access logs for requests matching this route. | No |
uri |
StringMatch |
URI to match values are case-sensitive and formatted as follows:exact: "value" for exact string matchprefix: "value" for prefix-based matchregex: "value" for ECMAscript style regex-based matchNote: Case-insensitive matching could be enabled via the ignore_uri_case flag. |
No |
scheme |
StringMatch |
URI Scheme values are case-sensitive and formatted as follows:exact: "value" for exact string matchprefix: "value" for prefix-based matchregex: "value" for ECMAscript style regex-based match |
No |
method |
StringMatch |
HTTP Method values are case-sensitive and formatted as follows:exact: "value" for exact string matchprefix: "value" for prefix-based matchregex: "value" for ECMAscript style regex-based match |
No |
authority |
StringMatch |
HTTP Authority values are case-sensitive and formatted as follows:exact: "value" for exact string matchprefix: "value" for prefix-based matchregex: "value" for ECMAscript style regex-based match |
No |
headers |
map |
The header keys must be lowercase and use hyphen as the separator, e.g. x-request-id.Header values are case-sensitive and formatted as follows:exact: "value" for exact string matchprefix: "value" for prefix-based matchregex: "value" for ECMAscript style regex-based matchNote: The keys uri , scheme , method , and authority will be ignored. |
No |
port |
uint32 |
Specifies the ports on the host that is being addressed. Many services only expose a single port or label ports with the protocols they support, in these cases it is not required to explicitly select the port. | No |
sourceLabels |
map |
One or more labels that constrain the applicability of a rule to workloads with the given labels. If the VirtualService has a list of gateways specified at the top, it must include the reserved gateway mesh for this field to be applicable. |
No |
queryParams |
map |
Query parameters for matching.Ex: - For a query parameter like “?key=true”, the map key would be “key” and the string match could be defined as exact: "true" . - For a query parameter like “?key”, the map key would be “key” and the string match could be defined as exact: "" . - For a query parameter like “?key=123”, the map key would be “key” and the string match could be defined as regex: "\d+$" . Note that this configuration will only match values like “123” but not “a123” or “123a”.Note: prefix matching is currently not supported. |
No |
ignoreUriCase |
bool |
Flag to specify whether the URI matching should be case-insensitive.Note: The case will be ignored only in the case of exact and prefix URI matches. |
No |
StringMatch
如下:
Field | Type | Description | Required |
---|---|---|---|
exact |
string (oneof) |
exact string match | Yes |
prefix |
string (oneof) |
prefix-based match | Yes |
regex |
string (oneof) |
ECMAscript style regex-based match | Yes |
HTTP路由目标 HTTPRouteDestination VirtualService.http.route.
位置:
HTTPRoute上的route字段是一个HTTPRouteDestination类型的数组,表示满足条件的流量目标。
... |
在HTTPRouteDestination中主要有三个字段:Destination(请求目标),weight(权重)和headers(HTTP头操作),Destination和weight是必须字段。
destination
核心字段destination表示请求的目标。在
VirtualService
上执行一组规则,最终的流量要被送到这个目标上,这个字段是一个Destination类型的结构,通过host、subset和port三个属性来描述。host 是Destination的必选字段,表示Istio中注册的服务名,不但包括网格内的服务,也包括通过ServiceEntry方式注册的外部服务。在Kubernetes平台上如果用到短域名,istio就会根据规则的命名空间解析服务名,而不是根据Service的命名空间来解析。所以建议在使用上写全域名,这和
VirtualService
上的hosts用法类似。...
namespace: weather
...
spec:
hosts:
- forecast
http:
route:
- destination:
host: forecast # 服务全名是:forecast.weather.svc.cluster.local
subset: v2
- route:
- destination:
host: forecast # 服务全名是:forecast.weather.svc.cluster.local
subset: v1如果在这个
VirtualService
上没有写namespace,则后端地址会是forecast.default.svc.cluster.local。建议通过如下方式写服务的全名,即不管规则在哪个命名空间下,后端地址总是明确的:route:
- destination:
host: forecast.weather.svc.cluster.local
subset: v2
- route:
- destination:
host: forecast.weather.svc.cluster.local
subset: v1与host匹配来表示流量路由后端的是另一个重要字段subset,它表示在host上定义的一个子集。例如:在灰度发布中奖版本定义为subset,配置路由策略会将流量转发到不同版本的subset上。
weight
除了 destination,HTTPRouteDestination 上的另一个必选字段是 weight,表示流量分配的比例,在一个route下多个destination的weight总和要求是100。
例如:从原有的v1版本中切分20%的流量到v2版本,这也是灰度发布常用的一种流量策略,即不区分内容,平等地从总流量中切出一部分流量给新版本:
...
spec:
hosts:
- forecast
http:
- route:
- destination:
host: forecast
subset: v2
weight: 20
- destination:
host: forecast
subset: v1
weight: 80如果一个route只有一个destination,那么可以不用配置weight,默认就是100。如下所示为将全部流量都转到这一个destination上:
http:
- route:
- destination:
host: forecastheaders
headers字段提供了对HTTP Header的一种操作机制,可以修改一次HTTP请求中Request或者Response的值,包含request和response两个字段。
request:表示在发请求给目标地址时修改Request的Header。
response:表示在返回应答时修改Response的Header。
对应的类型都是HeaderOperation类型,使用set、add、remove字段来定义对Header的操作。
- set: 使用map上的Key和Value覆盖response或者request中对应的Header。
- add:追加map上的Key和Value到原有Header。
- remove:删除在列表中指定的Header。
以上分别介绍了 HTTP 请求匹配条件的定义和 HTTP 目标路由的定义,这也是HTTPRoute的要功能。Istio对于HTTP除了可以做流量的路由,还可以做适当的其他操作,很多原来需要在代码里进行的HTTP 操作,在使用 Istio 后通过这些配置都可以达到同样的效果。
route 官网说明:
https://istio.io/docs/reference/config/networking/virtual-service/#HTTPRouteDestination
Field | Type | Description | Required |
---|---|---|---|
destination |
Destination |
Destination uniquely identifies the instances of a service to which the request/connection should be forwarded to. | Yes |
weight |
int32 |
The proportion of traffic to be forwarded to the service version. (0-100). Sum of weights across destinations SHOULD BE == 100. If there is only one destination in a rule, the weight value is assumed to be 100. | No |
headers |
Headers |
Header manipulation rules | No |
removeResponseHeaders |
string[] |
Use of remove_response_header is deprecated. Use the headers field instead. |
No |
appendResponseHeaders |
map |
Use of append_response_headers is deprecated. Use the headers field instead. |
No |
removeRequestHeaders |
string[] |
Use of remove_request_headers is deprecated. Use the headers field instead. |
No |
appendRequestHeaders |
map |
Use of append_request_headers is deprecated. Use the headers field instead. |
No |
Destination
字段:
Field | Type | Description | Required |
---|---|---|---|
host |
string |
The name of a service from the service registry. Service names are looked up from the platform’s service registry (e.g., Kubernetes services, Consul services, etc.) and from the hosts declared by ServiceEntry. Traffic forwarded to destinations that are not found in either of the two, will be dropped.Note for Kubernetes users: When short names are used (e.g. “reviews” instead of “reviews.default.svc.cluster.local”), Istio will interpret the short name based on the namespace of the rule, not the service. A rule in the “default” namespace containing a host “reviews will be interpreted as “reviews.default.svc.cluster.local”, irrespective of the actual namespace associated with the reviews service. To avoid potential misconfigurations, it is recommended to always use fully qualified domain names over short names. | Yes |
subset |
string |
The name of a subset within the service. Applicable only to services within the mesh. The subset must be defined in a corresponding DestinationRule. | No |
port |
PortSelector |
Specifies the port on the host that is being addressed. If a service exposes only a single port it is not required to explicitly select the port. | No |
PortSelector
字段:
Field | Type | Description | Required |
---|---|---|---|
number |
uint32 |
Valid port number | No |
Headers字段:
Field | Type | Description | Required |
---|---|---|---|
request |
HeaderOperations |
Header manipulation rules to apply before forwarding a request to the destination service | No |
response |
HeaderOperations |
Header manipulation rules to apply before returning a response to the caller | No |
HeaderOperations
字段
Field | Type | Description | Required |
---|---|---|---|
set |
map |
Overwrite the headers specified by key with the given values | No |
add |
map |
Append the given values to the headers specified by keys (will create a comma-separated list of values) | No |
remove |
string[] |
Remove a the specified headers | No |
HTTP重定向 HTTPRedirect VirtualService.http.redirect.
通过HTTPRedirect可以发送一个301重定向的应答给服务调用方,简单讲就是从一个URL到另一个URL的永久重定向。
如下图:用户输入一个URL,通过HTTPRedirect可以将其跳转到另一个URL。比较常见的场景:有一个在线网站,网址变了,通过这样的重定向,可以在用户输入老地址时跳转到新地址:
HTTPRedirect包括两个重要的字段来表示重定向的目标:
uri:替换URL中的Path部分
authority:替换URL中的Authority部分。
需要注意的是:这里使用HTTPRedirect的uri配置会替换原请求中的完整PATH,而不是匹配条件上的uri部分,如下所示:对forecast服务所有前缀是/advertisement
的请求都会被重定向到new-forecast的/recommendation/activity
地址:
apiVersion: networking.istio.io/v1alpha3 |
redirect 官网解释:
HTTPRedirect can be used to send a 301 redirect response to the caller, where the Authority/Host and the URI in the response can be swapped with the specified values. For example, the following rule redirects requests for /v1/getProductRatings API on the ratings service to /v1/bookRatings provided by the bookratings service.
https://istio.io/docs/reference/config/networking/virtual-service/#HTTPRedirect
Field | Type | Description | Required |
---|---|---|---|
uri |
string |
On a redirect, overwrite the Path portion of the URL with this value. Note that the entire path will be replaced, irrespective of the request URI being matched as an exact path or prefix. | No |
authority |
string |
On a redirect, overwrite the Authority/Host portion of the URL with this value. | No |
redirectCode |
uint32 |
On a redirect, Specifies the HTTP status code to use in the redirect response. The default response code is MOVED_PERMANENTLY (301). | No |
HTTP重写 HTTPRewrite VirtualService.http.rewrite.
通过HTTP重写可以在将请求转发给目标服务钱修改HTTP请求中指定部分的内容,流程如下图。不同于重定向对用户可见,比如浏览器地址栏里的地址会变成重定向的地址,HTTP重写对最终用户是不可见的,因为是在服务端进行的。
和HTTPRedirect相同,重写HTTPRewrite也包括两个字段:
- uri:重写URL中的Path部分。
- authority:重写URL中的Authority部分。
和HTTPRedirect规则不同的:HTTPRedirect的uri只能替换全部Path,HTTPRewrite的uri是可以重写前缀的,即如果原来的匹配条件是前缀匹配,则修改后也只修改匹配到的前缀。
如下图,前缀匹配/advertisement
的请求,其请求uri中的这部分前缀会被/recommendation/activity
替换:
apiVersion: networking.istio.io/v1alpha3 |
rewrite 字段 官网说明:
https://istio.io/docs/reference/config/networking/virtual-service/#HTTPRewrite
Field | Type | Description | Required |
---|---|---|---|
uri |
string |
rewrite the path (or the prefix) portion of the URI with this value. If the original URI was matched based on prefix, the value provided in this field will replace the corresponding matched prefix. | No |
authority |
string |
rewrite the Authority/Host header with this value. | No |
HTTP重试 HTTPRetry VirtualService.http.retries.
HTTP重试是解决很多请求异常最直接,最简单的办法。尤其是在工作环境比较复杂的场景下,可提高总体的服务质量。但重试使用不当也会有问题,最糟糕的情况是重试一直不成功,反而增加了总的延迟和性能开销。所以,根据系统运行环境、服务自身特点,配置适当的重试规则显得尤为重要。
HTTPRetry可以定义请求失败时的重试策略。重试策略包括重试次数、超时、重试条件等:
attempts:必选字段,定义重试的次数。
perTryTimeout:每次重试的超时时间,单位可以是毫秒ms,秒s,分钟m,小时h。
retryOn:进行重试的条件,可以是多个条件,以逗号分隔。取值包括以下几种:
- 5xx:在上游服务返回5xx应答码,只对502/503/504应答码进行重试。
- connect-failure:在上游服务失败时重试。
- retriable-4xx:在上游服务返回可重试的4xx应答码时重试。
- refused-stream:在上游服务使用REFUSED_STREAM错误码重置时进行重试。
- cancelled:在gRPC应答的Header中状态码是cancelled时进行重试。
- deadline-exceeded:在gRPC应答的Header中状态码是deadline-exceeded时进行重试。
- internal:在gRPC应答的Header中状态码是internal时执行重试。
- resource-exhausted:在gRPC应答的Header中状态码是resource-exhausted时执行重试。
- unavailable:在gRPC应答的Header中状态码是unavailable时执行重试。
如下示例,forecast服务配置了一个重试策略,在“5xx, connect-failure”条件下进行最多5次的重试,每次重试的超时时间是3秒:
apiVersion: networking.istio.io/v1alpha3 |
retries 字段 官网说明:
https://istio.io/docs/reference/config/networking/virtual-service/#HTTPRetry
Field | Type | Description | Required |
---|---|---|---|
attempts |
int32 |
Number of retries for a given request. The interval between retries will be determined automatically (25ms+). Actual number of retries attempted depends on the httpReqTimeout. | Yes |
perTryTimeout |
Duration |
Timeout per retry attempt for a given request. format: 1h/1m/1s/1ms. MUST BE >=1ms. | No |
retryOn |
string |
Specifies the conditions under which retry takes place. One or more policies can be specified using a ‘,’ delimited list. See the retry policies and gRPC retry policies for more details. | No |
HTTP流量镜像 Mirror VirtualService.http.mirror.
HTTP流量镜像指的是在将流量转发到原目标地址的同时将流量给另一个目标地址镜像一份。如下图,把生产系统中宝贵的时间流量镜像一份到另一个系统上,完全不会对生产系统产生影响,这里只镜像了一份流量,数据面代理制需关注原来转发的流量就可以,不用等待镜像目标地址的返回。
配置如下:
apiVersion: networking.istio.io/v1alpha3 |
mirror 字段下面等同于destination:
Field | Type | Description | Required |
---|---|---|---|
host |
string |
The name of a service from the service registry. Service names are looked up from the platform’s service registry (e.g., Kubernetes services, Consul services, etc.) and from the hosts declared by ServiceEntry. Traffic forwarded to destinations that are not found in either of the two, will be dropped.Note for Kubernetes users: When short names are used (e.g. “reviews” instead of “reviews.default.svc.cluster.local”), Istio will interpret the short name based on the namespace of the rule, not the service. A rule in the “default” namespace containing a host “reviews will be interpreted as “reviews.default.svc.cluster.local”, irrespective of the actual namespace associated with the reviews service. To avoid potential misconfigurations, it is recommended to always use fully qualified domain names over short names. | Yes |
subset |
string |
The name of a subset within the service. Applicable only to services within the mesh. The subset must be defined in a corresponding DestinationRule. | No |
port |
PortSelector |
Specifies the port on the host that is being addressed. If a service exposes only a single port it is not required to explicitly select the port. | No |
HTTP故障注入 HTTPFaultInjection VirtualService.http.fault.
在HTTP上做故障注入和Redirect、Rewrite、Retry没有太多差别,都是修改HTTP请求或者应答的内容。在使用故障注入时不能启用超时和重试。
通过delay和abort两个字段配置延时和中止两种故障,分别表示Proxy延迟转发HTTP请求和中止HTTP请求:
延迟故障注入使用delay字段,表示在发送请求前进行一段时间的延迟,模拟网格,远程服务负载等各种原因导致的失败,主要有如下两个字段:
fixedDelay:一个必选字段,表示延迟时间,但是可以是毫秒、秒、分钟和小时,要求时间必须大于1毫秒。
percentage:配置的延迟故障作用在多少比例的请求上,通过这种方式可以只让部分请求发生故障。如下,让forecast服务的v2版本上1.5%的请求产生10s的延迟:
......
route:
- destination:
host: forecast
subset: v2
fault:
delay:
percentage:
value: 1.5
fixedDelay: 10s
请求中止故障注入,使用abort字段,模拟服务端异常,给调用的客户端返回预先定义的错误状态码,主要有如下两个字段:
httpStatus:必选字段,表示中止的HTTP状态码。
percentage:配置的中止故障作用在多少比例的请求上。如下示例,让forecast服务v2版本上1.5%的请求返回500状态码:
......
route:
- destination:
host: forecast
subset: v2
fault:
abort:
percentage:
value: 1.5
httpStatus: 500
fault 字段官方说明:
https://istio.io/docs/reference/config/networking/virtual-service/#HTTPFaultInjection
Field | Type | Description | Required |
---|---|---|---|
delay |
Delay |
Delay requests before forwarding, emulating various failures such as network issues, overloaded upstream service, etc. | No |
abort |
Abort |
Abort Http request attempts and return error codes back to downstream service, giving the impression that the upstream service is faulty. | No |
Delay 字段:
fixedDelay |
Duration (oneof) |
Add a fixed delay before forwarding the request. Format: 1h/1m/1s/1ms. MUST be >=1ms. | Yes |
---|---|---|---|
percentage |
Percent |
Percentage of requests on which the delay will be injected. | No |
percent |
int32 |
Percentage of requests on which the delay will be injected (0-100). Use of integer percent value is deprecated. Use the double percentage field instead. |
No |
About 字段:
httpStatus |
int32 (oneof) |
HTTP status code to use to abort the Http request. | Yes |
---|---|---|---|
percentage |
Percent |
Percentage of requests to be aborted with the error code provided. | No |
percent |
int32 |
Percentage of requests to be aborted with the error code provided (0-100). Use of integer percent value is deprecated. Use the double percentage field instead. |
No |
HTTP跨域资源共享 CorsPolicy VirtualService.http.corsPolicy.
当一个资源向该资源所在服务器的不同域发起请求时,就会产生一个跨域的HTTP请求,出于安全原因,浏览器会限制从脚本发起的跨域HTTP请求。通过跨域资源共享CORS(Cross Origin Resource Sharing)机制可允许Web应用服务器进行跨域访问控制,是跨域数据传输安全进行。在实现上是在HTTP Header中追加一些额外的信息来通知浏览器准许以上访问。
在VirtualService
中可以对满足条件的请求配置跨域资源共享:
- allowOrigin:允许跨域资源共享的源的列表,在内容被序列化后,被添加到Access-Control-Allow-Origin的Header上。当使用通配符“*”时表示允许所有。
- allowMethods:允许访问资源的HTTP方法列表,内容被序列化到Access-Control-Allow-Methods的 Header上。
- allowHeaders:请求资源的HTTP Header列表,内容被序列化到Access-Control-Allow-Headers的Header上。
- exposeHeaders:浏览器允许访问的HTTP Header的白名单,内容被序列化到Access-Control-Expose-Headers的header上。
- maxAge:请求缓存的时长,被转化为Access-Control-Max-Age的Header上。
- allowCredentials:是否允许服务调用方使用凭据发起时间请求,被转化为Access-Control-Allow-Credentials的Header。
我们给forecast服务配置跨域策略,允许源自news.com的GET方法的请求的访问:
apiVersion: networking.istio.io/v1alpha3 |
corsPolicy 字段官网说明:
https://istio.io/docs/reference/config/networking/virtual-service/#CorsPolicy
Field | Type | Description | Required |
---|---|---|---|
allowOrigin |
string[] |
The list of origins that are allowed to perform CORS requests. The content will be serialized into the Access-Control-Allow-Origin header. Wildcard * will allow all origins. | No |
allowMethods |
string[] |
List of HTTP methods allowed to access the resource. The content will be serialized into the Access-Control-Allow-Methods header. | No |
allowHeaders |
string[] |
List of HTTP headers that can be used when requesting the resource. Serialized to Access-Control-Allow-Headers header. | No |
exposeHeaders |
string[] |
A white list of HTTP headers that the browsers are allowed to access. Serialized into Access-Control-Expose-Headers header. | No |
maxAge |
Duration |
Specifies how long the results of a preflight request can be cached. Translates to the Access-Control-Max-Age header. |
No |
allowCredentials |
BoolValue |
Indicates whether the caller is allowed to send the actual request (not the preflight) using credentials. Translates to Access-Control-Allow-Credentials header. |
No |
TLS路由 TLSRoute VirtualService.tls.
在VirtualService
中,tls是一种TLSRoute类型的路由集合,用于处理非终结的TLS和HTTPS流量,选择SNI(Server Name Indication,客户端在TLS握手阶段建立连接使用的服务Hostname)做路由选择。TLSRoute应用场景如下:
Indication
英 /ˌɪndɪˈkeɪʃn/ 美 /ˌɪndɪˈkeɪʃn/ 全球(美国)
n. 指示,指出;迹象;象征
复数 indications
- 服务的端口协议是HTTPS和TLS。即在服务的端口名中包含https-、tls-等。
- Gateway的端口是非终结的HTTPS和TLS。
- ServiceEntry的端口是HTTPS和TLS。
TLSRoute配置示例
简单配置如下:
apiVersion: networking.istio.io/v1alpha3 |
解释:
可以通过HTTPS方式从外部访问weather应用内部的两个HTTPS服务frontend和recommendation,访问目标端口是443并且SNI是frontend.weather.com的请求会被转发到frontend服务上,访问目标端口443并且SNI是recommendation.weather.com的请求会被转发到recommendation服务上。
TLSRoute规则解析
规则逻辑是将满足一定条件的流量转发到对应的后端。匹配条件是TLSMatchAttributes,路由规则目标是RouteDestination。
tls 字段官方说明:
https://istio.io/docs/reference/config/networking/virtual-service/#TLSRoute
Field | Type | Description | Required |
---|---|---|---|
match |
TLSMatchAttributes[] |
Match conditions to be satisfied for the rule to be activated. All conditions inside a single match block have AND semantics, while the list of match blocks have OR semantics. The rule is matched if any one of the match blocks succeed. | Yes |
route |
RouteDestination[] |
The destination to which the connection should be forwarded to. | No |
TLS匹配规则 TLSMatchAttributes VirtualService.tls.match
在TLSRoute中,match字段是一个TLSMatchAttributes类型的数组,表示TLS的匹配条件,从以下几个方面描述一个TLS服务的请求特性。
- sniHosts:必选字段,用来匹配TLS请求的SNI。SNI的值必须是VirtualService的Hosts的子集。
- destinationSubnets:目标IP地址匹配的IP子网。
- port:访问的目标端口
- sourceLabels:一个map类型的键值对,匹配来源负载的标签。
- gateways:表示规则适用的Gateway名字。覆盖VirtualService上的gateways定义。
sniHosts和destinationSubnets是TLS特有的,port、sourceLabels和gateways属性同HTTP的条件定义,一般的用法匹配port和sniHosts,配置如下:
tls: |
tls.match 官方说明:
https://istio.io/docs/reference/config/networking/virtual-service/#TLSMatchAttributes
Field | Type | Description | Required |
---|---|---|---|
sniHosts |
string[] |
SNI (server name indicator) to match on. Wildcard prefixes can be used in the SNI value, e.g., *.com will match foo.example.com as well as example.com. An SNI value must be a subset (i.e., fall within the domain) of the corresponding virtual serivce’s hosts. | Yes |
destinationSubnets |
string[] |
IPv4 or IPv6 ip addresses of destination with optional subnet. E.g., a.b.c.d/xx form or just a.b.c.d. | No |
port |
uint32 |
Specifies the port on the host that is being addressed. Many services only expose a single port or label ports with the protocols they support, in these cases it is not required to explicitly select the port. | No |
sourceLabels |
map |
One or more labels that constrain the applicability of a rule to workloads with the given labels. If the VirtualService has a list of gateways specified at the top, it should include the reserved gateway mesh in order for this field to be applicable. |
No |
gateways |
string[] |
Names of gateways where the rule should be applied to. Gateway names at the top of the VirtualService (if any) are overridden. The gateway match is independent of sourceLabels. | No |
TLS四层路由目标 RouteDestination VirtualService.tls.route
TLS的路由目标通过RouteDestination来描述转发的目的地址,这是一个四层路由转发地址,包含两个必须属性destination和weight。
- destination:表示满足条件的流量的目标。
- weight:表示切分的流量比例。
tls.route 官方说明:
Field | Type | Description | Required |
---|---|---|---|
destination |
Destination |
Destination uniquely identifies the instances of a service to which the request/connection should be forwarded to. | Yes |
weight |
int32 |
The proportion of traffic to be forwarded to the service version. If there is only one destination in a rule, all traffic will be routed to it irrespective of the weight. | No |
tls.route.destination.
Field | Type | Description | Required |
---|---|---|---|
host |
string |
The name of a service from the service registry. Service names are looked up from the platform’s service registry (e.g., Kubernetes services, Consul services, etc.) and from the hosts declared by ServiceEntry. Traffic forwarded to destinations that are not found in either of the two, will be dropped.Note for Kubernetes users: When short names are used (e.g. “reviews” instead of “reviews.default.svc.cluster.local”), Istio will interpret the short name based on the namespace of the rule, not the service. A rule in the “default” namespace containing a host “reviews will be interpreted as “reviews.default.svc.cluster.local”, irrespective of the actual namespace associated with the reviews service. To avoid potential misconfigurations, it is recommended to always use fully qualified domain names over short names. | Yes |
subset |
string |
The name of a subset within the service. Applicable only to services within the mesh. The subset must be defined in a corresponding DestinationRule. | No |
port |
PortSelector |
Specifies the port on the host that is being addressed. If a service exposes only a single port it is not required to explicitly select the port. | No |
TCP路由 TCPRoute VirtualService.tcp.
所有不满足以上HTTP和TLS条件的流量都会应用TCP流量规则。
TCPRoute配置示例
如下:将来自frontend服务23003端口的流量转发到inner-forecast服务的3003端口:
apiVersion: networking.istio.io/v1alpha3 |
TCPRoute规则解析
TCPRoute的规则描述也是将满足一定条件的流量转发到对应的目标后端,后端是四层的RouteDestination。
四层匹配规则L4MatchAttributes VirtualService.tcp.match.
match 字段也是一个数组,元素类型是L4MatchAttributes,支持一下匹配属性:
- destinationSubnets:目标IP地址匹配的IP子网。
- port:访问的目标端口。
- sourceLabels:源工作负载标签。
- gateways:Gateway的名称。
这几个字段和TLSMatchAttributes对应的字段意义相同,以下基于端口和源工作负载描述TCP流量的典型实例:
tcp: |
tcp.match 字段官方说明:
https://istio.io/docs/reference/config/networking/virtual-service/#L4MatchAttributes
Field | Type | Description | Required |
---|---|---|---|
destinationSubnets |
string[] |
IPv4 or IPv6 ip addresses of destination with optional subnet. E.g., a.b.c.d/xx form or just a.b.c.d. | No |
port |
uint32 |
Specifies the port on the host that is being addressed. Many services only expose a single port or label ports with the protocols they support, in these cases it is not required to explicitly select the port. | No |
sourceLabels |
map |
One or more labels that constrain the applicability of a rule to workloads with the given labels. If the VirtualService has a list of gateways specified at the top, it should include the reserved gateway mesh in order for this field to be applicable. |
No |
gateways |
string[] |
Names of gateways where the rule should be applied to. Gateway names at the top of the VirtualService (if any) are overridden. The gateway match is independent of sourceLabels. | No |
tcp.route 字段官方说明:
https://istio.io/docs/reference/config/networking/virtual-service/#RouteDestination
Field | Type | Description | Required |
---|---|---|---|
destination |
Destination |
Destination uniquely identifies the instances of a service to which the request/connection should be forwarded to. | Yes |
weight |
int32 |
The proportion of traffic to be forwarded to the service version. If there is only one destination in a rule, all traffic will be routed to it irrespective of the weight. | No |
Destination 字段,等同于上面的Destination字段。
Field | Type | Description | Required |
---|---|---|---|
host |
string |
The name of a service from the service registry. Service names are looked up from the platform’s service registry (e.g., Kubernetes services, Consul services, etc.) and from the hosts declared by ServiceEntry. Traffic forwarded to destinations that are not found in either of the two, will be dropped.Note for Kubernetes users: When short names are used (e.g. “reviews” instead of “reviews.default.svc.cluster.local”), Istio will interpret the short name based on the namespace of the rule, not the service. A rule in the “default” namespace containing a host “reviews will be interpreted as “reviews.default.svc.cluster.local”, irrespective of the actual namespace associated with the reviews service. To avoid potential misconfigurations, it is recommended to always use fully qualified domain names over short names. | Yes |
subset |
string |
The name of a subset within the service. Applicable only to services within the mesh. The subset must be defined in a corresponding DestinationRule. | No |
port |
PortSelector |
Specifies the port on the host that is being addressed. If a service exposes only a single port it is not required to explicitly select the port. | No |
三种协议路由规则的对比
VirtualService在http、tls和tcp这三个字段上分别定义了应用于HTTP、TLS和TCP三种协议的路由规则。从规则构成上都是先定义一组匹配条件,然后对满足条件的流量执行对应的操作。因为协议的内容不同,路由规则匹配的条件不同,所以可执行的操作也不同。如下表所示对比了三种路由规则,从各个维度来看,HTTP路由规则的内容最丰富,TCP路由规则的内容最少,这也符合协议分层的设计。
VirtualService的典型应用
多个服务的组合
VirtualService
是一个广义的Service,如下配置:将一个weather应用的多个服务组装成一个大的虚拟服务。根据访问路径不同,对weather服务的访问会被转发到不同的内部服务上:
apiVersion: networking.istio.io/v1alpha3 |
架设frontend服务访问weather.com服务,则根据不同的路径,流量 会被分发到不同的后端服务上。当然,对于内部服务间的访问,更常规的用法是直接使用服务名。
路由规则的优先级
可以对一个VirtualService配置N个路由,在VirtualService中通过路由的顺序即可明确表达规则。
如下示例:以/weather/data/开头的流量被转发到v3版本;以/weather/开头的其他流量被转发到v2版本;其他流量被转发到v1版本:
apiVersion: networking.istio.io/v1alpha3 |
以上三条路由规则随便调整顺序,都会导致另一个规则在理论上不会有流量。例如,调整v2和v3的顺序,则匹配“/weather/”的所有流量都被路由到v2版本,在v3版本上永远不会有流量。在路由规则执行时,只要有一个匹配,规则执行就会跳出,类似代码中的switch分支,碰到一个匹配的case就break,不会再尝试下面的条件。这也是在设计流量规则时需要注意的。
复杂条件路由
灰度发布等分流规则一般有两种用法:
- 基于请求的内容切分流量
- 按比例切分流量
实际上也可以结合使用这两种用法,如下:
apiVersion: networking.istio.io/v1alpha3 |
这里的http路由包含两个HTTPRoute,只有第1个包含match条件,根据优先级路由列表的顺序优先级原则,满足第 1个 route中 match条件的流量走第 1个路由,剩下的流量都走第2个路由。
在第一个路由的match条件数组中包含两个HTTPMatchRequest条件:第一个条件检查请求的uri和headers;第二个条件检查请求的uri。根据请求的组合规则,第一个条件的两个属性是与逻辑,第一个和第二个条件之间是或逻辑。
第一个Route包含两个路由目标,分别对应20%和80%的流量。
整个复杂条件表达的路由规则如下图:
对于forecast服务的请求,当请求的cookie满足^(.*?;)?(local=north)(;.*)?
表达式,并且uri匹配/weather,或者请求的uri匹配/data时,流量走v2和v3版本,其中v2版本的流量占20%,v3版本占80%;其他流量都走forecast的v1版本:
特定版本间的访问规则
通过sourceLabels字段可以用于过了访问来源,如下,只对frontend服务的v2版本到forecast服务的v1版本的请求设置20s的延迟:
apiVersion: networking.istio.io/v1alpha3 |
效果如下图:
VirtualService 字段 思维导图
图片右键在新窗口打开,或者复制图片路径,可以查看原图。
点击这里,查看思维导图网页版,可以查看字段的解释说明,可以保存该网页到本地。
Istio目标规则配置:DestinationRule
在上面的VirtualService中,路由的目标对象Destination中大多包含表示Service子集的subset字段,这个服务子集就是通过DestinationRule定义的。
DestinationRule配置示例
如下,定义了forecast服务的两个版本子集v1和v2,并且两个版本分别配置了随机和轮询的负载均衡策略:
apiVersion: networking.istio.io/v1alpha3 |
DestinationRule规则定义
DestinationRule经常和VirtualService结合使用,VirtualService用到的服务子集subset在DestinationRule上也有定义。同时,在VirtualService上定义了一些规则,在DestinationRule上也定义了一些规则。
如何理解两者的定位、差别和配合关系呢?
观察下面一段 Restful 服务端代码,在前面的Resource 部分将“/forecast”的 POST 请求路由到一个 addForecast 的后端方法上,将“/forecast/hangzhou”的GET请求路由到一个getForecast的天气检索后端方法上:
VirtualService也是一个虚拟Service,描述的是满足什么条件的流量被哪个后端处理。可以对应这样一个Restful服务,每个路由规则都对应其中Resource中的资源匹配表达式。只是在 VirtualService 中,这个匹配条件不仅仅是路径方法的匹配,还是更开放的 Match条件。
而 DestinationRule 描述的是这个请求到达某个后端后怎么去处理,即所谓目标的规则,类似以上Restful服务端代码中addForecast()和getForecast()方法内的处理逻辑。
理解了这两个对象的定位,就不难理解其规则上的设计原理,从而理解负载均衡和熔断等策略为什么被定义在DestinationRule上。DestinationRule定义了满足路由规则的流量到达后端后的访问策略。在Istio中可以配置目标服务的负载均衡策略、连接池大小、异常实例驱逐规则等功能。在前面Restful的例子中服务端的处理逻辑是服务开发者提供的,类似地,在DestinationRule中这些服务管理策略也是服务所有者维护和管理的。
上面说到的几个配置在DestinationRule中都不仅仅是对一个后端服务的配置,还可以配置到每个子集Subset甚至每个端口上。这也不难理解,在计算机世界里,服务是一个到处被使用的术语,从 IaaS、PaaS、SaaS 这种业务上的服务,到微服务化术语中功能实现模块的服务,其最本源的定义应该是监听在某个特定端口上对外提供功能的服务。DestinationRule配置的策略正是配置到这种端口粒度的服务上。
DestinationRule定义如下:
图片右键在新窗口打开,或者复制图片路径,可以查看原图。
outlier
英 /ˈaʊtlaɪə(r)/ 美 /ˈaʊtlaɪər/ 全球(英国)
n. 离开主体的人(或物);(地质)外露层;(统计)异常值;局外人(远离业务、职务)detection
英 /dɪˈtekʃn/ 美 /dɪˈtekʃn/ 全球(美国)
n. 侦查,探测;发觉,发现;察觉
复数 detectionsconsistent
英 /kənˈsɪstənt/ 美 /kənˈsɪstənt/ 全球(美国)
adj. 始终如一的,一致的;坚持的
比较级 more consistent最高级 most consistentconsecutive
英 /kənˈsekjətɪv/ 美 /kənˈsekjətɪv/
adj. 连贯的;连续不断的ejection
英 /ɪˈdʒekʃn/ 美 /ɪˈdʒekʃn/ 全球(美国)
n. 喷出;排出物
复数 ejections
DestinationRule上的重要属性如下:
- host:必选字段,表示规则的适用对象,取值是在服务注册中心注册的服务名,可以是网格内的服务,也可以是ServiceEntry方式注册的网格外部的服务。如果这个服务名在服务注册中心不存在,则这个规则无效。host如果取短域名,则会根据规则所在的命名空间进行解析,方式同上面的VirtualService的解析规则。
- trafficPolicy:是规则内容的定义,包括负载均衡、连接池策略、异常点检查等。
- subsets:一个服务的子集,经常用来定义一个服务版本。
- exportTo:用于控制DestinationRule跨命名空间的可见性,这样就可以控制在一个命名空间下定义的资源对象是否可以被其他命名空间下的Sidecar执行。如果未赋值,默认全局可见。“.”表示仅应用到当前命名空间,“*”表示应用到所有的命名空间。在Istio 1.1中只支持“.”和“*”这两种配置。
流量策略 TrafficPolicy DestinationRule.trafficPolicy
整个DestinationRule中主要数据结构接种在流量策略方面。
流量策略包含以下5个重要配置:
- LoadBalancer:LoadBalancerSettings类型,描述服务的负载均衡算法。
- connectionPool:ConnectionPoolSettings类型,描述服务的连接池配置。
- outlierDetection:OutlierDetection,描述服务的异常点检查。
- tls:TLSSettings类型,描述服务的TLS连接设置
- portLevelSetting:PortTrafficPolicy类型,表示对每个端口的流量策略。
负载均衡设置 LoadBalancerSettings DestinationRule.trafficPolicy.loadBalancer.
负载均衡设置的规则定义,如图:
simple:字段定义了如下几种可选的负载均衡算法:
- ROUND_ROBIN:轮询算法,默认采用这种算法。
- LEAST_CONN:最少连接算法,算法实现是从两个随即选择的服务后端选择一个活动请求数较少的后端实例。
- RANDOM:从可用的健康实例中随即选择一个。
- PASSTHROUGHT:(pass through),直接转发连接到客户端连接的目标地址,即没有做负载均衡。
如下配置,给一个服务设置随机的负载均衡策略:
trafficPolicy: |
consistentHash字段:一致性哈希是一种高级的负载均衡策略,只对HTTP有效,因为在实现上基于HTTP Header、Cookie的取值来进行哈希。负载均衡器会把哈希一致的请求转发到相同的后端实例上,从而实现一定的会话保持,通过下面的字段描述一致性哈希:
- httpHeaderName:计算哈希的header。
- httpCookie:计算哈希的Cookie。
- useSourceIp:基于源IP计算哈希值。
- minimumRingSize:哈希环上虚拟节点数的最小值,节点数越多则负责均衡越精细。如果后端实例数小于哈希环上的虚拟节点数,则每个后端实例都会有一个虚拟节点。
通过配置cookie:location上进行一致性哈希的会话保持:
trafficPolicy: |
Istio的数据面Envoy其实提供了更多的负载均衡算法的支持,Istio当前只支持以上几种。
连接池设置 ConnectionPoolSettings DestinationRule.trafficPolicy.connectionPool
通过连接池管理可以配置阀值来防止一个服务的失败级联影响到整个应用,如下图是对Istio连接池设置的规则定义,连接池管理在协议上分为TCP流量和TTP流量治理:
TCP连接池配置 TCPSettings DestinationRule.trafficPolicy.connectionPool.tcp.
可以配置三个属性:
- maxConnection:表示为上游服务的所有实力建立的最大连接数,默认是1024,属于TCP层的配置,对于HTTP,只用于HTTP/1.1,因为HTTP/2对每个主机都是用单个连接。
- connectTimeout:TCP连接超时,表示主机网络连接超时,可以改善因调用服务变慢导致整个链路变慢的情况。
- tcpKeepalive:设置TCP keepalives,定期给对端发送一个keepalive的探测包,判断连接是否可用。这种0长度的数据包对用户的程序没有影响。包括三个字段:
- probes:表示有多少次探测没有应答就可以断定连接断开,默认使用操作系统额配置,在linux系统中是9;
- time:表示在发送探测前连接空闲了多长时间,也默认使用操作系统配置,在linux中默认是两个小时;
- inverval:探测间隔,默认使用操作系统配置,在linux中是75秒。
如下示例,为forecast服务配置了TCP连接池,最大连接数是80,连接超时25ms,并且配置了TCP的Keepalive探测策略:
apiVersion: networking.istio.io/v1alpha3 |
HTTP连接池配置 TCPSettings DestinationRule.trafficPolicy.connectionPool.http.
对于七层协议,可以通过对应的HTTPSettings对连接池进行更细致的配置:
- HTTP1MaxPendingRequests:最大等待HTTP请求数,默认值是1024,只适用于HTTP/1.1的服务,因为HTTP/2协议的请求在到来时会立即复用连接,不会在连接池等待。
- http2MaxRequests:最大请求数,默认是1024,只适用于HTTP/2服务,因为HTTP/1.1使用最大连接数maxConnections即可,表示上游服务的所有实力处理的最大请求数。
- maxRequestsPerConnection:每个连接的最大请求数。HTTP/1.1和HTTP/2连接池都遵循次参数。如果没有设置,则没有限制。设置为1时表示每个连接只处理一个请求,也就是禁用了Keepalive。
- maxRetries:最大重试次数,默认是3,表示服务可以执行的最大重试次数。如果调用端因为偶尔抖动导致请求直接失败,则可能会带来业务损失,一般建议配置重试,若重试成功则可正常返回数据,只不过比原来响应的慢一点,点重试次数太多会影响性能,要谨慎使用。不是重试那些重试了也总还是失败的请求;不要对那些消耗大的服务进行重试,特别是那些不会被取消的服务。
- idleTimeout:空闲超时,定义在多长时间内没有活动请求则关闭连接。
HTTP连接池配置一般和对应的TCP设置配合使用,如下:为forecast服务配置了最大80个连接,只允许最多有800个并发请求,每个连接的请求数不超过10个,连接超时是20ms:
apiVersion: networking.istio.io/v1alpha3 |
Istio连接池总结
tcp和http两者的属性划分维度不一样:
在Istio中根据协议划分为TCP和HTTP;在Envoy中根据属性的业务划分为不同的分组,一部分属于circuit_breakers分组,另一部分属于cluster分组。另外,Istio在属性名上区分表示了HTTP/1.1和HTTP/2的配置:
如下图所示的HTTP/1.1和HTTP/2在语义上的差别,在控制最大请求数时,对HTTP/1.1使用maxConnections参数配置,对HTTP/2则使用http2MacRequest参数配置:
异常实例检测设置 OutlierDetection DestinationRule.trafficPolicy.outlierDetection.
异常点检查就是定期考察被访问的服务实例的工作情况,如果持续出现访问异常,则将服务实例标记为异常并进行隔离,在一段时间内不为其分配流量。过一段时间后,被隔离的服务实例会再次被解除隔离,尝试处理请求,若还不正常,则被隔离更长的时间,在模型上Istio的异常点检查符合一般意义的熔断模型。
在Istio中,其实可以将异常点检查理解为健康检查,但是与传统的健康检查不同:在传统的健康检查中,都是定期探测目标服务实例,根据应答来判断服务实例的健康状态,例如Kubernetes上的Readniess或者一般负载均衡器上的健康检查等。这里的健康检查是指通过对实际的访问情况进行统计来找出不健康的实例,所以被被动型的健康检查,负载均衡器的健康检查是主动型的健康检查。
可以通过下列参数配置检查驱逐的逻辑:
- consecutiveErrors:实例被驱逐前的连续错误次数,默认是5次。对于HTTP服务,返回502/503和504的请求会被认为异常;对于TCP服务,连接超时或者换连续错误事件会被认为异常。
- interval:驱逐的时间间隔,默认是10秒,要求大于1毫秒,单位可以是h/m/s/ms
- baseEjectionTime:最小驱逐时间。一个实例被驱逐的时间等于这个最小驱逐时间乘以驱逐的次数。这样一个因多次异常被驱逐的实例,被驱逐的时间会越来越长。默认是30s,要求大于1毫秒,单位可以是h/m/ms。
- maxEjectionPercent:值负载均衡池中可以被驱逐的故障实例的最大比例,默认是10%,设置这个值是为了避免太多的服务实例被驱逐导致服务整体能力下降。
- minHealthPercent:最小健康实例比例。当负载均衡池中的健康实例数的比例大于这个比利时,异常点检查机制可用;当可用实例数的比例小于这个比利时,异常点检查公能被禁用,所有服务实例不管被认为健康还是不健康,都可以接收请求。参数的默认值是50%。
如下所示为检查4分钟内forecast服务实例的访问异常情况,连续出现5次访问异常的实例被隔离10分钟,被隔离的实例数不超过30%,在第一次隔离期满后,异常实例将重新接收流量,如果仍然不能正常工作,则会被重新隔离,第二次隔离20分钟,以此类推:
apiVersion: networking.istio.io/v1alpha3 |
端口流量策略设置 PortTrafficPolicy DestinationRule.trafficePolicy.portLevelSettings.
端口流量策略是将前面讲到的4中流量策略应用到每个服务端口上。如下图,是端口流量策略的规则定义,可以发现总体和前面的TrafficPolicy没有很大的差别,一个关键的差别字段就是port,表示流量策略要应用的服务端口,关于PortTrafficPolicy,只要了解在端口上定义的流量策略会覆盖全局的流量策略即可:
如下,为forecast服务配置了最大连接数80,但是为端口3002单独配置了最大连接数100:
apiVersion: networking.istio.io/v1alpha3 |
服务子集 subset DestinationRule.subsets.
服务子集Subset,包含若干后端服务实例。例如,通过Subset定义了一个版本,在VirtualService上可以给版本配置流量规则,将满足条件的流量路由到这个Subset的后端实例上。要在VirtualService中完成这种流量规则,就必须先通过DestinationRule对Subset进行定义。
Subset包含以下三个重要属性:
- name:Subset的名字,必须字段。通过VirtualService引用的就是这个名字。
- labels:Subset上的标签,通过一组标签定义了属于这个Subset的服务实例,比如最常用的标识服务版本的Version标签。
- TrafficPolicy:应用到这个Subset上的流量策略。前面将的若干中流量策略都可以在Subset上定义并作用到这些服务实例上。
如下,给一个特定的Subset配置最大连接数:
apiVersion: networking.istio.io/v1alpha3 |
将上面的例子稍微修改一下:给forecast服务全局配置100的最大连接数,给它的一个子集v2配置80的最大连接数。那么,forecast服务在v2版本的子集的最大连接数是多少呢?有了前面 PortTrafficPolicy 的覆盖原则,不难理解,根据本地覆盖全局的原则,v2版本的Subset上的配置生效:
apiVersion: networking.istio.io/v1alpha3 |
当然,这里只定义了流量策略,只有真正定义了流量规则且有流量到这个Subset上,流量策略才会生效。比如在上面这个示例中,如果在VirtualService中并没有给v2版本定义流量规则,则在DestinationRule上给v2版本配置的最大连接数80不会生效,起作用的仍然是在forecast服务上配置的最大连接数100。
DestinationRule的典型应用
定义Subset
使用DestinationRule定义Subset是比较常见的用法,如下,为forecast服务定义了两个Subset:
apiVersion: networking.istio.io/v1alpha3 |
如下图,通过DestinationRule定义Subset,就可以配合VirtualService给每个Subset配置路由规则,可以将流量路由到不同的Subset实例上,这个过程对服务访问方透明,服务访问放仍然通过域名进行访问。
服务熔断
在使用中一般根据场景将异常点检查和连接池管理配合使用,如下,为forecast服务配置了一个完整的熔断保护:
apiVersion: networking.istio.io/v1alpha3 |
解释:
假设 forecast 服务有 10 个实例,则以上配置的效果是:为 forecast 服务配置最大 80个连接,最大请求数为800,每个连接的请求数都不超过10个,连接超时是25毫秒;另外,在4分钟内若有某个forecast服务实例连续出现5次访问异常,比如返回5xx错误,则该forecast服务实例将被隔离10分钟,被隔离的实例总数不超过3个。在第1次隔离期满后,异常的实例将重新接收流量,如果实例工作仍不正常,则被重新隔离,第2次将被隔离20分钟,以此类推。
负载均衡配置
我们可以为服务及其某个端口或者某个Subset配置负载均衡策略。如下所示为给forecast服务的两个版本Subset v1和v2分别配置RANDOM和ROUND_ROBIN的负载均衡策略:
apiVersion: networking.istio.io/v1alpha3 |
效果如下图,这个策略通过Pilot下发到各个Envoy,frontend服务的Envoy在代理访问forecast服务时对不同的版本执行不同的负载均衡策略:v1版本随即选择实例发起访问,v2版本通过轮询的方式选择实例发起访问。
TLS认证配置
可以通过DestinationRule为一个服务的调用启用双向认证,当然,前提是服务本身已经通过Config开启了对应的认证方式。以下配置可以使对于forecast服务的访问使用双向TLS,只需要将模式配置为ISTIO_MUTUAL,Istio便可自动进行密钥证书的管理:
apiVersion: networking.istio.io/v1alpha3 |
frontend服务对forecast服务的访问会自动启用双向认证,对forecast服务和frontend服务的代码都无须修改,而且对双方的证书密钥也无须维护。
DestinationRule 思维导图
图片右键在新窗口打开,或者复制图片路径,可以查看原图。
点击这里,查看思维导图网页版,可以查看字段的解释说明,可以保存该网页到本地。
Istio服务网关配置:Gateway
Gateway在网格边缘接收外部访问,并将流量转发到网格内的服务。Istio通过Gateway将网格内的服务发布成外部可访问的服务,还可以通过Gateway配置外部访问的端口、协议及与内部服务的映射关系。
Gateway规范描述了负载均衡器的L4-L6属性。然后,可以将VirtualService绑定到网关,以控制到达特定主机或网关端口的流量的转发。
Gateway配置示例
示例:通过HTTP的80端口访问网格内的服务:
apiVersion: networking.istio.io/v1alpha3 |
配合Gateway的使用,VirtualService要做适当修改,在hosts上匹配Gateway上请求的主机名,并通过gateways字段关联定义的Gateway对象。
apiVersion: networking.istio.io/v1alpha3 |
Gateway规则定义
Gateway一般和VirtualService配合使用。Gateway定义了服务从外面怎样访问;VirtualService定义了匹配到的内部服务怎么流转。正式有了Gateway的存在,才能在入口处对服务进行统一管理。
Gateway只是描述服务的外部访问,而服务的内部路由都在VirtualService中定义,从而解耦服务的外部入口和服务的内部路由。在一个VirtualService上定义的路由既可以对接Gateway应用到外部访问,也可以作为内部路由规则应用到网格内的服务间调用。
Gateway的规则定义,如下图,主要定义了一组开放的服务列表。
在Gateway上定义了如下两个关键字段:
- selector:必选字段,表示Gateway负载,为入口处的Envoy运行的Pod的标签,通过这个标签来找到执行Gateway规则的Envoy。标签的选择范围被限定到Gateway配置所在的命名空间,换句话说,Gateway的规则定义和Gateway的Envoy负载必须在同一个命名空间下。
- servers:必选字段,表示开放的服务列表,是Gateway的关键内容信息,是一个数组,每个元素都是Server类型。
后端服务Server Gateway.servers.
Server在结构上真正定义了服务的访问入口,可通过port、hosts、defaultEndpoint和tls来描述。
port:必选字段,描述服务在哪个端口对外开放,是对外监听的端口。
- number:端口号
- protocol:协议,MUST BE one of HTTP|HTTPS|GRPC|HTTP2|MONGO|TCP|TLS
- name:名称
hosts:必选字段,为Gateway发布的服务地址,通常适用于HTTP、HTTPS服务,同样适用于使用了SNI的TLS的TCP服务。是一个FQDN域名,可以支持左侧通配符来进行模糊匹配。另外,Istio 1.1支持在这个字段中加入命名空间条件来匹配特定命名空间下的VirtualService(格式:namespace/host)。如果设置了命名空间,则会匹配该命名空间下的VirtualService,如果未包含命名空间,则会尝试匹配所有的命名空间。namespace可以是“.”或者“*”,分别表示当前命名空间和所有命名空间。
注意:在Istio 1.1的Gateway中支持在hosts匹配时使用命名空间的过滤条件。
绑定到一个Gateway上的VirtualService必须匹配这里的hosts条件,支持精确匹配和模糊匹配。以Gateway配置示例 为例,假设通过VirtualService上的gateways字段已经建立了绑定,则实例中的Gateway在istio-system下,VirtualService在weather下,通过下表查看Gateway和VirtualService Hosts的匹配实例来理解规则。
在Gateway和VirtualService关联时,需要在VirtualService中增加exportTo字段,只有对应的VirtualService的exportTo包含Gateway的命名空间,对应的关联才会生效。
- defaultEndpoint:表示流量转发的默认后端,可以是一个lookback的后端,也可以是UNIX的域套接字。
- tls:在实际使用中考虑安全问题,在入口处都通过HTTPS的安全协议访问,需要一些额外的信息来描述,在Gateway上Server专门有个TLSOptions类型的字段tls来描述这部分定义。
我们一般基于port和hosts字段来发布一个内部服务供外面访问,如下所示发布一个HTTP的服务:
servers: |
TLS选项 TLSOptions Gateway.servers.tls
tls是与安全服务接口相关,属性如下:
- httpsRedirect:是否要做HTTP重定向,在这个布尔属性启用时,负载均衡器会给所有HTTP连接都发送一个301的重定向,要求使用HTTPS。
- mode:在配置的外部端口上使用TLS模式时,可以取PASSTHROUGH、SIMPLE、MUTUAL、AUTO_PASSTHROUGH、ISTIO_MUTUAL这5中模式。
- serverCertificate:服务端证书路径,当模式是SIMPLE和MUTUAL时必须指定,配置得单向和双向认证场景下用到的服务端证书。
- privateKey:服务端密钥的路径。当模式是SIMPLE和MUTUAL时必须指定,配置得单向和双向认证场景下用到的服务端私钥。
- caCertificate:CA证书路径。档模式是MUTUAL时指定,在双向认证场景下配置在Gateway上验证客户端的证书。
- credentialName:用于唯一标示服务端证书和密钥,Gateway使用credentialName从远端的凭据存储(如Kubernetes的Secrets)中获取证书和密钥,而不是使用Mount的文件。
- subjectAltNames:SAN列表。SubjectAltNames允许一个证书指定多个域名,在Gateway上可以用来验证客户端提供的证书中的主题标识。
- minProtocolVersion:TLS协议的最小版本。
- maxProtocolVersion:TLS协议的最大版本。
- cipherSuites:指定的加密套件,默认使用Envoy支持的加密套件。
Gateway字段属性,官网摘录
参考:https://istio.io/docs/reference/config/networking/gateway
一级字段:Gateway.
Gateway describes a load balancer operating at the edge of the mesh receiving incoming or outgoing HTTP/TCP connections.
Field | Type | Description | Required |
---|---|---|---|
servers |
Server[] |
A list of server specifications. | Yes |
selector |
map |
One or more labels that indicate a specific set of pods/VMs on which this gateway configuration should be applied. The scope of label search is restricted to the configuration namespace in which the the resource is present. In other words, the Gateway resource must reside in the same namespace as the gateway workload instance. | Yes |
Gateway.servers.
Server
describes the properties of the proxy on a given load balancer port.
Field | Type | Description | Required |
---|---|---|---|
port |
Port |
The Port on which the proxy should listen for incoming connections. | Yes |
hosts |
string[] |
One or more hosts exposed by this gateway. While typically applicable to HTTP services, it can also be used for TCP services using TLS with SNI. A host is specified as a dnsName with an optional namespace/ prefix. The dnsName should be specified using FQDN format, optionally including a wildcard character in the left-most component (e.g., prod/*.example.com ). Set the dnsName to * to select all VirtualService hosts from the specified namespace (e.g.,prod/* ).The namespace can be set to * or . , representing any or the current namespace, respectively. For example, */foo.example.com selects the service from any available namespace while ./foo.example.com only selects the service from the namespace of the sidecar. The default, if no namespace/ is specified, is */ , that is, select services from any namespace. Any associated DestinationRule in the selected namespace will also be used.A VirtualService must be bound to the gateway and must have one or more hosts that match the hosts specified in a server. The match could be an exact match or a suffix match with the server’s hosts. For example, if the server’s hosts specifies *.example.com , a VirtualService with hosts dev.example.com or prod.example.com will match. However, a VirtualService with host example.com or newexample.com will not match.NOTE: Only virtual services exported to the gateway’s namespace (e.g., exportTo value of * ) can be referenced. Private configurations (e.g., exportTo set to . ) will not be available. Refer to the exportTo setting in VirtualService , DestinationRule , and ServiceEntry configurations for details. |
Yes |
tls |
TLSOptions |
Set of TLS related options that govern the server’s behavior. Use these options to control if all http requests should be redirected to https, and the TLS modes to use. | No |
defaultEndpoint |
string |
The loopback IP endpoint or Unix domain socket to which traffic should be forwarded to by default. Format should be 127.0.0.1:PORT or unix:///path/to/socket or unix://@foobar (Linux abstract namespace). |
No |
Gateway.servers.port.
Port describes the properties of a specific port of a service.
Field | Type | Description | Required |
---|---|---|---|
number |
uint32 |
A valid non-negative integer port number. | Yes |
protocol |
string |
The protocol exposed on the port. MUST BE one of HTTP|HTTPS|GRPC|HTTP2|MONGO|TCP|TLS. TLS implies the connection will be routed based on the SNI header to the destination without terminating the TLS connection. | Yes |
name |
string |
Label assigned to the port. | No |
Gateway.servers.tls.
Field | Type | Description | Required |
---|---|---|---|
httpsRedirect |
bool |
If set to true, the load balancer will send a 301 redirect for all http connections, asking the clients to use HTTPS. | No |
mode |
TLSmode |
Optional: Indicates whether connections to this port should be secured using TLS. The value of this field determines how TLS is enforced. | No |
serverCertificate |
string |
REQUIRED if mode is SIMPLE or MUTUAL . The path to the file holding the server-side TLS certificate to use. |
No |
privateKey |
string |
REQUIRED if mode is SIMPLE or MUTUAL . The path to the file holding the server’s private key. |
No |
caCertificates |
string |
REQUIRED if mode is MUTUAL . The path to a file containing certificate authority certificates to use in verifying a presented client side certificate. |
No |
credentialName |
string |
The credentialName stands for a unique identifier that can be used to identify the serverCertificate and the privateKey. The credentialName appended with suffix “-cacert” is used to identify the CaCertificates associated with this server. Gateway workloads capable of fetching credentials from a remote credential store such as Kubernetes secrets, will be configured to retrieve the serverCertificate and the privateKey using credentialName, instead of using the file system paths specified above. If using mutual TLS, gateway workload instances will retrieve the CaCertificates using credentialName-cacert. The semantics of the name are platform dependent. In Kubernetes, the default Istio supplied credential server expects the credentialName to match the name of the Kubernetes secret that holds the server certificate, the private key, and the CA certificate (if using mutual TLS). Set the ISTIO_META_USER_SDS metadata variable in the gateway’s proxy to enable the dynamic credential fetching feature. |
No |
subjectAltNames |
string[] |
A list of alternate names to verify the subject identity in the certificate presented by the client. | No |
verifyCertificateSpki |
string[] |
An optional list of base64-encoded SHA-256 hashes of the SKPIs of authorized client certificates. Note: When both verifycertificatehash and verifycertificatespki are specified, a hash matching either value will result in the certificate being accepted. | No |
verifyCertificateHash |
string[] |
An optional list of hex-encoded SHA-256 hashes of the authorized client certificates. Both simple and colon separated formats are acceptable. Note: When both verifycertificatehash and verifycertificatespki are specified, a hash matching either value will result in the certificate being accepted. | No |
minProtocolVersion |
TLSProtocol |
Optional: Minimum TLS protocol version. | No |
maxProtocolVersion |
TLSProtocol |
Optional: Maximum TLS protocol version. | No |
cipherSuites |
string[] |
Optional: If specified, only support the specified cipher list. Otherwise default to the default cipher list supported by Envoy. | No |
Gateway.servers.tls.mode.
TLS modes enforced by the proxy
Name | Description |
---|---|
PASSTHROUGH |
The SNI string presented by the client will be used as the match criterion in a VirtualService TLS route to determine the destination service from the service registry. |
SIMPLE |
Secure connections with standard TLS semantics. |
MUTUAL |
Secure connections to the downstream using mutual TLS by presenting server certificates for authentication. |
AUTO_PASSTHROUGH |
Similar to the passthrough mode, except servers with this TLS mode do not require an associated VirtualService to map from the SNI value to service in the registry. The destination details such as the service/subset/port are encoded in the SNI value. The proxy will forward to the upstream (Envoy) cluster (a group of endpoints) specified by the SNI value. This server is typically used to provide connectivity between services in disparate L3 networks that otherwise do not have direct connectivity between their respective endpoints. Use of this mode assumes that both the source and the destination are using Istio mTLS to secure traffic. |
ISTIO_MUTUAL |
Secure connections from the downstream using mutual TLS by presenting server certificates for authentication. Compared to Mutual mode, this mode uses certificates, representing gateway workload identity, generated automatically by Istio for mTLS authentication. When this mode is used, all other fields in TLSOptions should be empty. |
Gateway.servers.tls.minProtocolVersion or Gateway.servers.tls.maxProtocolVersion
TLS protocol versions.
Name | Description |
---|---|
TLS_AUTO |
Automatically choose the optimal TLS version. |
TLSV1_0 |
TLS version 1.0 |
TLSV1_1 |
TLS version 1.1 |
TLSV1_2 |
TLS version 1.2 |
TLSV1_3 |
TLS version 1.3 |
Gateway的典型应用
将网格内的HTTP服务发布为HTTP外部服务
在上面的配置:Gateway配置示例 介绍了将一个内部的HTTP服务通过Gateway发布出去的典型场景,如下图所示,外部服务通过域名http://weather.com
访问到应用的入口服务frontend。VirtualService本身定义了frontend服务从内部和外部访问同样的路由规则,即根据内容的不同,将请求路由到v2版本或v1版本,这里的Gateway的协议是HTTP。
将网格内的HTTPS服务发布为HTTPS外部服务
将网格内的HTTPS服务通过HTTPS协议发布。这样在浏览器端中输入https://weather.com
就可以访问到这个服务。
此时,重点是:端口为443,协议为HTTPS,TLS模式为PASSTHROUGH,表示Gateway只透传应用程序提供的HTTPS内容,frontend入口服务自身是HTTPS类型的服务,TLS需要的服务端证书、密钥等都是frontend服务子集维护的。这时需要对frontend服务做路由管理,在VirtualService中需要配置支持TLSRoute规则,如果没有配置,则流量会被当做TCP处理:
apiVersion: networking.istio.io/v1alpha3 |
这时,Istio只是通过Gateway将一个内部的HTTPS服务发布出去。Istio提供了通道机制,HTTPS的证书及网格外部HTTPS客户端如何访问frontend服务都是frontend服务自己的事情。这里的HTTPS是应用程序的HTTPS,不是Istio的Gateway提供的HTTPS。对于自身的服务已经是HTTPS的应用,Istio支持通过这种方式把服务发布成外部可访问,单更推荐的是下面的做法,即将网格内的一个HTTP的服务通过Gateway发布为HTTPS外部访问。
将网格内的HTTP服务发布为HTTPS外部服务
此时,要求网格外部通过HTTPS访问入口服务,差别为服务自身是HTTP,在发布的时候通过Gateway的配置可以提供HTTPS的对外访问能力,如下图,外部通过HTTPS访问,入口服务frontend是HTTP服务:
这时Gateway配置如下,端口为4443,协议为HTTPS。这里的TLS模式时SIMPLE,表示Gateway提供标准的单向TLS认证。这时需要通过serverCertificate和privateKey提供服务端证书密钥。如上图,TLS认证的服务端是在入口的Envoy上创建的,入口服务frontend本身保持原有的HTTP方式:
apiVersion: networking.istio.io/v1alpha3 |
这种方式又被称为终结的HTTPS,在Gateway外面是HTTPS,但从Gateway往里的服务访问还是HTTP。入口处作为Gateway的Envoy,一方面作为服务提供者的入口代理,将frontend服务以HTTPS安全协议发布出去;另一方面作为服务消费者的代理,以HTTP向frontend服务发起请求。正因为有了后面这种能力,对于frontend服务上的路由仍然可以使用HTTP的路由规则。
这种方式既可以提供第1种HTTP发布同样的灵活性,又可以满足第2种场景要求的入口安全访问。在Gateway服务发布时提供了安全的能力,对服务自身的代码、部署及网格内部的路由规则的兼容都没有影响,因此是推荐的一种做法。
将网格内的HTTP服务发布为双向HTTPS外部访问
在某些场景下,比如调用入口服务的是另一个服务,在服务端需要对客户端进行身份校验,这就需要用到TLS的双向认证。
这种方式的主要流程和第3种场景单向认证类似,都是在入口处Gateway角色的Envoy上开放 HTTPS服务,外部 HTTPS请求在 Gateway处终止,内部 VirtualService的路由配置仍然是HTTP。
在如下配置方式中,可以看到,双向认证和单向认证的差别在于,Gateway上的模式被设定为MUTUAL 时表示双向认证,同时,为了支持双向认证,除了要配置通过serverCertificate和privateKey提供服务端证书密钥,还需要提供caCertificates来验证客户端的证书,从而实现和调用方的双向认证:
apiVersion: networking.istio.io/v1alpha3 |
将网格内的HTTP服务发布为HTTPS外部访问和HTTPS内部访问
有一种方式可以将一个HTTP服务通过Gateway发布为HTTPS外部访问,同时在网格内也是HTTPS的双向认证。如下图,不用修改代码,HTTP服务在网格内核网格外都是HTTPS安全方式互访。
此时的Gateway的Manifest配置和场景3完全相同:将网格内的HTTP服务发布为HTTPS外部服务
Istio可以透明的给网格内的服务启用双向TLS,并且自动维护证书和密钥。入口Gateway和入口服务frontend在这种场景下的工作机制如下:
- frontend服务自身还是HTTP,不涉及证书密钥的事情。
- Gateway作为frontend服务的入口代理,对外提供HTTPS的访问。外部访问到的是在Gateway上发布的HTTPS服务,使用Gateway上的配置提供服务证书和密钥。
- Gateway作为外部服务访问frontend服务的客户端代理,对frontend服务发起另一个HTTPS请求,使用的是Citadel分发和维护的客户端证书和密钥,与frontend服务的服务端证书和密钥进行双向TLS认证和通信。
注意:入口服务通过Gateway发布成HTTPS,结合Istio提供的透明双向TLS,在入口的Envoy上是两套证书密钥,一套是Gateway对外发布HTTPS服务使用的,另一套是Istio提供的网格内双向TLS认证,两者没有任何关系。
以上发布方式的对比:
在Gateway上一般都是发布多个服务,配置如下:
apiVersion: networking.istio.io/v1alpha3 |
Gateway 思维导图
图片右键在新窗口打开,或者复制图片路径,可以查看原图。
点击这里,查看思维导图网页版,可以查看字段的解释说明,可以保存该网页到本地。
Istio外部服务配置:ServiceEntry
将网格外的服务加入到网格中,通过ServiceEntry方式,就像网格内的服务一样进行管理。在实际上就是把外部服务加入Istio的服务发现,这些外部服务因为各种原因不能直接注册到网格中。
ServiceEntry配置示例
通过ServiceEntry包装了一个对www.weatherdb.com外部服务的访问。在网格内是一个完整应用,对外提供weather服务,单某些数据来自另一个开放数据服务www.weatherdb.com,通过如下配置就可以对开放数据服务的访问进行治理:
apiVersion: networking.istio.io/v1alpha3 |
ServiceEntry规则的定义和用法
如下图,可以配置外部服务的DNS域名、vip、端口、协议和后端地址等。
ServiceEntry字段解释:
hosts:必选,表示与ServiceEntry相关的主机名,可以是一个DNS域名,还可以使用前缀模糊匹配,在使用上说明如下:
- HTTP的流量,这个字段匹配HTTP Header的Host或Authority
- HTTPS或TLS流量,这个字段匹配SNI。
- 其他协议的流量,这个字段不生效,使用下面的address和port字段
- 当resolution被设置为DNS类型并且没有指定Endpoints时,这个字段将用作后端的域名来进行路由。
address:表示与服务管理的虚拟IP地址,可以是CIDR这种前缀表达式,对于hTTP的流量,该字段被忽略,而是使用Header中的Host或Authority。如果address为空,则只能根据目标端口来识别,这这种情况下这个端口不能被网格里的其他服务使用。即Sidecar只作为一个TCP代理,把某个 特定端口的流量转发到配置的目标后端。
ports:表示与外部服务关联的端口,必须按字段。
location:用于设置服务是在网格内部还是网格外部。可以取以下两种模式:
MESH_EXTERNAL:表示在网格外部,通过API访问的外部服务。
MESH_INTERNAL:表示在网格内部,一些不能直接注册到网格服务注册中心的服务,例如一些虚拟机上的服务不能通过Kubernetes机制自动在Istio中进行服务注册,通过这种方式可以扩展网格管理的服务。
location 字段会影响 mTLS 双向认证、策略执行等特性。当和网格外部服务通信时,mTLS双向认证将被禁用,并且策略只能在客户端执行,不能在服务端执行。因为对于外部服务,远端不可能注入一个Sidecar来进行双向认证等操作。
resolution:是一个内容觉多的必须字段,表示服务发现的模式,用来设置代理解析服务的方式,将一个服务名解析到一个后端的IP地址上,可以设置NONE、STATIC、DNS三种模式。另外这里配置的解析模式不影响应用的服务名解析,应用仍然使用DNS将服务解析到IP上,这样Outbound流量会被Envoy拦截:
- NONE:用于当连接的目标地址已经是一个明确IP的场景。当访问外部服务且应用要被解析到一个特定的IP上时,要将模式设为NONE。
- STATIC:用在已经用endpoints设置了服务实例的地址场景中,即不用解析。
- DNS:表示用查询环境中的DNS进行解析。如果没有设置endpoints,代理就会使用在hosts中指定的NDS名称进行解析,前提是在hosts中未使用通配符;如果设置了endpoints,则使用endpoints中的DNS地址解析出目标IP。在上面的例子中使用hosts的值
www.weatherdb.com
进行解析。
subjectAltNAmes:表示这个服务负载的SAN列表,在Istio安全相关配置的多个地方被用到,被设置时,代理将验证服务证书的SAN是否匹配。
endpoints:表示与网格服务关联的网格地址,可以是一个IP,也可以是一个主机名。这个字段是endpoints的复杂结构:
- address:必选字段,表示网格后端的地址。当resolution被设置为DNS时,address可以使用域名,但要请示明确的地址,不可以使用模糊匹配。
- ports:端口列表。
- labels:后端的标签。
- network:主要用在Istio多集群中,所有属于相同network的后端都可以直接相互访问,不再同一个network的后端不能直接访问。在使用Istio Gateway时可以对不同network的后端建立连接。
- locality:后端的locality,主要用于亲和性路由,即Envoy可以基于这个表示做本地化路由,优先路由到本地的后端上。locality表示一个故障域,常见的如国家、地区、区域也可以分割每个故障域来表示任意层次的结构。
- weight:表示负载均衡的权重,权重越高,接收的流量占比越大。
exporTo:用于控制ServiceEntry跨命名空间的可见性,这样就可以控制在一个命名空间下定义的资源对象是否可以被其他命名空间下的Sidecar、Gateway和VirtualService使用。如果未赋值,则默认全局可见。“.”表示仅应用到当前命名空间,“*”表示应用到所有命名空间,在Istio 1.1中只支持“.”和“*”这两种配置。
ServiceEntry的典型应用
配置访问外部服务是ServiceEntry的典型应用,如上面定义:ServiceEntry配置示例 这样可以向网格内的服务一样进行治理。如下图,forecast服务对www.weatherdb.com
的访问被本地的Sidecar拦截,从而对访问进行治理。
有时对外部服务的访问必须经过一个对外的Egress代理的场景,因为只有这个节点有对外的IP或者这个节点是统一的安全出口等,访问会如下图所示:
这时需要创建一个Egress Gateway,创建对外部服务www.weatherdb.com
的访问:
apiVersion: networking.istio.io/v1alphs3 |
然后通过VirtualService定义流量规则:
apiVersion: networking.istio.io/v1alpha3 |
解释:
- 网格内流量:这个Route的gateways是
mesh
关键字,表示来自网格内的流量。这种流量在访问www.weatherdb.com
这个外部地址时将被转发到Egress Gateway上。 - 网格对外流量:这个Route匹配的gateways字段是Egress,表示匹配来自Egress的流量,这种流量将被路由到外部服务
www.weatherdb.com
上。
Istio代理规则配置:Sidecar
Sidecar这个资源对象用于对Istio数据面的行为进行更精细的控制。
Sidecar配置示例
如下配置了一组基于命名空间描述的Egress,定义了weather这个命名空间下的Sidecar只可以访问istio-system和news两个命名空间下的服务:
apiVersion: networking.istio.io/v1alpha3 |
Sidecar规则定义
在Istio里Envoy正式先拦截到工作负载的Inbound流量和Outbound流量,才能执行服务间访问的治理,Sidecar资源对象可以更精细的控制Envoy转发和接收的端口、协议等,并可以限制Sidecar Outbound流量允许到达的目标服务集合,如下图所示是Sidecar的规则定义:
字段说明:
workloadSelector:表示工作负载的选择器。Sidecar的配置可以使用workloadSelector应用到命名空间下的一个或者多个负载,如果未配置workloadSelector,则应用到整个命名空间。每个命名空间都只能定义一个没有workloadSelector的Sidecar,表示对命名空间的全局配置。如下所示为在weather这个命名空间下app标签匹配forecast服务的工作负载标签:
apiVersion: networking.istio.io/v1alpha3
kind: Sidecar
metadata:
name: weather-forecast
namespace: weather
spec:
workloadSelector:
labels:
app: forecast
...egress:是一种IstioEgressListener类型,可用来配置Sidecar对网格内其他服务的访问,如果没有配置,则只要命名空间可见,命名空间里的服务就可以被访问。通过如下几个字段来描述规则:
- port:监听器关联的端口,被设定后会作为主机的默认目标端口。
- bind:监听器绑定的地址。
- captureMode:配置如何捕获监听器的流量,可以有DEFAULT、IPTABLES、NONE三种模式。
- DEFAULT表示使用环境默认的捕获规则;
- IPTABLES指定基于iptables的流量拦截;
- NONE表示没有流量拦截。
- hosts:必选字段,表示监听器的服务,为“namespace/dnsName”格式。dnsName需要为FQDN格式,可以对namespace、DNSName使用通配符。
如下,对于istio-system命名空间下的所有Outbound流量,Sidecar都会进行转发;对于命名空间weather下的服务,Sidecar只转发目标端口是3002端口的流量:
apiVersion: networking.istio.io/v1alpha3 |
- ingress:IstioIngressListener类型,配置Sidecar对工作负载的Inbound流量,字段如下:
- port:必选字段,监听器管理的端口
- bind:监听器绑定的地址
- captureMode:配置如何捕获监听器的流量,该模式的取值同上面的IstioEgressListener上对应的字段。
- defaultEndpoint:必选字段,为流量转发的目标地址。
如下,为在命名空间weather下匹配forecast负载的Sidecar规则,允许其接受来自3002端口的HTTP流量,并将请求转到127.0.0.1:3012
上。这种方式用在自动拦截流量功能不可用,即未能初始化iptables规则时,通过Sidecar的这种配置可以将流量转发到本地负载的3012端口:
apiVersion: networking.istio.io/v1alpha3 |
总结
Istio的治理能力大部分是通过本文的流量规则来配置管理的。重点如下:
来自:云原生服务网格Istio:原理、实践、架构与源码解析书籍,本文只作为读书笔记记录,版权属于原作者。
本文到这里就结束了,欢迎期待后面的文章。您可以关注下方的公众号二维码,在第一时间查看新文章。