写点什么

【IstioCon 2021】如何在 Istio 中进行源地址保持?

发布于: 2021 年 03 月 23 日
【IstioCon 2021】如何在Istio中进行源地址保持?

北京时间 2 月 23 日,在全球首届社区峰会 IstioCon 2021 中,华为云原生开源团队核心成员徐中虎发表了《Preserve Original Source Address within Istio》主题演讲。


演讲嘉宾:徐中虎

 

徐中虎,华为云原生开源团队核心成员,Istio 社区指导委员会委员(亚洲唯一),Istio Maintainer 以及核心贡献者,Kubernetes 项目核心贡献者。畅销书《云原生服务网格 Istio:原理、实践、架构与源码解析》作者之一,聚焦在 Kubernetes、容器、Service Mesh 等云原生技术。对于分布式系统高性能、高可靠、大规模扩展性有深入的研究和丰富的经验。


演讲主要包含三部分的内容:

  • 源地址的使用场景

  • 常用的源地址保持方式

  • Istio 源地址保持的方案


源地址的使用场景


源地址使用场景多种多样,比如说:

1)简单的会话保持,可以根据客户端的地址,基于源 IP 做负载均衡,将来自同一个客户端的请求,转发到同一个服务实例;

2)用于安全策略控制,常用的黑白名单设置;

3)访问日志和监控统计,访问日志和监控指标中包含真实的源地址,有助于开发人员分析和 Debug;

4)IP 电话(VoIP)和流媒体服务的典型代表技术 SIP 中继链接是一种基于 IP 地址区分用户的方式,源 IP 地址对于 SIP 来说至关重要。


我们可以看到不同的技术场景对源 IP 的依赖程度不一,对于某些强依赖的场景,如果不能实现源地址的保持,那么 Istio 则不能应用于此场景。


常见的源 IP 保持方式及背景知识


在 Istio 等服务网格技术出现以前,典型的服务访问模型如图所示。开发者一般将应用服务部署在企业负载均衡设备后面,以应对高并发、高可用的需求。企业通过负载均衡设备提供服务的统一访问入口,常见的负载均衡设备有硬件负载均衡 F5,软件负载均衡 LVS、HaProxy、Nginx 等。不同负载均衡器提供的源 IP 地址保持的方式不尽相同。


我们常用的源 IP 保持的方式从 OSI 网络模型 L3-L7 主要分为:


1. L3

LVS,是内核层的软负载,从原理上看属于一次连接,性能属于软负载中最高的,也是业界使用最为广泛的 L3 负载均衡器。LVS 工作模型有 NAT 模式、DR 模式、隧道模式。我们主要基于 NAT 模式看一下 LVS 的源地址保持。

(1)当用户请求到达 Director Server,此时请求的数据报文会先到内核空间的 PREROUTING 链。此时报文的源 IP 为 CIP,目标 IP 为 VIP。

(2) PREROUTING 检查发现数据包的目标 IP 是本机,将数据包送至 INPUT 链, LVS 主要工作在 INPUT 链。

(3) IPVS 比对数据包请求的服务是否为集群服务,若是,修改数据包的目标 IP 地址为后端服务器 IP,然后将数据包发至 POSTROUTING 链。此时报文的源 IP 为 CIP,目标 IP 为 RIP ,在这个过程完成了目标 IP 的转换(DNAT),而源地址始终没变。

(4) POSTROUTING 链通过选路,将数据包发送给 Real Server。


HAProxy 透明传输模式也是一种 L3 层的源地址保持方式,但是它工作在用户空间,是典型的两次连接模型。

1)用户首先与 HAProxy 建立一条连接,当用户请求到达 HAProxy 时,HAProxy 获取客户端的 IP 地址。


2)HAProxy 工作在透明传输模式下,根据负载均衡策略选择一个真实的后端服务,然后绑定客户端的 IP 地址,与后端服务建立新的连接。透明代理依赖 socket 的 IP_TRANSPARENT


3)真实服务器响应数据包必须经过 HAProxy 代理,因此,透明传输还得依赖个性化路由的配置以及 TPROXY。


2. L4

TOA, TOA 插件是基于四层协议(TCP)获取真实源 IP 的方法,本质是将源 IP 地址插入 TCP 协议的 Options 字段。华为云提供了 TOA 插件,用户只要在在内核中安装 TOA 模块,在使用时即可以系统调用的方式获取源 IP 地址。


Proxy Protocol 是另外一种四层的源地址保持方式,协议标准最早由 HAProxy 社区发展而来。其工作原理特别简单,要求客户端在 TCP 连接建立之后,应用数据发送之前,首先发送一个 Proxy Protocol 协议头,服务器通过解析协议头获取真实的客户端 IP 地址。Proxy Protocol 标准要求客户端和服务端同时支持代理协议。这里 Client 在真实世界中可以是 Envoy、HAProxy、Nginx 等支持代理协议的负载均衡器。



3. L7

七层源地址保持的方式相对而言最为简单,最具代表性的是 HTTP 头 x-forwarded-for,x-forwarded-for 中可以包含原始用户的 IP 地址,高级语言 HTTP 库基本都能自动获取源地址。


另外,开发者可以自定义协议类型,将客户端的源 IP 地址塞到协议帧。


Istio 源地址保持困境

我们从服务网格东西向和南北向分别来看一下,当前 Istio 服务网格中源地址获取的障碍。


1)服务网格东西向服务访问时,由于 Sidecar 的注入,所有进出服务的流量均被 Envoy 拦截代理,当 svcA 访问 svcB 时,svcB 的 Sidecar Envoy 与 svcB 建立一条连接,源地址是 127.0.0.1,目的地址也是 127.0.0.1(未来是 PodIP)。单纯从 TCP 通信的角度来看,svcB 只能获取到客户端地址是 127.0.0.1。


集群内服务访问


Ingress 服务访问


2)Istio 南北向服务访问中,用户请求首先通过 ELB 服务代理转发到 Istio 的 Ingress Gateway,然后 Ingress Gateway 再将请求负载均衡到真实的服务实例。由图中可见,中间经过的网络节点更多,同时包含 ELB 和 Istio。源地址的保持更加困难。


如何在 Istio 服务网格中获取源地址


Envoy 提供了两个监听器级别的过滤器:源地址过滤器(“envoy.filters.listener.original_src”)和代理协议过滤器(“envoy.filters.listener.proxy_protocol”)。


1)源地址过滤器作用在 Envoy 的 Inbound 监听器,其工作原理是获取下游连接的客户端地址,并以客户端地址为源地址与上游服务建立新的连接。本质上是 IP_TRANSPARENT 透明传输,这一点对 TCP 源地址的获取非常重要。前面我们介绍到透明传输还必须解决 IP 包回程的问题,这一点我们留在后面再讲。

2)代理协议过滤器也作用于监听器,主要职责为解析 Proxy Protocol 协议,可在服务端获取源地址,特别适合 Ingress 服务源地址获取。

3)Proxy Protocol Transport Socket,是 Envoy 与上游通过 Proxy Protocol 进行源 IP 保持的一种方式,其主要构造代理协议头,并主动发送给上游支持代理协议的服务。

4)HTTP XFF(x-forwarded-for)自动注入,envoy 可以根据 LDS HTTP 连接管理配置自动添加最近的下游客户端的 IP 地址到 XFF 中。


1. HTTP 类协议源 IP 保持



Ingress HTTP


Ingress 服务访问场景,ELB 提供的方案可以分为 TOA 和 Proxy Protocol 两种。在 TOA 模式下,必须在 Ingress Gateway 所在的节点安装 TOA 内核模块才能使 Ingress Gateway 获取原始客户端 IP 地址。在 Proxy Protocol 场景下,必须通过配置 envoy.filters.listener.proxy_protocol 过滤器才能使 Ingress Gateway 获取真实客户 IP。详细配置如下,当然使能此过滤器必须非常小心,前提是确保所有进入 Ingress Gateway 的流量一定是 Proxy Protocol。


两种模式下,都需要配置 Ingress gateway 使其支持 XFF 自动添加, 另外可以通过 xff_num_trusted_hops 额外配置 Envoy 信任的代理跳数,详细参考https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_conn_man/headers#x-forwarded-for


2. TCP 源 IP 保持


集群内 TCP 源地址保持


Istio 主要通过以下配置确保 svcB 和 Sidecar Envoy 之间通过 svcA 的地址通信。

1)配置源地址过滤器,Envoy 就能绑定下游客户端的地址(10.244.0.20)svcB 建立连接。

2)配置 TPROXY 和个性化路由,确保 svcB 发送到 10.244.0.20 的数据包被 Envoy 接收。主要是对数据包打标记,然后根据自定义路由,将非本地的数据包通过本地 lo 路由。

-A PREROUTING -p tcp -m mark --mark 0x539 -j CONNMARK --save-mark --nfmask 0xffffffff --ctmask 0xffffffff
-A OUTPUT -p tcp -m connmark --mark 0x539 -j CONNMARK --restore-mark --nfmask 0xffffffff --ctmask 0xffffffff
ip -f inet rule add fwmark 1337 lookup 133
ip -f inet route add local default dev lo table 133
复制代码



Ingress TCP 源地址保持相对更复杂,理论上除以上规则外,需要额外增加 Proxy Protocol 协议的支持。在 Ingress Gateway 上配置 Proxy Protocol,


在 svcB 上配置 envoy.filters.listener.proxy_protocol,保证 Envoy 监听器获取原始客户端 IP。


本文小结


源 IP 保持并不是一个新鲜的话题,然而我们在 Istio 服务网格中发现很多成熟的方案都黯然失效。说到底,这与 Istio Sidecar 的代理有莫大的关系,Istio Sidecar 自动注入直接导致了我们不能直接以个性化配置解决源地址保持的问题。而是要结合 Istio 的配置管理,实现统一的配置方案。


本文根据本人在 IstioCon 2021 的分享整理而来,相关的案例 demo 都可以在https://github.com/hzxuzhonghu/istio-demo

找到,希望对大家有所启发。


欢迎关注华为云原生团队,我们将为你提供:

我们每日更新关于云原生技术动态、实战进阶、应用案例等;

入群与行业技术大牛,1 万+云原生爱好者一起链接学习;

不定期邀请云原生 OG 级技术大咖分享技术实战

…………


用户头像

还未添加个人签名 2020.02.11 加入

还未添加个人简介

评论

发布
暂无评论
【IstioCon 2021】如何在Istio中进行源地址保持?