使用 IPVS 在大规模集群下有一定的性能优势,但是也是需要一定条件才能支持的,如果没有满足的话就会自动降级为使用iptables模式,当前环境就是一开始内核版本为3.10.0,系统为CentOS 7.6,内核升级为 4.1 版本才完全支持。
在 Kubernetes 集群中,每个 Node 运行一个 kube-proxy 进程。kube-proxy 负责为 Service 实现了一种 VIP(虚拟IP)的形式,而不是 ExternalName 的形式。
在 Kubernetes v1.0 版本,代理完全在 userspace。在 Kubernetes v1.1 版本,新了 iptables 代理,但并不是默认的运行模式。从 Kubernetes v1.2 起,默认就是iptables代理。在 Kubernetes v1.8.0-beta.0 中,添加了 ipvs 代理。在 Kubernetes 1.14 版本开始默认使用 ipvs 代理。
为什么为 Kubernetes 选择 IPVS ?
随着 Kubernetes 的使用增长,其资源的可扩展性变得越来越重要。特别是,服务的可扩展性对于运行大型工作负载的开发人员/公司采用 Kubernetes 至关重要。
Kube-proxy 是服务路由的构建块,它依赖于经过强化攻击的 iptables 来实现支持核心的服务类型,如 ClusterIP 和 NodePort。 但是,iptables 难以扩展到成千上万的服务,因为它纯粹是为防火墙而设计的,并且基于内核规则列表。
尽管 Kubernetes 在版本v1.6中已经支持5000个节点,但使用 iptables 的 kube-proxy 实际上是将集群扩展到5000个节点的瓶颈。 一个例子是,在5000节点集群中使用 NodePort 服务,如果我们有2000个服务并且每个服务有10个 pod,这将在每个工作节点上至少产生20000个 iptable 记录,这可能使内核非常繁忙。
另一方面,使用基于 IPVS 的集群内服务负载均衡可以为这种情况提供很多帮助。 IPVS 专门用于负载均衡,并使用更高效的数据结构(哈希表),允许几乎无限的规模扩张。
类型 | 用途介绍 |
---|---|
rr |
轮询调度 |
lc |
最小连接数 |
dh |
目标哈希 |
sh |
源哈希 |
sed |
最短期望延迟 |
nq |
不排队调度 |
如果已经内核版本已经大于4.1的可以忽略这一步骤,因为此内核版本可以完美的支持IPVS,以我当前内核版本为例,如果把Sevice模式由 iptables 改成 ipvs,可能会出现以下问题:
# 开始环境的系统信息
# uname -r
3.10.0-1160.41.1.el7.x86_64
# cat /etc/redhat-release
CentOS Linux release 7.9.2009 (Core)
# 在 3.10 内核版本中改用ipvs,kube-proxy 会报如下错误
# kubectl -n kube-system logs kube-proxy-6pp2d
E0415 09:46:55.397466 1 proxier.go:1192] Failed to sync endpoint for service: 172.16.0.82:30080/TCP, err: parseIP Error ip=[172 16 100 7 0 0 0 0 0 0 0 0 0 0 0 0]
E0415 09:46:55.398639 1 proxier.go:1950] Failed to list IPVS destinations, error: parseIP Error ip=[172 16 100 7 0 0 0 0 0 0 0 0 0 0 0 0]
E0415 09:46:55.398658 1 proxier.go:1533] Failed to sync endpoint for service: 10.10.1.35:30080/TCP, err: parseIP Error ip=[172 16 100 7 0 0 0 0 0 0 0 0 0 0 0 0]
E0415 09:46:55.398751 1 proxier.go:1950] Failed to list IPVS destinations, error: parseIP Error ip=[172 16 100 7 0 0 0 0 0 0 0 0 0 0 0 0]
...
1) 从阿里云上下载
kernel-4.9# 更新内核时,对系统的cpu的负载很高,因此建议一台一台更新
# yum install kernel-4.9.215-36.el7.x86_64.rpm -y
# init 6
# uname -r
4.9.215-36.el7.x86_64
查看内核是否加载了 ipvs ,没有则加单独加载、安装。
# lsmod | grep -e ip_vs
ip_vs_sh 16384 0
ip_vs_wrr 16384 0
ip_vs_rr 16384 9
ip_vs 147456 15 ip_vs_wrr,ip_vs_rr,ip_vs_sh
nf_conntrack 106496 8 ip_vs,nf_conntrack_proto_sctp,nf_conntrack_ipv4,nf_conntrack_netlink,nf_nat_masquerade_ipv4,xt_conntrack,nf_nat_ipv4,nf_nat
libcrc32c 16384 2 ip_vs,xfs
# lsmod |grep nf_conntrack_ipv4
nf_conntrack_ipv4 16384 8
nf_defrag_ipv4 16384 1 nf_conntrack_ipv4
nf_conntrack 106496 8 ip_vs,nf_conntrack_proto_sctp,nf_conntrack_ipv4,nf_conntrack_netlink,nf_nat_masquerade_ipv4,xt_conntrack,nf_nat_ipv4,nf_na
# cat > /etc/sysconfig/modules/ipvs.modules <
# kubectl edit configmap kube-proxy -n kube-system
...
kind: KubeProxyConfiguration
metricsBindAddress: ""
mode: "ipvs" # "" 改成 ipvs
nodePortAddresses: null
oomScoreAdj: null
...
configmap/kube-proxy edited
--
# 删除现有的 kube-proxy pod,相当于重启后才会变更成 ipvs
# kubectl get pods -n kube-system|grep kube-proxy
kube-proxy-6pp2d 1/1 Running 1 8h
kube-proxy-mcfp6 1/1 Running 1 8h
kube-proxy-qmdhp 1/1 Running 1 8h
# kubectl delete pod/kube-proxy-6pp2d -n kube-system
pod "kube-proxy-6pp2d" deleted
# kubectl delete pod/kube-proxy-mcfp6-n kube-system
pod "kube-proxy-mcfp6" deleted
# kubectl delete pod/kube-proxy-qmdhp -n kube-system
pod "kube-proxy-qmdhp" deleted
# kubectl -n kube-system logs kube-proxy-qmdhp|grep ipvs
I0415 10:48:49.984477 1 server_others.go:259] Using ipvs Proxier.
# 在 kube-proxy pod 看到如上信息后说明是启用ipvs的
# 测试使用的是 deployment 2个nginx, 一个 svc 指向 nginx pod
# ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 127.0.0.1:30080 rr
-> 172.16.100.8:80 Masq 1 0 0
-> 172.16.100.197:80 Masq 1 0 0
TCP 172.16.0.1:443 rr
-> 10.10.1.35:6443 Masq 1 4 0
TCP 172.16.0.10:53 rr
-> 172.16.100.9:53 Masq 1 0 0
-> 172.16.100.10:53 Masq 1 0 0
TCP 172.16.0.10:9153 rr
-> 172.16.100.9:9153 Masq 1 0 0
-> 172.16.100.10:9153 Masq 1 0 0
...
注意事项:ipvs 尚未稳定,请慎用;而且 --masquerade-all 选项与 Calico 安全策略控制不兼容,请酌情考虑使用(Calico 在做网络策略限制的时候要求不能开启此选项)
Reference:
https://blog.csdn.net/weixin_43936969/article/details/106175580
https://blog.csdn.net/qq_25854057/article/details/122469765
https://kubernetes.io/zh/blog/2018/07/09/ipvs-based-in-cluster-load-balancing-deep-dive/