Gateway在网格边缘接收外部访问,并将流量转发到网格内的服务。Istio通过Gateway将网格内的服务发布成外部可访问的服务,还可以通过Gateway配置外部访问的端口、协议及与内部服务的映射关系。
下面通过一个配置示例认识Gateway,通过HTTP的80端口访问网格内的服务:
另外,配合 Gateway的使用,VirtualService要做适当修改,在 hosts上匹配 Gateway上请求的主机名,并通过gateways字段关联定义的Gateway对象。3.2.1节VirtualService部分的示例配置被更新为:
Gateway 一般和 VirtualService 配合使用。Gateway 定义了服务从外面怎样访问;VirtualService定义了匹配到的内部服务怎么流转。正是有了Gateway的存在,才能在入口处对服务进行统一治理。
不同于在V1alpha1的API中使用Kubernetes的Ingress对象同时描述服务入口和对后端服务的路由,Istio 在当前的 V1alpha3 中引入的 Gateway只是描述服务的外部访问,而服务的内部路由都在VirtualService中定义,从而解耦服务的外部入口和服务的内部路由。在一个 VirtualService 上定义的路由既可以对接 Gateway 应用到外部访问,也可以作为内部路由规则应用到网格内的服务间调用。例如,3.4.1节配置示例中的规则对于内部和外部路由都可以生效。
Gateway的规则定义如图3-52所示,与前面的两个规则定义相比较,Gateway的定义看上去比较简单,主要定义了一组开放的服务列表。
图3-52 Gateway的规则定义
可以看到,在Gateway上定义了如下两个关键字段。
◎ selector:必选字段,表示Gateway负载,为入口处的Envoy运行的Pod的标签,通过这个标签来找到执行Gateway规则的Envoy。在Istio 1.1后,社区推荐Gateway的规则定义和Gateway的Envoy负载在同一个命名空间下。在Istio 1.0时没有这个要求,包括社区的Bookinfo经典示例仍将Gateway的负载部署在istio-system下,但是Gateway规则可以在另外的命名空间如default下。
◎ server:必选字段,表示开放的服务列表,是Gateway的关键内容信息,是一个数组,每个元素都是Server类型。
1.后端服务Server
Server 在结构上真正定义了服务的访问入口,可通过 port、hosts、defaultEndpoint 和tls来描述。
(1)port:必选字段,描述服务在哪个端口对外开放,是对外监听的端口。
(2)hosts:必选字段,为 Gateway 发布的服务地址,是一个 FQDN 域名,可以支持左侧通配符来进行模糊匹配。另外,Istio 1.1支持在这个字段中加入命名空间条件来匹配特定命名空间下的 VirtualService。如果设置了命名空间,则会匹配该命名空间下的VirtualService,如果未包含命名空间,则会尝试匹配所有命名空间。常用于HTTP服务,也可以是TCP或者HTTPS。
注意:在Istio 1.1的Gateway中支持在hosts匹配时使用命名空间的过滤条件。
绑定到一个Gateway上的VirtualService必须匹配这里的hosts条件,支持精确匹配和模糊匹配。以本节的入门示例Gateway和VirtualService进行说明,假设通过VirtualService上的gateways字段已经建立了绑定,则示例中的Gateway在istio-system下,VirtualService在weather下。我们通过比较如表3-5所示的Gateway和VirtualService Hosts的匹配示例来理解规则。
表3-5 Gateway和VirtualService Hosts的匹配示例
续表
在 Gateway 和 VirtualService 关联时,要注意 Istio 1.1 在 VirtualService 中增加的exportTo字段,只有对应的VirtualService的exporTo包含Gateway的命名空间,对应的关联才会生效。
(3)defaultEndpoint:是 Istio 1.1 新增的属性,表示流量转发的默认后端,可以是一个loopback的后端,也可以是UNIX的域套接字。
(4)tls:在实际使用中考虑到安全问题,在入口处都通过 HTTPS 的安全协议访问。这就需要一些额外的信息来描述,在Gateways上Server专门有个TLSOptions类型的字段tls来描述这部分定义,在下一节详细描述。
我们一般基于port和hosts字段来发布一个内部服务供外面访问,如下所示为发布一个HTTP的服务:
2.TLS选项TLSOptions
Server 上的另一个重要字段 tls 是与安全服务接口相关的,配置一个安全的协议总不那么容易,在这个属性上配置会比较多。
◎ httpsRedirect:是否要做HTTP重定向,在这个布尔属性启用时,负载均衡器会给所有HTTP连接都发送一个301的重定向,要求使用HTTPS。
◎ mode:在配置的外部端口上使用TLS模式时,可以取PASSTHROUGH、SIMPLE、MUTUAL、AUTO_PASSTHROUGH这4种模式。
◎ serverCertificate:服务端证书的路径。当模式是SIMPLE和MUTUAL时必须指定,配置在单向和双向认证场景下用到的服务端证书。
◎ privateKey:服务端密钥的路径。当模式是SIMPLE和MUTUAL时必须指定,配置在单向和双向认证场景下用到的服务端私钥。
◎ caCertificates:CA 证书路径。当模式是 MUTUAL 时指定,在双向认证场景下配置在Gateway上验证客户端的证书。
◎ credentialName:Istio 1.1 的新特性,用于唯一标识服务端证书和密钥。Gateway使用 credentialName从远端的凭据存储(如 Kubernetes的 Secrets)中获取证书和密钥,而不是使用Mount的文件。
◎ subjectAltNames:SAN 列表。SubjectAltName 允许一个证书指定多个域名,在Gateways上可以用来验证客户端提供的证书中的主题标识。
◎ minProtocolVersion:TLS协议的最小版本。
◎ maxProtocolVersion:TLS协议的最大版本。
◎ cipherSuites:指定的加密套件,默认使用Envoy支持的加密套件。
下面认识Gateway的几种典型应用。
1.将网格内的HTTP服务发布为HTTP外部访问
3.4.1 节的配置示例介绍了将一个内部的 HTTP 服务通过 Gateway 发布出去的典型场景。如图3-53所示,外部服务通过域名http://weather.com访问到应用的入口服务frontend。VirtualService本身定义了frontend服务从内部和外部访问同样的路由规则,即根据内容的不同,将请求路由到v2版本或v1版本。注意,这里Gateway的协议是HTTP。
图3-53 将网格内的HTTP服务发布为HTTP外部访问
2.将网格内的HTTPS服务发布为HTTPS外部访问
在实际使用中更多的是配置 HTTPS 等安全的外部访问。例如,在这个场景中,将网格内的HTTPS服务通过HTTPS协议发布。这样在浏览器端中输入“https://weather.com”就可以访问到这个服务,如图3-54所示。
图3-54 将网格内的HTTPS服务发布为HTTPS外部访问
如下所示是这种场景的Gateway配置,重点是:端口为443,协议为HTTPS,TLS模式为PASSTHROUGH,表示Gateway只透传应用程序提供的HTTPS内容。在本示例中,frontend 入口服务自身是 HTTPS 类型的服务,TLS 需要的服务端证书、密钥等都是由frontend服务自己维护的。这时要对frontend服务做路由管理,在VirtualService中需要配置支持TLSRoute规则,如果没有配置,则流量会被当作TCP处理:
这时,Istio只是通过Gateway将一个内部的HTTPS服务发布出去。Istio提供了通道和机制,HTTPS的证书及网格外部HTTPS客户端如何访问frontend服务都是frontend服务自己的事情。这里的HTTPS是应用程序的HTTPS,不是Istio的Gateway提供的HTTPS。对于自身的服务已经是HTTPS的应用,Istio支持通过这种方式把服务发布成外部可访问,但更推荐的是下面的做法,即将网格内一个 HTTP的服务通过 Gateway发布为 HTTPS外部访问。
3.将网格内的HTTP服务发布为HTTPS外部访问
与上一个场景类似,要求网格外部通过 HTTPS 访问入口服务,差别为服务自身是HTTP,在发布的时候通过 Gateway 的配置可以提供 HTTPS 的对外访问能力。如图 3-55所示,外部通过HTTPS访问,入口服务frontend是HTTP服务。
图3-55 将网格内HTTP服务发布为HTTPS外部访问
这时配置Gateway如下,可以看到端口为443,协议为HTTPS。与前一种场景的入口服务自身为HTTPS不同,这里的TLS模式是SIMPLE,表示Gateway提供标准的单向TLS认证。这时需要通过 serverCertificate和 privateKey提供服务端证书密钥。从图 3-55也可以看到 TLS 认证的服务端是在入口的 Envoy 上创建的,入口服务 frontend 本身保持原有的HTTP方式:
这种方式又被称为终结的HTTPS,在Gateway外面是HTTPS,但从Gateway往里的服务间访问还是 HTTP。入口处作为 Gateway的 Envoy,一方面作为服务提供者的入口代理,将 frontend 服务以 HTTPS 安全协议发布出去;另一方面作为服务消费者的代理,以HTTP向 frontend服务发起请求。正因为有了后面这种能力,对于 frontend服务上的路由仍然可以使用HTTP的路由规则。
这种方式既可以提供第1种HTTP发布同样的灵活性,又可以满足第2种场景要求的入口安全访问。在Gateway服务发布时提供了安全的能力,对服务自身的代码、部署及网格内部的路由规则的兼容都没有影响,因此是推荐的一种做法。
4.将网格内的HTTP服务发布为双向HTTPS外部访问
对于大多数场景,使用上面的方式将入口的 HTTP 服务发布成标准的 HTTPS 就能满足需要。在某些场景下,比如调用入口服务的是另一个服务,在服务端需要对客户端进行身份校验,这就需要用到TLS的双向认证,如图3-56所示。
图3-56 将网格内HTTP服务发布为双向HTTPS外部访问
这种方式的主要流程和第3种场景单向认证类似,都是在入口处Gateway角色的Envoy上开放 HTTPS服务,外部 HTTPS请求在 Gateway处终止,内部 VirtualService的路由配置仍然是HTTP。
在如下配置方式中,可以看到,双向认证和单向认证的差别在于,Gateway上的模式被设定为 MUTUAL 时表示双向认证,同时,为了支持双向认证,除了要配置通过serverCertificate和privateKey提供服务端证书密钥,还需要提供caCertificates来验证客户端的证书,从而实现和调用方的双向认证:
5.将网格内的HTTP服务发布为HTTPS外部访问和HTTPS内部访问
除了以上几种方式,有没有一种方式可以将一个 HTTP 服务通过 Gateway 发布为HTTPS服务?同时在网格内部也是HTTPS的双向认证?当然有,这是Istio安全能力的主要场景,如图 3-57所示,不用修改代码,HTTP服务在网格内和网格外都是 HTTPS安全方式互访。
图3-57 将网格内的HTTP服务发布为HTTPS外部访问和HTTPS内部访问
这里的Gateway的Manifest和场景3完全相同,不再重复介绍。
我们只需知道 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认证,两者没有任何关系。
下面通过如表3-6所示的Gateway上的服务发布方式比较来理解以上几种场景。
表3-6 Gateway上的服务发布方式比较
此外,在Gateway上一般都是发布多个服务,如下所示为配置多个Server元素: