istio系列:第二章-流量路由转发配置详解
VirtualService
VirtualService定义了对特定目标服务的一组流量规则。如其名字所示,VirtualService在形式上表示一个虚拟服务,将满足条件的流量都转发到对应的服务后端,这个服务后端可以是一个服务,也可以是在DestinationRule中定义的服务的子集。
下面是VirtualService.yaml对应的结构体
type VirtualService struct {
Hosts []string `protobuf:"bytes,1,rep,name=hosts,proto3" json:"hosts,omitempty"`
Gateways []string `protobuf:"bytes,2,rep,name=gateways,proto3" json:"gateways,omitempty"`
Http []*HTTPRoute `protobuf:"bytes,3,rep,name=http,proto3" json:"http,omitempty"`
Tls []*TLSRoute `protobuf:"bytes,5,rep,name=tls,proto3" json:"tls,omitempty"`
Tcp []*TCPRoute `protobuf:"bytes,4,rep,name=tcp,proto3" json:"tcp,omitempty"`
ExportTo []string `protobuf:"bytes,6,rep,name=export_to,json=exportTo,proto3" json:"export_to,omitempty"`
}
接下来让我们细细讲解每个属性的作用
Hosts
标明目的地址,可以是IP、DNS也可以是短域名、服务名(仅用于k8s) 例如reviews(短域名)、reviews.default.svc.cluster.local。对于短域名来说,VirtualService会自动添加后面的服务信息,比如添加命名空间。
注意:VirtualService 的 hosts 的短域名填充到的完整域名时,补齐的 Namespace 是VirtualService的Namespace,而不是Service的Namespace。
Gateways
Gateways表示应用这些流量规则的 Gateway。VirtualService 描述的规则可以作用到网格里的Sidecar 和入口处的 Gateway,表示将路由规则应用于网格内的访问还是网格外经过Gateway的访问。其使用方式有点绕,需要注意以下场景。
-
场景1:服务只是在网格内访问的,这是最主要的场景。gateways字段可以省略,实际上在VirtualService的定义中都不会出现这个字段。一切都很正常,定义的规则作用到网格内的Sidecar。
-
场景2:服务只是在网格外访问的。配置要关联的Gateway,表示对应Gateway进来的流量执行在这个VirtualService上定义的流量规则。
-
场景3:在服务网格内和网格外都需要访问。这里要给这个数组字段至少写两个元素,一个是外部访问的Gateway,另一个是保留关键字“mesh”。使用中的常见问题是忘了配置“mesh”这个常量而导致错误。我们很容易认为场景 3是场景 1和场景2的叠加,只需在内部访问的基础上添加一个可用于外部访问的Gateway。
Http
一个与 HTTPRoute 类似的路由集合,用于处理 HTTP 的流量,是 Istio中内容最丰富的一种流量规则。
type HTTPRoute struct {
Name string `protobuf:"bytes,17,opt,name=name,proto3" json:"name,omitempty"`
Match []*HTTPMatchRequest `protobuf:"bytes,1,rep,name=match,proto3" json:"match,omitempty"`
Route []*HTTPRouteDestination `protobuf:"bytes,2,rep,name=route,proto3" json:"route,omitempty"`
Redirect *HTTPRedirect `protobuf:"bytes,3,opt,name=redirect,proto3" json:"redirect,omitempty"`
Delegate *Delegate `protobuf:"bytes,20,opt,name=delegate,proto3" json:"delegate,omitempty"`
Rewrite *HTTPRewrite `protobuf:"bytes,4,opt,name=rewrite,proto3" json:"rewrite,omitempty"`
Timeout *duration.Duration `protobuf:"bytes,6,opt,name=timeout,proto3" json:"timeout,omitempty"`
Retries *HTTPRetry `protobuf:"bytes,7,opt,name=retries,proto3" json:"retries,omitempty"`
Fault *HTTPFaultInjection `protobuf:"bytes,8,opt,name=fault,proto3" json:"fault,omitempty"`
Mirror *Destination `protobuf:"bytes,9,opt,name=mirror,proto3" json:"mirror,omitempty"`
MirrorPercent *wrappers.UInt32Value `protobuf:"bytes,18,opt,name=mirror_percent,json=mirrorPercent,proto3" json:"mirror_percent,omitempty"`
MirrorPercentage *Percent `protobuf:"bytes,19,opt,name=mirror_percentage,json=mirrorPercentage,proto3" json:"mirror_percentage,omitempty"`
CorsPolicy *CorsPolicy `protobuf:"bytes,10,opt,name=cors_policy,json=corsPolicy,proto3" json:"cors_policy,omitempty"`
Headers *Headers `protobuf:"bytes,16,opt,name=headers,proto3" json:"headers,omitempty"`
}
下面让我们一一分析
Name
name 提供了当前规则的一个名称
Route
满足 HTTPMatchRequest 条件的流量都被路由到HTTPRouteDestination,执行重定向(HTTPRedirect)、重写(HTTPRewrite)、重试(HTTPRetry)、故障注入(HTTPFaultInjection)、跨站(CorsPolicy)策略等。
type HTTPRouteDestination struct {
// 目的地
Destination *Destination `protobuf:"bytes,1,opt,name=destination,proto3" json:"destination,omitempty"`
// 要转发到目的地的流量的相对比例。 目的地将收到“权重/(所有权重之和)”请求。多个Destination的权重和要求为100
Weight int32 `protobuf:"varint,2,opt,name=weight,proto3" json:"weight,omitempty"`
// 修改一次请求或响应header信息
Headers *Headers `protobuf:"bytes,7,opt,name=headers,proto3" json:"headers,omitempty"`
}
type Destination struct {
// DestinationRule名称
Host string `protobuf:"bytes,1,opt,name=host,proto3" json:"host,omitempty"`
// 服务中子集的名称。由DestinationRule定义
Subset string `protobuf:"bytes,2,opt,name=subset,proto3" json:"subset,omitempty"`
// 指定端口号
Port *PortSelector `protobuf:"bytes,3,opt,name=port,proto3" json:"port,omitempty"`
}
Match
匹配规则,为一个HTTPMatchRequest类型的数组,表示HTTP请求满足的条件,支持将HTTP属性如uri、scheme、method、authority、port 等作为条件来匹配请求。
type HTTPMatchRequest struct {
// 请求匹配的名称
Name string
// 下面4个字段都是StringMatch类型,
//在匹配请求时都支持exact、prefix和regex三种模式的匹配
//分别表示完全匹配输入的字符串,前缀方式匹配和正则表达式匹配
Uri *StringMatch
// For example, `http` or `https`.
Scheme *StringMatch
Method *StringMatch
Authority *StringMatch
// 对于header头的每个字段都可以用完全、前缀、正则来判断
Headers map[string]*StringMatch
// 请求的port 当服务都只开启一个port时不用指定
Port uint32
// 表示请求来源的负载匹配标签
// 在很多时候非常有用,可以对一组服务都打一个相同的标签
// 然后使用sourceLabels字段对这些服务实施相同的流量规则。
SourceLabels map[string]string
// 表示规则应用的Gateway名称
// 语义同VirtualService上面的gateways定义
// 是一个更细的Match条件,会覆盖在VirtualService上配置的gateways
Gateways []string
// 根据查询参数进行匹配
// 比如请求url中有?name=123
// 那么我们可以配置name为key值,exact = 123为value
QueryParams map[string]*StringMatch
// 指定匹配时是否忽略大小写
// 只有在 `exact` 和 `prefix` 的情况下才会有用
IgnoreUriCase bool
// 是上面headers取反的意思,不存在...
WithoutHeaders map[string]*StringMatch
// 资源命名空间
SourceNamespace string
}
注意:在HTTPRoute的匹配条件中,每个HTTPMatchRequest中的诸多属性都是“与”逻辑,几个元素间的关系是“或”逻辑
比如 下面的配置,在匹配时会根据请求的url判断前缀是否为www.lisi.com/aa或www.zhangsan.com/bb而url与header为与的关系。
MatchRequest:
- match:
- url:
prefix: "www.lisi.com/aa"
url:
prefix: "www.zhangsan.com/bb"
- header:
source:
exact: north
Redirect
请求req在重定向时对req头进行了改变。
type HTTPRedirect struct {
// 用该uri替换请求的uri
Uri string
// 替换请求的权限
Authority string
// 替换请求的端口
RedirectPort isHTTPRedirect_RedirectPort
// 替换请求的传输协议,比如http或https
Scheme string
// 替换重定向code,默认是301
RedirectCode uint32
}
Delegate
委托用于指定特定的VirtualService
只有当Route和Redirect为空时才可以设置并且路由委托 VirtualService 的规则
- 仅支持一级委托。
- 委托的 HTTPMatchRequest 必须是根的严格子集,否则会发生冲突,HTTPRoute 不会生效。
type Delegate struct {
Name string
Namespace string
}
Rewrite
重写 HTTP URI 和授权标头。 重写不能与重定向一起使用。 转发前会进行重写。
type HTTPRewrite struct {
Uri string
Authority string
}
URI会根据原本设置的匹配规则(前缀匹配等)更改前缀字符串,这是与重定向一个区别(重定向是重写整个url)
Timeout
HTTP 请求超时,默认禁用。
Retries
HTTP 请求的重试策略。
type HTTPRetry struct {
//运行重试的次数
Attempts int32
//每次尝试的超时时间
PerTryTimeout *duration.Duration
//重试发生的条件
// See the [retry policies](https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_filters/router_filter#x-envoy-retry-on)
// and [gRPC retry policies](https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_filters/router_filter#x-envoy-retry-grpc-on) for more details.
RetryOn string
//用于指定重试是否应在其他位置重试的标志
//(https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/http/http_connection_management#retry-plugin-configuration) for more details.
RetryRemoteLocalities *wrappers.BoolValue
}
CorsPolicy
跨域资源共享策略 (CORS)
Headers
修改一次请求或响应header信息
Tls
tls 是一种 TLSRoute 类型的路由集合,用于处理非终结的 TLS和HTTPS的流量,使用SNI(Server Name Indication,客户端在TLS握手阶段建立连接使用的服务Hostname)做路由选择
type TLSRoute struct {
// 匹配规则
Match []*TLSMatchAttributes
// 路由配置 前面已经讲解过用法
Route []*RouteDestination
}
type TLSMatchAttributes struct {
// SNI地址
SniHosts []string
// 关于子网配置 例如,a.b.c.d/xx
DestinationSubnets []string
// 端口绑定
Port uint32
// 资源标签
SourceLabels map[string]string
// Gateways名称
Gateways []string
// 命名空间
SourceNamespace string
}
Tcp
不满足以上HTTP和TLS条件的流量都会应用本节要介绍的TCP流量规则
type TCPRoute struct {
// 匹配规则
Match []*L4MatchAttributes
// 路由配置 前面已经讲解过用法
Route []*RouteDestination
}
type L4MatchAttributes struct {
// 请求ip地址
DestinationSubnets []string
// 请求端口号
Port uint32
// 关于子网配置 例如,a.b.c.d/xx
SourceSubnet string `protobuf:"bytes,3,opt,name=source_subnet,json=sourceSubnet,proto3" json:"source_subnet,omitempty"`
// 资源label前面已经讲解过
SourceLabels map[string]string
// gatway名称
Gateways []string
// 命名空间
SourceNamespace string
}
ExportTo
如果没有指定,该配置可以供所有命名空间使用,如果是. 则只允许本命名空间使用