天天看点

《Kubernetes网络权威指南》读书笔记 | Kubernetes Service探秘

作者:热爱编程的通信人

书籍来源:《Kubernetes网络权威指南:基础、原理与实践》

一边学习一边整理读书笔记,并与大家分享,侵权即删,谢谢支持!

附上汇总贴:《Kubernetes网络权威指南》读书笔记 | 汇总_COCOgsta的博客-CSDN博客

运行在每个节点上的Kube-proxy会监控Service和Endpoints的更新,并调用其Load Balancer模块在主机上刷新路由转发规则。

Kube-proxy的Load Balancer模块实现有userspace、iptables和IPVS三种,当前主流的实现方式是iptables和IPVS。随着iptables在大规模环境下暴露出了扩展性和性能问题,越来越多的厂商开始使用IPVS模式。

4.1.1userspace模式

Kube-proxy的userspace模式是通过Kube-proxy用户态程序实现Load Balancer的代理服务。userspace模式是Kube-proxy 1.0之前版本的默认模式。由于转发发生在用户态,效率自然不太高,而且容易丢包。

4.1.2iptables模式

从Kubernetes 1.1版本开始,增加了iptables模式,在1.2版本中它正式替代userspace模式成为默认模式。Kube-proxy iptables模式的原理如图4-3所示。

《Kubernetes网络权威指南》读书笔记 | Kubernetes Service探秘

图4-3 Kube-proxy iptables模式的原理

iptables模式与userspace模式最大的区别在于,Kube-proxy利用iptables的DNAT模块,实现了Service入口地址到Pod实际地址的转换,免去了一次内核态到用户态的切换。

iptables模式最主要的链是KUBE-SERVICES、KUBE-SVC-*和KUBE-SEP-*。

  • KUBE-SERVICES链是访问集群内服务的数据包入口点,它会根据匹配到的目标IP:port将数据包分发到相应的KUBE-SVC-*链;
  • KUBE-SVC-*链相当于一个负载均衡器,它会将数据包平均分发到KUBE-SEP-*链。每个KUBE-SVC-*链后面的KUBE-SEP-*链都和Service的后端Pod数量一样;
  • KUBE-SEP-*链通过DNAT将连接的目的地址和端口从Service的IP:port替换为后端Pod的IP:port,从而将流量转发到相应的Pod。

图4-4演示了从客户端Pod到不同节点上的服务器Pod的流量路径。客户端通过172.16.12.100:80连接到服务。每个节点上的Kube-proxy进程会根据Service和对应的Endpoints创建一系列的iptables规则,以将流量重定向到相应Pod(例如10.255.255.202:8080)。

《Kubernetes网络权威指南》读书笔记 | Kubernetes Service探秘

图4-4 Kube-proxy iptables模式的工作流

iptables模式与userspace模式相比虽然在稳定性和性能上均有不小的提升,但因为iptable使用NAT完成转发,也存在不可忽视的性能损耗。另外,当集群中存在上万服务时,Node上的iptables rules会非常庞大,对管理是个不小的负担,性能还会大打折扣。

iptables的SNAT

既然利用iptables做了一次DNAT,为了保证回程报文能够顺利返回,需要做一次SNAT。Kube-proxy创建的对应iptables规则形如:

《Kubernetes网络权威指南》读书笔记 | Kubernetes Service探秘

在KUBE-POSTROUTING链中,对节点上匹配MARK标记(0x4000/0x4000)的数据包在离开节点时进行一次SNAT,即MASQUERADE(用节点IP替换包的源IP)。

4.1.3IPVS模式

IPVS是LVS的负载均衡模块,亦基于netfilter,但比iptables性能更高,具备更好的可扩展性。Kube-proxy的IPVS模式在Kubernetes 1.11版本达到稳定。

既然Kube-proxy已经有了iptables模式,为什么Kubernetes还选择IPVS呢?iptables纯粹是为防火墙而设计的,并且底层路由表的实现是链表,对路由规则的增删改查操作都涉及遍历一次链表。

尽管Kubernetes在1.6版本中已经支持5000个节点,但使用iptables模式的Kube-proxy实际上是将集群扩展到5000个节点的最大瓶颈。

另外,使用IPVS做集群内服务的负载均衡可以解决iptables带来的性能问题。IPVS专门用于负载均衡,并使用更高效的数据结构(散列表)。

  1. IPVS的工作原理

IPVS是Linux内核实现的四层负载均衡,是LVS负载均衡模块的实现。

IPVS支持TCP、UDP、SCTP、IPv4、IPv6等协议,也支持多种负载均衡策略,例如rr、wrr、lc、wlc、sh、dh、lblc等。IPVS通过persistent connection调度算法原生支持会话保持功能。LVS的工作原理如图4-6所示。

《Kubernetes网络权威指南》读书笔记 | Kubernetes Service探秘

图4-6 LVS的工作原理

由于IPVS的DNAT发生在netfilter的INPUT链,因此如何让网路报文经过INPUT链在IPVS中就变得非常重要了。一般有两种解决方法,一种方法是把服务的虚IP写到本机的本地内核路由表中;另一种方法是在本机创建一个dummy网卡,然后把服务的虚IP绑定到该网卡上。Kubernetes使用的是第二种方法,详见下文。

IPVS支持三种负载均衡模式:Direct Routing(简称DR)、Tunneling(也称ipip模式)和NAT(也称Masq模式)。

DR

IPVS的DR模式如图4-7所示。DR模式是应用最广泛的IPVS模式,它工作在L2,即通过MAC地址做LB,而非IP地址。在DR模式下,要求IPVS的Director和客户端在同一个局域网内。另外,DR不支持端口映射,无法支撑Kubernetes Service的所有场景。

《Kubernetes网络权威指南》读书笔记 | Kubernetes Service探秘

图4-7 IPVS的DR模式

Tunneling

IPVS的Tunneling模式就是用IP包封装IP包,因此也称ipip模式,如图4-8所示。Tunneling模式下的报文不经过IPVS Director,而是直接回复给客户端。Tunneling模式同样不支持端口映射。

《Kubernetes网络权威指南》读书笔记 | Kubernetes Service探秘

图4-8 IPVS的Tunneling模式

NAT

IPVS的NAT模式支持端口映射,回程报文需要经过IPVS Director,因此也称Masq(伪装)模式,如图4-9所示。Kubernetes在用IPVS实现Service时用的正是NAT模式。

《Kubernetes网络权威指南》读书笔记 | Kubernetes Service探秘

图4-9 IPVS的NAT模式

  1. Kube-proxy IPVS模式参数

在运行基于IPVS的Kube-proxy时,需要注意以下参数:

  • --proxy-mode:除了现有的userspace和iptables模式,IPVS模式通过--proxy-mode=ipvs进行配置;
  • --ipvs-scheduler:用来指定IPVS负载均衡算法,如果不配置则默认使用roundrobin(rr)算法。

在运行IPVS模式的Kube-proxy前,请确保主机上已经加载了IPVS所需的所有内核模块,如下所示:

《Kubernetes网络权威指南》读书笔记 | Kubernetes Service探秘

如果要在Kubernetes 1.11之前使用IPVS模式的Kube-proxy,需要打开Kubernetes的特性开关,形如--feature-gates=SupportIPVSProxyMode=true。

  1. IPVS模式实现原理

Kube-proxy IPVS模式的工作原理如图4-10所示。

《Kubernetes网络权威指南》读书笔记 | Kubernetes Service探秘

图4-10 Kube-proxy IPVS模式的工作原理

一旦创建一个Service和Endpoints,IPVS模式的Kube-proxy会做以下三件事情。

(1)确保一块dummy网卡(kube-ipvs0)存在。

(2)把Service的访问IP绑定在dummy网卡上。

(3)通过socket调用,创建IPVS的virtual server和real server,分别对应Kubernetes的Service和Endpoints。

IPVS虽然有三种代理模式NAT、ipip和DR,但只有NAT模式支持端口映射。因此,Kube-proxy的IPVS使用了NAT模式,为的就是支持端口映射。

  1. IPVS模式中的iptables和ipset

IPVS用于流量转发,它无法处理Kube-proxy中的其他问题,例如包过滤、SNAT等。

不想创建太多的iptables规则,可以使用ipset减少iptables规则,使得不管集群内有多少服务,IPVS模式下iptables规则的总数在5条以内。

4.1.4iptablesVS.IPVS

表4-1 iptables和IPVS在刷新服务路由规则上的时延对比

《Kubernetes网络权威指南》读书笔记 | Kubernetes Service探秘

IPVS刷新规则的时延明显要低iptables几个数量级。

IPVS在端到端的吞吐率和平均时延方面均有不小的优化。

表4-2 iptables和IPVS的吞吐率与平均时延对比

《Kubernetes网络权威指南》读书笔记 | Kubernetes Service探秘

表4-3 Kube-proxy在IPVS和iptables模式下的资源消耗

《Kubernetes网络权威指南》读书笔记 | Kubernetes Service探秘

无论是资源消耗还是性能,IPVS模式均要优于iptables模式。

4.1.5conntrack

在内核中,所有由netfilter框架实现的连接跟踪模块称作conntrack(connection tracking)。在DNAT的过程中,conntrack使用状态机启动并跟踪连接状态。其中最主要的4个conntrack状态如下:

(1)NEW:匹配连接的第一个包,这表示conntrack对该数据包的信息一无所知。通常发生在收到SYN数据包时。

(2)ESTABLISHED:匹配连接的响应包及后续的包,conntrack知道该数据包属于一个已建立的连接。通常发生在TCP握手完成之后。

(3)RELATED:当一个连接与另一个ESTABLISHED状态的连接有关时,这个连接就被认为是RELATED。

(4)INVALID:匹配那些无法识别或没有任何状态的数据包,conntrack不知道如何处理它。

在Pod和Service之间的TCP数据流路径如图4-11所示。

《Kubernetes网络权威指南》读书笔记 | Kubernetes Service探秘

图4-11 Pod和Service之间的TCP数据流路径

TCP连接的生命周期分析如下:

  • 左边的客户端发送数据包到Service:192.168.0.2:80;
  • 数据包通过本地节点的iptables规则,目的地址被改为Pod的地址:10.0.1.2:80;
  • 提供服务的Pod处理完数据包后返回响应包给客户端:10.0.0.2;
  • 数据包到达客户端所在的节点后,被conntrack模块识别并将源地址改为:192.169.0.2:80;
  • 客户端接收到响应包。