IPVS(IP Virtual Server)是lvs项目的一部分,作为Linux内核的一部分,提供4层负载均衡器的功能,即传输层负载均衡。ipvs运行在主机内核中,作为真是服务器集群前的负载均衡器,将到对服务的请求转发到真实的服务器上,并将多个ip的真实服务器集群的服务显示为单个ip的虚拟机服务。

kube-proxy作为Kubernetes集群中的网络代理和负载均衡器,其作用是将发送到Service的请求转发到具体的后端。 Kubernetes从1.8开始为kube-proxy组件引入了IPVS模式,并在Kubernetes 1.11进入GA,在Kubernetes 1.12成为kube-proxy的默认代理模式。本文将实践在测试环境中Kubernetes 1.11集群上开启IPVS。

1.kube-proxy代理的三种模式

当前Kubernetes kube-proxy的负载均衡支持以下三种代理模式:

  • userspace:这种模式下kube-proxy进程在用户空间监听一个本地端口,iptables规则将流量转发到这个本地端口,然后kube-proxy在其内部应用层建立到具体后端的连接,即在其内部进行转发,这是在用户空间的转发,虽然比较稳定,但效率不高。userspace模式是kube-proxy早期(Kubernetes 1.0)的模式,早就不推荐使用,也不会被我们使用。

kube-proxy-userspace

  • iptables:这种模式是从Kubernetes 1.2开始并在Kubernetes 1.12之前的默认方式。在这种模式下kube-proxy监控Kubernetes对Service、Endpoint对象的增删改操作。监控到Service对象的增删改,将配置iptables规则,截获到Service的ClusterIp和端口的流量并将其重定向到服务的某个后端;监控到Endpoint对象的增删改,将更新具体到某个后端的iptables规则。iptables模式基于netfilter,但因为流量的转发都是在Kernel Space,所以性能更高且更加可靠。 这种模式的缺点是,对于超大规模集群,当集群中服务数量达到一定量级时,iptables规则的添加将会出现很大延迟,因为规则的更新出现kernel local,所以此时将会出现性能问题,据这篇文章中《华为云在 K8S 大规模场景下的 Service 性能优化实践》介绍当Service数量达到5000个,iptables规则基数为40000,增加一条规则的时间将达到11分钟。

kube-proxy-iptables

  • ipvs:这种模式从Kubernetes 1.11进入GA,并在Kubernetes 1.12成为kube-proxy的默认代理模式。ipvs模式也是基于netfilter,对比iptables模式在大规模Kubernetes集群有更好的扩展性和性能,支持更加复杂的负载均衡算法(如:最小负载、最少连接、加权等),支持Server的健康检查和连接重试等功能。ipvs依赖于iptables,使用iptables进行包过滤、SNAT、masquared。ipvs将使用ipset需要被DROP或MASQUARED的源地址或目标地址,这样就能保证iptables规则数量的固定,我们不需要关心集群中有多少个Service了。

kube-proxy-ipvs

2.配置kube-proxy开启ipvs模式

2.1 开启ipvs的前提

由于ipvs已经加入到了内核的主干,所以为kube-proxy开启ipvs的前提需要加载以下的内核模块:

1ip_vs
2ip_vs_rr
3ip_vs_wrr
4ip_vs_sh
5nf_conntrack_ipv4

在所有的Kubernetes节点上执行以下脚本:

1cat > /etc/sysconfig/modules/ipvs.modules <<EOF
2#!/bin/bash
3modprobe -- ip_vs
4modprobe -- ip_vs_rr
5modprobe -- ip_vs_wrr
6modprobe -- ip_vs_sh
7modprobe -- nf_conntrack_ipv4
8EOF
9chmod 755 /etc/sysconfig/modules/ipvs.modules && bash /etc/sysconfig/modules/ipvs.modules && lsmod | grep -e ip_vs -e nf_conntrack_ipv4

上面脚本创建了的/etc/sysconfig/modules/ipvs.modules文件,保证在节点重启后能自动加载所需模块。 使用lsmod | grep -e ip_vs -e nf_conntrack_ipv4命令查看是否已经正确加载所需的内核模块。

接下来还需要确保各个节点上已经安装了ipset软件包yum install ipset。 为了便于查看ipvs的代理规则,最好安装一下管理攻击ipvsadm yum install ipvsadm

以上前提条件如果不满足,则及时kube-proxy的配置开启了ipvs模式,也会退回到iptables模式。

2.2 配置kube-proxy开启ipvs

Kubernetes 1.12的kube-proxy已经默认开启,对于Kubernetes 1.11,我们为kube-proxy的命令行参数中加入--proxy-mode=ipvs

重启kube-proxy后,查看其日志:

1I1020 14:57:11.915294       1 server_others.go:189] Using ipvs Proxier.
2W1020 14:57:11.915505       1 proxier.go:343] IPVS scheduler not specified, use rr by default
3I1020 14:57:11.915676       1 server_others.go:216] Tearing down inactive rules.

可以看出ipvs Proxier已经启用。同时使用ipvsadm命令可以看到相关Service的ipvs规则:

 1ipvsadm -ln
 2IP Virtual Server version 1.2.1 (size=4096)
 3Prot LocalAddress:Port Scheduler Flags
 4  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
 5TCP  127.0.0.1:30058 rr
 6  -> 10.244.1.3:443               Masq    1      0          0
 7  -> 10.244.1.4:443               Masq    1      0          0
 8TCP  172.17.0.1:30058 rr
 9  -> 10.244.1.3:443               Masq    1      0          0
10  -> 10.244.1.4:443               Masq    1      0          0
11TCP  172.17.0.1:31657 rr
12  -> 10.244.1.3:80                Masq    1      0          0
13  -> 10.244.1.4:80                Masq    1      0          0
14TCP  192.168.61.10:80 rr
15  -> 10.244.1.3:80                Masq    1      0          0
16  -> 10.244.1.4:80                Masq    1      0          0
17TCP  192.168.61.10:443 rr
18  -> 10.244.1.3:443               Masq    1      1          0
19  -> 10.244.1.4:443               Masq    1      0          1
20TCP  192.168.61.12:30058 rr
21  -> 10.244.1.3:443               Masq    1      0          0
22  -> 10.244.1.4:443               Masq    1      0          0
23TCP  192.168.61.12:31657 rr
24  -> 10.244.1.3:80                Masq    1      0          0
25  -> 10.244.1.4:80                Masq    1      0          0
26TCP  10.0.2.15:30058 rr
27  -> 10.244.1.3:443               Masq    1      0          0
28  -> 10.244.1.4:443               Masq    1      0          0
29......

注意事项:对于使用了externalIPs的Service,如ingress-controller,当开启IPVS后,externalIP也会作为VIP被ipvs接管,因此如果在externalIp指定的Kubernetes集群中的具体Node节点的IP,在重启kube-proxy之前需要提前将externalIp替换成预先规划好的VIP,否则会出现VIP和Node节点IP冲突的问题。

参考