使用外部 Web 服务
描述基于 Istio Bookinfo 示例的简单场景。
在许多情况下,在 service mesh 中的微服务序并不是应用程序的全部,有时, 网格内部的微服务需要使用在服务网格外部的遗留系统提供的功能,虽然我们希望逐步将这些系统迁移到服务网格中。 但是在迁移这些系统之前,必须让服务网格内的应用程序能访问它们。还有其他情况, 应用程序使用外部组织提供的 Web 服务,通常是通过万维网提供的服务。
在这篇博客文章中,我修改了 Istio Bookinfo 示例应用程序让它可以 从外部 Web 服务(Google Books APIs )获取图书详细信息。 我将展示如何使用 mesh-external service entries 在 Istio 中启用外部 HTTPS 流量。最后, 我解释了当前与 Istio 出口流量控制相关的问题。
初始设定
为了演示使用外部 Web 服务的场景,我首先使用安装了 Istio 的 Kubernetes 集群, 然后我部署 Istio Bookinfo 示例应用程序, 此应用程序使用 details 微服务来获取书籍详细信息,例如页数和发布者, 原始 details 微服务提供书籍 详细信息,无需咨询任何外部服务。
此博客文章中的示例命令适用于 Istio 1.0+,无论启用或不启用双向 TLS。
Bookinfo 配置文件位于 Istio 发行存档的 samples/bookinfo
目录中。
以下是原始 Bookinfo 示例应用程序中应用程序端到端体系结构的副本。
执行部署应用程序、确认应用正在运行,以及 应用默认目标规则中的步骤部分。
Bookinfo 使用 HTTPS 访问 Google 图书网络服务
让我们添加一个新版本的 details 微服务,v2,从 Google Books APIs 中获取图书详细信息。
它设定了服务容器的 DO_NOT_ENCRYPT
环境变量为 false
。此设置将指示已部署服务使用 HTTPS(而不是 HTTP )来访问外部服务。
现在,应用程序的更新架构如下所示:
请注意,Google Book 服务位于 Istio 服务网格之外,其边界由虚线标记。
现在让我们将指向 details 微服务的所有流量定向到 details v2:
请注意,VirtualService
依赖于您在应用默认目标规则部分中创建的目标规则。
在确定 ingress 的 IP 和端口之后, 让我们访问应用程序的网页。
糟糕… 页面显示 Error fetching product details,而不是书籍详细信息:
好消息是我们的应用程序没有崩溃, 通过良好的微服务设计,我们没有让故障扩散。在我们的例子中,
失败的 details 微服务不会导致 productpage
微服务失败, 尽管 details 微服务失败,
仍然提供了应用程序的大多数功能, 我们有优雅的服务降级:正如您所看到的,评论和评级正确显示,
应用程序仍然有用。
那可能出了什么问题?啊…… 答案是我忘了启用从网格内部到外部服务的流量,在本例中是 Google Book Web 服务。 默认情况下,Istio sidecar 代理(Envoy proxies) 阻止到集群外目的地的所有流量, 要启用此类流量,我们必须定义 mesh-external service entry。
启用对 Google Books 网络服务的 HTTPS 访问
不用担心,让我们定义网格外部 ServiceEntry
并修复我们的应用程序。您还必须定义 virtual
service 使用 SNI 对外部服务执行路由。
现在访问应用程序的网页会显示书籍详细信息而不会出现错误:
您可以查询您的 ServiceEntry
:
您可以删除您的 ServiceEntry
:
并在输出中看到删除了 ServiceEntry
。
删除 ServiceEntry
后访问网页会产生我们之前遇到的相同错误,即 Error fetching product details,
正如我们所看到的,与许多其他 Istio 配置一样,ServiceEntry
是动态定义的 , Istio 运算符可以动态决定
它们允许微服务访问哪些域, 他们可以动态启用和禁用外部域的流量,而无需重新部署微服务。
清除对 Google 图书网络服务的 HTTPS 访问权限
由 Istio 发起的 TLS
这个故事有一个警告。假设您要监视您的微服务使用 Google API 的哪个特定集
(书籍,日历,任务等)
假设您要强制执行仅允许使用图书 API 的策略。
假设您要监控您的微服务访问的标识符。对于这些监视和策略任务,您需要知道 URL 路径。
考虑例如 URL www.googleapis.com/books/v1/volumes?q=isbn:0486424618
。
在该网址中,路径段指定了图书 API
/books
和路径段的 ISBN 代码
/volumes?q=isbn:0486424618
。但是,在 HTTPS 中,所有 HTTP 详细信息(主机名,路径,标头等)都是加密的
sidecar 代理的这种监督和策略执行是无法实现的。Istio 只能通过 SNI(Server Name Indication)得知加密请求中的主机名称,在这里就是 www.googleapis.com
。
为了允许 Istio 基于域执行出口请求的过滤,微服务必须发出 HTTP 请求, 然后,Istio 打开到目标的 HTTPS 连接(执行 TLS 发起), 根据微服务是在 Istio 服务网格内部还是外部运行, 微服务的代码必须以不同方式编写或以不同方式配置, 这与最大化透明度 的 Istio 设计目标相矛盾, 有时我们需要妥协……
下图显示了如何执行外部服务的 HTTPS 流量, 在顶部,Istio 服务网格外部的微服务发送常规 HTTPS 请求, 端到端加密, 在底部,Istio 服务网格内的相同微服务必须在 pod 内发送未加密的 HTTP 请求, 这些请求被 sidecar Envoy 代理拦截 , sidecar 代理执行 TLS 发起,因此 pod 和外部服务之间的流量被加密。
以下是我们如何在 Bookinfo 的 details 微服务代码 中使用 Ruby net/http 模块:
当定义 WITH_ISTIO
环境变量时,在没有 SSL(普通 HTTP )的情况下请求会通过 80 端口执行。
我们将 details v2 的部署配置文件 的环境变量 DO_NOT_ENCRYPT
设置为 “true”。
container
部分:
在下一节中,您将配置 TLS 发起以访问外部 Web 服务。
具有 TLS 的 Bookinfo 起源于 Google Books 网络服务
部署 details v2 版本,将 HTTP 请求发送到 Google Books API。 在
bookinfo-details-v2.yaml
中,DO_NOT_ENCRYPT
变量设置为 true。将指向 details 微服务的流量定向到 details v2。
为
www.google.apis
创建网格外部ServiceEntry
,virtual service 将目标端口从 80 重写为 443,并执行 TLS 的destination rule
。访问应用程序的网页,并验证显示的书籍详细信息没有错误。
检查 details v2 的 sidecar 代理的日志,并查看 HTTP 请求。
请注意日志中的 URL 路径,可以监视路径并根据它来应用访问策略。要了解有关 HTTP 出口流量的监控和访问策略 的更多信息,请查看归档博客之出口流量监控之日志。
清除 TLS 原始数据到 Google Books 网络服务
Istio 双向 TLS 的关系
请注意,在这种情况下,TLS 的源与 Istio 应用的双向 TLS 无关, 无论 Istio 双向 TLS 是否启用,外部服务的 TLS 源都将起作用 , 保证服务网内的服务到服务通信, 并为每个服务提供强大的身份认证, 在此博客文章中的 外部服务的情况下,我们有单向 TLS, 这是用于保护 Web 浏览器和 Web 服务器之间通信的相同机制 , TLS 应用于与外部服务的通信, 以验证外部服务器的身份并加密流量。
结论
在这篇博文中,我演示了 Istio 服务网格中的微服务如何通过 HTTPS 使用外部 Web 服务, 默认情况下,
Istio 会阻止集群外主机的所有流量, 要启用此类流量,请使用 mesh-external, 必须为服务网格创建 ServiceEntry
,
可以通过 HTTPS 访问外部站点,当微服务发出 HTTPS 请求时,流量是端到端加密的,但是 Istio 无法监视 HTTP 详细信息,
例如请求的 URL 路径。当微服务发出 HTTP 请求时,Istio 可以监视请求的 HTTP 详细信息并强制执行基于 HTTP 的访问策略。
但是,在这种情况下,微服务和 sidecar 代理之间的流量是未加密的。在具有非常严格的安全要求的组织中,
可以禁止未加密的部分流量。