Istio 网关之南北向流量管理

天涯浪子 提交于 2020-08-13 12:39:49

头图.png

作者 | 王夕宁  阿里巴巴高级技术专家

参与阿里巴巴云原生公众号文末留言互动,有机会获得赠书福利!

本文摘自于由阿里云高级技术专家王夕宁撰写的《Istio 服务网格技术解析与实践》一书,文章介绍将集群外部的客户端连接到集群内运行的服务,以及如何从集群内的服务访问集群外部的任何服务,即通常所说的南北向流量管理。其中介绍了 Istio 在南北向流量方面的路由控制能力,引出 Istio 网关的概念及其工作原理。

本文文末汇集并整理了近期 Istio 的相关问题并特邀王夕宁老师进行解答,希望能够对大家有所帮助~

Istio 网关

网络社区中有一个术语 Ingress,是指入口请求到集群内服务的流量管理。Ingress 指的是源自本地网络之外的流量,指向本地集群网络中的端点。此流量首先路由到公开的入口点,以便通过执行一些本地网络的规则和策略来确认哪些流量被允许进入。如果流量未通过这些入口点,则无法与集群内的任何服务连接。如果入口点允许流量进入,则将其代理到本地网络中的合适节点。Istio 对入口流量的管理是由 Istio 网关进行的。

Istio 网关的工作原理

传统上,Kubernetes 使用 Ingress 控制器来处理从外部进入集群的流量。使用 Istio 时,情况不再如此。Istio 网关用新的 Gateway 资源和 VirtualServices 资源来控制入口流量,它们协同工作以将流量路由到网格中。在网格内部不需要 Gateways,因为服务可以通过集群本地服务名称相互访问。

那么 Istio 网关是怎样工作的?请求如何到达它想要的应用程序?基本步骤如下:

1.客户端在特定端口上发出请求;
2.负载均衡器在这个端口上进行侦听,并将请求转发到集群中(在相同或新的端口);
3.在集群内部,请求被路由到 Istio IngressGateway 服务所侦听的负载均衡器转发过来的端口上;
4.Istio IngressGateway 服务将请求(在相同或新的端口)转发到对应的 pod 上;
5.在 IngressGateway pod 上会配置 Gateway 资源和 VirtualService 资源定义。Gateway 会配置端口、协议以及相关安全证书。VirtualService 的路由配置信息用于找到正确的服务;
6.Istio IngressGateway pod 会根据路由配置信息将请求路由到对应的应用服务上;
7.应用服务将请求路由到对应的应用 pod 上。





1.png
(tio 网关的工作原理)

Istio 网关的负载均衡作用

典型的服务网格具有一个或多个负载均衡器,也称为网关(Gateway),它们从外部网络终止 TLS 并允许流量进入网格。然后,流量通过边车网关(Sidecar gateway)流经内部服务。应用程序使用外部服务的场景也很常见,可以直接调用外部服务,或者在某些部署中强制通过专用出口网关(Egress Gateway)离开网格的所有流量。

Istio 具有入口网关的概念,它扮演网络入口点的角色,负责保护和控制来自集群外部的流量对集群的访问。

2.png
(网关在网格中的使用情况)

此外,Istio 的网关还扮演负载均衡和虚拟主机路由的角色。如图所示,可以看到默认情况下 Istio 使用 Envoy 代理作为入口代理。Envoy 是一个功能强大的服务到服务代理,但它也有负载均衡和路由的功能,可代理的流量包括从服务网格外部到其内部运行的服务,或者从集群内部服务到外部服务。在前面章节中介绍的 Envoy 的所有功能也可以在入口网关中使用。

3.png
(Istio 的入口网关服务)

对于入口流量管理,你可能会问:为什么不直接使用 Kubernetes Ingress API?

  • 第一个原因,Kubernetes Ingress 是一个面向 HTTP 工作负载的非常简单的规范。有 Kubernetes Ingress 的实现(如 Nginx、Heptio Contour 等),但每个都适用于 HTTP 流量。实际上,Ingress 规范只将端口 80 和端口 443 视为入口点。这严重限制了集群运维人员可以允许进入服务网格的流量类型。例如,如果你有 Kafka 工作负载,则可能希望向这些消息代理公开直接 TCP 连接;
  • 第二个原因,Kubernetes Ingress API 无法表达 Istio 的路由需求。Ingress 没有通用的方法来指定复杂的流量路由规则,如流量拆分或流量镜像等。这个领域缺乏规范会导致每个供应商重新设想如何更好地为每种类型的 Ingress 实现(如 HAProxy、Nginx 等)做好配置管理。Ingress 试图在不同的 HTTP 代理之间取一个公共的交集,因此只能支持最基本的 HTTP 路由;
  • 最后一个原因,由于事前没有明确规定,大多数供应商的选择是通过部署上的定制注释来做配置。供应商之间的注释各不相同,并且不可移植,如果 Istio 继续延续这种趋势,那么就会有更多的注释来解释 Envoy 作为边缘网关的所有功能。

Istio 网关通过将 L4-L6 配置与 L7 配置分离克服了 Ingress 的这些缺点。Istio 网关只用于配置 L4-L6 功能(例如,对外公开的端口、TLS 配置),所有主流的 L7 代理均以统一的方式实现了这些功能。然后,通过在 Gateway 上绑定 VirtualService 的方式,可以使用标准的 Istio 规则来控制进入 Gateway 的 HTTP 和 TCP 流量。负载均衡器可以手动配置或通过服务自动配置其类型,例如 type: LoadBalancer。在这种情况下,由于并非所有云都支持自动配置,假设手动配置负载均衡器以将流量转发到 IngressGateway Service 正在侦听的端口。例如如下的负载均衡器正在监听以下端口:

  • HTTP:端口 80,将流量转发到端口 30080;
  • HTTPS:端口 443,将流量转发到端口 30443;
  • MySQL:端口 3306,将流量转发到端口 30306 确保负载均衡器配置转发到所有工作节点。这将确保即使某些节点关闭也会转发流量。

入口网关服务

IngressGateway 服务(入口网关服务)必须监听上节介绍的所有端口,以便能够将流量转发到 IngressGateway pod 上。Kubernetes 服务不是“真正的”服务,该请求将由 Kubernetes 提供的 kube-proxy 转发到具有运行对应 pod 的节点上。在节点上,IP table 配置将请求转发到适当的 pod:

ports:
  - name: http2
    nodePort: 30000
    port: 80
    protocol: TCP
  - name: https
    nodePort: 30443
    port: 443
    protocol: TCP
  - name: mysql
    nodePort: 30306
    port: 3306
    protocol: TCP

入口网关部署

IngressGateway 部署是一个基于 Envoy 代理的封装,它的配置方式与服务网格中使用的 Sidecar 配置相同(实际上是同样的容器镜像)。当我们创建或更改一个 Gateway 或 VirtualService 时,Istio Pilot 控制器会检测到这些变更,并将这些变更信息转换为 Envoy 配置,然后将 Envoy 配置信息发送给相关 Envoy 代理,包括内部的 Envoy 和 IngressGateway 中的 Envoy。

注意:这里不要混淆 IngressGateway 与 Gateway,Gateway 资源是用于配置 IngressGateway 的一种 Kubernetes 的自定义资源。

由于不必在 Kubernetes pod 或部署中声明容器端口,因此我们不必在 IngressGateway Deployment 中声明端口。但是,如果查看部署内部,可以看到声明的许多端口。另外,在 IngressGateway 部署中需要关注 SSL 证书,为了能够访问 Gateway 资源内的证书,请确保已正确加载这些证书。

网关资源

网关资源用来配置 Envoy 的端口,前面的示例中已经使用该服务公开了三个端口,因此需要在 Envoy 中处理这些端口。此外,可以通过声明一个或多个 Gateways 来支持多端口能力。下面的示例中使用单个 Gateway,但可以分为两个或三个分别定义:

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: default-gateway
  namespace: istio-system
spec:
  selector:
    istio: ingressgateway
  servers:
  - hosts:
    - '*'
    port:
      name: http
      number: 80
      protocol: HTTP
  - hosts:
    - '*'
    port:
      name: https
      number: 443
      protocol: HTTPS
    tls:
      mode: SIMPLE
      privateKey: /etc/istio/ingressgateway-certs/tls.key
      serverCertificate: /etc/istio/ingressgateway-certs/tls.crt
  - hosts: # For TCP routing this fields seems to be ignored, but it is matched
    - '*'  # with the VirtualService, I use * since it will match anything.
    port:
      name: mysql
      number: 3306
      protocol: TCP

网关虚拟服务

VirtualService 资源与 Gateway 资源相互配合支持 Envoy 的配置。下面是一个支持 HTTP 服务的网关虚拟服务的基本配置:

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: counter
spec:
  gateways:
  - default-gateway.istio-system.svc.cluster.local
  hosts:
  - counter.lab.example.com
  http:
  - match:
    - uri:
      prefix: /
    route:
    - destination:
        host: counter
        port:
          number: 80

现在,当我们添加一个 Gateway 和一个 VirtualService 时,路由已在 Envoy 配置中创建。要查看此内容,你可以使用如下命令:

kubectl port-forward istio-ingressgateway-xxxx-yyyy-n istio-system 15000

调试入口网关

调试网络问题有时很困难,所以这里总结一些有用的命令用于调试。端口转发到第一个 istio-ingressgateway pod:

kubectl -n istio-system port-forward $(kubectl -n istio-system get pods 
-listio=ingressgateway -o=jsonpath="{.items[0].metadata.name}") 15000

然后,可以从端口转发的入口网关 pod 中获得 http 路由:

Curl --silent http://localhost:15000/config_dump |jq .configs[3].dynamic_route_configs[].route_config.virtual_hosts[]

4.png
(端口转发的入口网关 pod)

查看上述端口转发的入口网关 pod 的日志信息:

kubectl -n istio-system logs $(kubectl -n istio-system get pods 
-listio=ingressgateway -o=jsonpath="{.items[0].metadata.name}") --tail=300

查看 Pilot pod 的日志信息:

kubectl -n istio-system logs $(kubectl -n istio-system get pods 
-listio=pilot -o=jsonpath="{.items[0].metadata.name}") discovery --tail=300

当启动端口转发到入口网关 istio-ingressgateway 之后,可以执行更多操作以获取更多信息,例如:

《Istio服务网格技术解析与实战》读者可免费体验 ASM 产品进行学习!点击了解阿里云服务网格产品 ASM:
www.aliyun.com/product/servicemesh

作者简介

王夕宁 阿里云高级技术专家,阿里云服务网格产品 ASM 及 Istio on Kubernetes 技术负责人,专注于 Kubernetes、云原生、服务网格等领域。曾在 IBM 中国开发中心工作,担任过专利技术评审委员会主席,拥有 40 多项相关领域的国际技术专利。《Istio 服务网格解析与实战》一书由其撰写,详细介绍了 Istio 的基本原理与开发实战,包含大量精选案例和参考代码可以下载,可快速入门 Istio 开发。Gartner 认为,2020 年服务网格将成为所有领先的容器管理系统的标配技术。本书适合所有对微服务和云原生感兴趣的读者,推荐大家对本书进行深入的阅读。

关于 Istio 的一些 Q&A

Q1:Istio 在实际生产环境实践中都会遇到哪些瓶颈,常见的优化手段又都有哪些?
A1:阿里云之所以推出服务网格 ASM 这个产品,就是把过去一两年支持客户使用 Istio 的过程中遇到的太多问题,总结成了经验并落地到产品中。所以多关注下这个产品的能力就会看到具体解决了哪些问题。在此就不一一赘述了。

Q2:Istio 会导致性能消耗增加吗?
A2:这个问题需要一个上下文,这就像问 Java 虚拟机会导致性能消耗吗。任何解耦总会带来一定的通信消耗。建议使用 Istio 前先判断下自己的应用是否适合解耦、服务化以及容器化,然后再看是否适合采用 Istio 的哪些功能。

Q3:Service Mesh 是很好的工具,但是痛点也很明显,引入 Istio 会让运维更加复杂,阿里云服务网格产品 ASM 这方面有做什么改进?
A3:阿里云服务网格 ASM 提供了一个全托管式的服务网格平台,兼容于社区 Istio 开源服务网格,用于简化服务的治理,并提供了简单易用的控制台,托管模式下让用户解脱控制面的复杂管理,极大地减轻开发与运维的工作负担。具体可以参考这个入门教程了解一下:https://help.aliyun.com/document_detail/149552.html

Q4:最近在研究 Istio,有真正落地使用的例子吗?
A4:过去一两年我们已经支持了大量客户使用 Istio,譬如有客户使用 Istio 流量管理来做应用的灰度发布,有客户使用它的统一的声明式的方式来管理入口网关,包括入口网关的 tls 透传功能、tls 终止以及动态加载证书的能力等等。

Q5:目前阿里服务网格产品 ASM 针对 Istio 采用什么样的监控?
A5:阿里云服务网格 ASM 的可观测性能力从三个维度提供了不同的能力,包括:

Q6:阿里的 ASM 的 Proxy 会采用 MOSN 吗?期待 MOSN 成为 Istio 可选数据平面之一。
A6:阿里云服务网格 ASM 从一开始的设计就是兼容于社区 Istio 开源服务网格,只要符合与 Istio 控制面规约要求的数据面代理,从理论上都是可以支持的。当然一个新代理的适配是需要一定量的开发工作,这儿我们也想了解下客户对于这方面的诉求。

Q7:Istio 也有类似 Linkerd 的 mutls 功能吗?
A7:Istio 默认已经提供了双向 tls 认证的功能,而且支持渐进式,包括 permissive 和 strict 两种方式。

- 赠书福利 -

5.png

《Istio 服务网格技术解析与实践》- 机械工业出版社赞助

5 月 15 日 11:00 前在阿里巴巴云原生公众号留言区分享你在学习 Istio 技术的踩坑经验、或者对新技术的更新、迭代有何独特的个人见解,精选留言点赞前 3 名各送出此书一本!

课程推荐

为了更多开发者能够享受到 Serverless 带来的红利,这一次,我们集结了 10+ 位阿里巴巴 Serverless 领域技术专家,打造出最适合开发者入门的 Serverless 公开课,让你即学即用,轻松拥抱云计算的新范式——Serverless。

点击即可免费观看课程:https://developer.aliyun.com/learning/roadmap/serverless

阿里巴巴云原生关注微服务、Serverless、容器、Service Mesh 等技术领域、聚焦云原生流行技术趋势、云原生大规模的落地实践,做最懂云原生开发者的公众号。”

原文链接
本文为云栖社区原创内容,未经允许不得转载。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!