IPVS简介:

尽管 Kubernetes 在版本v1.6中已经支持5000个节点,但使用 iptables 的 kube-proxy 实
际上是将集群扩展到5000个节点的瓶颈。 在5000节点集群中使用 NodePort 服务,如果有2000个服务并且每个服务有10个 pod,这将在每个工作节点上至少产生20000个iptable 记录,这可能使内核非常繁忙。

ipvs (IP Virtual Server) 实现了传输层负载均衡,也就是我们常说的4层LAN交换,作为Linux 内核的一部分。ipvs运行在主机上,在真实服务器集群前充当负载均衡器。

k8s 默认情况下有三种网络负载均衡模式
1、userspace 代理模式
2、iptables代理模式
3、ipvs代理模式

这三种代理模式的负载能力是依次递增的

也就是说ipvs在同等资源占用下拥有最佳的性能
在这种模式下kube-proxy会监视k8s集群中的对象和端点(endpoint),调用netlink接口以相应地创建ipvs规则并定期与k8s中的service对象和endpoints同步ipvs规则,以确保ipvs状态与期望一致。当访问svc时流量就会被重定向到后端的一个pod。

与 iptables 类似,ipvs 于 netfilter 的 hook 功能,但使用哈希表作为底层数据结构并在内核空间中工作。这意味着 ipvs 可以更快地重定向流量,并且在同步代理规则时具有更好的性能。此外,ipvs 为负载均衡算法提供了更多选项,例如:

rr :轮询调度

lc :最小连接数

dh :目标哈希

sh :源哈希

sed :最短期望延迟

nq : 不排队调度

k8s iptables规则下发 k8s的ipvs_k8s iptables规则下发


kubernetes开启ipvs 模式,主要修改kube-proxy 配置。

前提条件:

确保IPVS需要内核模块

ip_vs

ip_vs_rr

ip_vs_wrr

ip_vs_sh

nf_conntrack_ipv4

检查已编译到节点内核中是否被加载

grep -e ipvs -e nf_conntrack_ipv4 /lib/modules/$(uname -r)/modules.builtin

modprobe -- ip_vs
modprobe -- ip_vs_rr
modprobe -- ip_vs_wrr
modprobe -- ip_vs_sh
modprobe -- nf_conntrack_ipv4
to check loaded modules, use
lsmod | grep -e ipvs -e nf_conntrack_ipv4
or
cut -f1 -d " " /proc/modules | grep -e ip_vs -e nf_conntrack_ipv4

注:
linux kernel 4.19版本已经将nf_conntrack_ipv4 更新为 nf_conntrack, 而 kube-proxy 1.13 以下版本,强依赖 nf_conntrack_ipv4。 解决方式:
1、降级内核到 4.18
2、升级kube-proxy到 1.13+ (推荐,无需重启机器,影响小)

升级kube-proxy:
1、下载bin文件

https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG-1.13.md#node-binaries
wget https://dl.k8s.io/v1.13.2/kubernetes-node-linux-amd64.tar.gz

2、解压后替换 kube-proxy文件,更新配置,完成重启

tar -zxvf kubernetes-node-linux-amd64.tar.gz
mv /usr/local/bin/kube-proxy /usr/local/bin/kube-proxy.1.12.3
cp kubernetes/node/bin/kube-proxy /usr/local/bin/
配置文件更新如下:
/etc/systemd/system/kube-proxy.service
...
--proxy-mode=ipvs
...
systemctl restart kube-proxy.service # 重启服务

3、 查看日志确认没有异常

journalctl -u kube-proxy.service
日志中输出:
server_others.go:189] Using ipvs Proxier. 表示配置ipvs模式成功

接下来验证 ipvs 规则:
(需提前安装好 ipvsadm 管理工具)

#ipvsadm -ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 172.17.0.1:30443 rr
-> 10.244.0.23:443 Masq 1 0 0
TCP 172.17.0.1:36142 rr

我们可以看到有相关的规则,表示service 已经开始使用ipvs 进行流量负载均衡了。
4、压力测试:
简单启动nginx 服务, 暴露nodeport

#kubectl create deployment nginxtest --image=nginx:1.12
#kubectl expose deployment nginxtest --port=80 --type=NodePort
#kubectl get svc nginxtest
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginxtest NodePort 10.68.10.190 80:35896/TCP 84s
#kubectl get deployments nginxtest
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
nginxtest 1 1 1 1 118s
使用ab进行测试:
#ab -c 100 -n 100000 http://10.68.10.190/
#ab -c 100 -n 100000 http://10.188.1.201:35896/

如无异常,则表示ipvs功能正常可用了。