在Istio中提供了ServiceEntry的配置,将网格外的服务加入网格中,像网格内的服务一样进行管理。在实现上就是把外部服务加入 Istio 的服务发现,这些外部服务因为各种原因不能被直接注册到网格中。
下面通过一个配置示例了解 ServiceEntry 的基本用法,在该配置示例中通过ServiceEntry包装了一个对“www.weatherdb.com”外部服务的访问。在网格内是一个完整应用,对外提供weather服务,但某些数据来自另一个开放数据服务“www.weatherdb.com”,通过如下配置就可以对开放数据服务的访问进行治理:
如图3-58所示是ServiceEntry的规则定义,可以配置外部服务的DNS域名、VIP、端口、协议和后端地址等。
图3-58 ServiceEntry的规则定义
可以看到,ServiceEntry主要包含如下几个字段。
(1)hosts:是一个必选字段,表示与 ServiceEntry 相关的主机名,可以是一个 DNS域名,还可以使用前缀模糊匹配。在使用上有以下几点需要说明。
◎ HTTP的流量,这个字段匹配HTTP Header的Host或Authority。
◎ HTTPS或TLS的流量,这个字段匹配SNI。
◎ 其他协议的流量,这个字段不生效,使用下面的addresses和port字段。
◎ 当resolution被设置为DNS类型并且没有指定endpoints时,这个字段将用作后端的域名来进行路由。
(2)addresses:表示与服务关联的虚拟IP地址,可以是CIDR这种前缀表达式。对于HTTP的流量,该字段被忽略,而是使用Header中的Host或Authority。如果addresses为空,则只能根据目标端口来识别,在这种情况下这个端口不能被网格里的其他服务使用。即Sidecar只是作为一个TCP代理,把某个特定端口的流量转发到配置的目标后端。
(3)ports:表示与外部服务关联的端口,是一个必选字段。
(4)location:用于设置服务是在网格内部还是在网格外部。可以取以下两种模式。
◎ MESH_EXTERNAL:表示在网格外部,通过 API 访问的外部服务。示例中的“www.weatherdb.com”就是一个外部服务。
◎ MESH_INTERNAL:表示在网格内部,一些不能直接注册到网格服务注册中心的服务,例如一些虚机上的服务不能通过Kubernetes机制自动在Istio中进行服务注册,通过这种方式可以扩展网格管理的服务。
location 字段会影响 mTLS 双向认证、策略执行等特性。当和网格外部服务通信时,mTLS双向认证将被禁用,并且策略只能在客户端执行,不能在服务端执行。因为对于外部服务,远端不可能注入一个Sidecar来进行双向认证等操作。
(5)resolution 是一个内容较多的必选字段,表示服务发现的模式,用来设置代理解析服务的方式,将一个服务名解析到一个后端IP地址上,可以设置NONE、STATIC、DNS三种模式。另外,这里配置的解析模式不影响应用的服务名解析,应用仍然使用 DNS 将服务解析到IP上,这样Outbound流量会被Envoy拦截。
◎ NONE:用于当连接的目标地址已经是一个明确 IP 的场景。当访问外部服务且应用要被解析到一个特定的IP上时,要将模式设为NONE。
◎ STATIC:用在已经用endpoints设置了服务实例的地址场景中,即不用解析。
◎ DNS:表示用查询环境中的DNS进行解析。如果没有设置endpoints,代理就会使用在hosts中指定的DNS地址进行解析,前提是在hosts中未使用通配符;如果设置了endpoints,则使用endpoints中的DNS地址解析出目标IP。在3.5.1节的配置示例中使用hosts的值“www.weatherdb.com”进行解析。
(6)subjectAltNames:表示这个服务负载的SAN列表。在Istio安全相关配置的多个地方被用到,被设置时,代理将验证服务证书的SAN是否匹配。
(7)endpoints:表示与网格服务关联的网络地址,可以是一个IP,也可以是一个主机名。这个字段是一个Endpoints的复杂结构。
◎ address:必选字段,表示网络后端的地址。在前面 ServiceEntry 的解析方式中resolution 被设置为 DNS时,address可以使用域名,但要求是明确的地址,不可以使用模糊匹配。
◎ ports:端口列表。
◎ labels:后端的标签。
◎ network:这个高级配置主要用在Istio多集群中。所有属于相同network的后端都可以直接互访,不在同一个 network 的后端不能直接访问。在使用 Istio Gateway时可以对不同network的后端建立连接。
◎ locality:后端的locality,主要用于亲和性路由。即Envoy可以基于这个标识做本地化路由,优先路由到本地的后端上。locality表示一个故障域,常见的如国家、地区、区域,也可以分割每个故障域来表示任意层次的结构。
◎ weight:表示负载均衡的权重,权重越高,接收的流量占比越大。
此外,Istio 1.1在ServiceEntry上添加了一个重要字段exportTo,用于控制ServiceEntry跨命名空间的可见性,这样就可以控制在一个命名空间下定义的资源对象是否可以被其他命名空间下的Sidecar、Gateway和VirtualService使用。如果未赋值,则默认全局可见。“.”表示仅应用到当前命名空间,“*”表示应用到所有命名空间,在Istio 1.1中只支持“.”和“*”这两种配置。
配置访问外部服务是ServiceEntry的典型应用,Manifest的定义参照3.5.1节的配置示例,这样就可以像网格内的服务一样进行治理。如图 3-59 所示,forecast 服务对“www.weatherdb.com”的访问被本地的Sidecar拦截,从而对访问进行治理。
除了采用上面这种方式直接从网格内的 Sidecar 访问外部服务,有时对外部服务的访问必须经过一个对外的 Egress代理的场景,因为只有这个节点有对外的 IP或者这个节点是统一的安全出口等,访问会如图3-60所示。
图3-59 通过ServiceEntry访问网格外的服务
图3-60 通过Egress Gateway访问外部服务
这时首先需要创建一个Egress Gateway,创建对外部服务“www.weatherdb.com”的访问:
然后通过如下VirtualService定义流量规则:
可以看到,定义了两个Route。
◎ 网格内流量:这个Route的gateways是“mesh”关键字,表示来自网格内的流量。这类流量在访问“www.weatherdb.com”这个外部地址时将被转发到Egress Gateway上。
◎ 网格对外流量:这个 Route匹配的 gateways字段是 Egress,表示匹配来自 Egress的流量,这种流量将被路由到外部服务“www.weatherdb.com”上。