一、先从Cluster IP开始

Kubernetes以Pod作为应用部署的最小单位。kubernetes会根据Pod的声明对其进行调度,包括创建、销毁、迁移、水平伸缩等,因此Pod 的IP地址不是固定的,不方便直接采用Pod IP对服务进行访问。

为解决该问题,Kubernetes提供了Service资源,Service对提供同一个服务的多个Pod进行聚合。一个Service提供一个虚拟的Cluster IP,后端对应一个或者多个提供服务的Pod。在集群中访问该Service时,采用Cluster IP即可,Kube-proxy负责将发送到Cluster IP的请求转发到后端的Pod上。

Kube-proxy是一个运行在每个节点上的go应用程序,支持三种工作模式:

二、userspace 模式

该模式下kube-proxy会为每一个Service创建一个监听端口。发向Cluster IP的请求被Iptables规则重定向到Kube-proxy监听的端口上,Kube-proxy根据LB算法选择一个提供服务的Pod并和其建立链接,以将请求转发到Pod上。

该模式下,Kube-proxy充当了一个四层Load balancer的角色。由于kube-proxy运行在userspace中,在进行转发处理时会增加两次内核和用户空间之间的数据拷贝,效率较另外两种模式低一些;好处是当后端的Pod不可用时,kube-proxy可以重试其他Pod。

userspace
userspace

三、iptables 模式

为了避免增加内核和用户空间的数据拷贝操作,提高转发效率,Kube-proxy提供了iptables模式。在该模式下,Kube-proxy为service后端的每个Pod创建对应的iptables规则,直接将发向Cluster IP的请求重定向到一个Pod IP。

该模式下Kube-proxy不承担四层代理的角色,只负责创建iptables规则。该模式的优点是较userspace模式效率更高,但不能提供灵活的LB策略,当后端Pod不可用时也无法进行重试。

k8s-iptables
k8s-iptables

四、ipvs 模式

该模式和iptables类似,kube-proxy监控Pod的变化并创建相应的ipvs rules。ipvs也是在kernel模式下通过netfilter实现的,但采用了hash table来存储规则,因此在规则较多的情况下,Ipvs相对iptables转发效率更高。除此以外,ipvs支持更多的LB算法。如果要设置kube-proxy为ipvs模式,必须在操作系统中安装IPVS内核模块。

k8s-ipvs
k8s-ipvs

五、选择IPVS的原因

IPVS (IP Virtual Server,IP虚拟服务器)是基于Netfilter的、作为linux内核的一部分实现传输层负载均衡的技术,通常称为第4层LAN交换。IPVS集成在LVS(Linux Virtual Server)中,它在主机中运行,并在真实服务器集群前充当负载均衡器。IPVS可以将对TCP/UDP服务的请求转发给后端的真实服务器,并使真实服务器的服务在单个IP地址上显示为虚拟服务。因此IPVS天然支持Kubernetes Service。

随着kubernetes使用量的增长,其资源的可扩展性变得越来越重要。特别是对于使用kubernetes运行大型工作负载的开发人员或者公司来说,service的可扩展性至关重要。kube-proxy是为service构建路由规则的模块,之前依赖iptables来实现主要service类型的支持,比如(ClusterIP和NodePort)。但是iptables很难支持上万级的service,因为iptables纯粹是为防火墙而设计的,并且底层数据结构是内核规则的列表。

kubernetes早在1.6版本就已经有能力支持5000多节点,这样基于iptables的kube-proxy就成为集群扩容到5000节点的瓶颈。举例来说,如果在一个5000节点的集群,我们创建2000个service,并且每个service有10个pod,那么我们就会在每个节点上有至少20000条iptables规则,这会导致内核非常繁忙。基于IPVS的集群内负载均衡就可以完美的解决这个问题。IPVS是专门为负载均衡设计的,并且底层使用哈希表这种非常高效的数据结构,几乎可以允许无限扩容。

IPVS模式在Kubernetes v1.8中引入,并在v1.9中进入了beta。 1.11中实现了GA(General Availability)。IPTABLES模式在v1.1中添加,并成为自v1.2以来的默认操作模式。 IPVS和IPTABLES都基于netfilter。 IPVS模式和IPTABLES模式之间的差异如下:

  • IPVS为大型集群提供了更好的可扩展性和性能。(规则的存储方式使用的数据结构更高效)
  • IPVS支持比iptables更复杂的负载平衡算法(最小负载,最少连接,位置,加权等)。
  • IPVS支持服务器健康检查和连接重试等。

六、以 ipvs 模式 运行kube-proxy

确保IPVS需要内核模块

 1$ ip_vs
 2ip_vs_rr
 3ip_vs_wrr
 4ip_vs_sh
 5nf_conntrack_ipv4
 6
 7# 可以通过如下命令加载
 8$ modprobe ip_vs
 9modprobe ip_vs_rr
10modprobe ip_vs_wrr
11modprobe ip_vs_sh
12modprobe nf_conntrack_ipv4
13
14#查看是否被加载
15$ ls /usr/lib/modules/3.10.0-514.el7.x86_64/kernel/net/netfilter/ipvs/ |grep  -e ip_vs
16ip_vs_dh.ko
17ip_vs_ftp.ko
18ip_vs.ko
19ip_vs_lblc.ko
20ip_vs_lblcr.ko
21ip_vs_lc.ko
22ip_vs_nq.ko
23ip_vs_pe_sip.ko
24ip_vs_rr.ko
25ip_vs_sed.ko
26ip_vs_sh.ko
27ip_vs_wlc.ko
28ip_vs_wrr.ko
29
30$ ls /usr/lib/modules/3.10.0-514.el7.x86_64/kernel/net/ipv4/netfilter/ |grep nf_conntrack_ipv4
31nf_conntrack_ipv4.ko
3233lsmod | grep -e ip_vs -e nf_conntrack_ipv4
3435cut -f1 -d " "  /proc/modules | grep -e ip_vs -e nf_conntrack_ipv4

在使用IPVS模式之前,还应在节点上安装ipset等软件包。默认情况下,Kube-proxy在以kubeadm部署的集群中以iptables模式运行。查看日志如下:

1[root@master] ~$ kubectl logs kube-proxy-58j2k  -n kube-system
2W0115 11:00:48.003306       1 server_others.go:295] Flag proxy-mode="" unknown, assuming iptables proxy
3I0115 11:00:48.814060       1 server_others.go:148] Using iptables Proxier.
4I0115 11:00:48.831178       1 server_others.go:178] Tearing down inactive rules.
5I0115 11:00:51.566086       1 server.go:464] Version: v1.13.0

修改ConfigMap的kube-system/kube-proxy中的config.conf

 1[root@master] ~$ kubectl edit cm kube-proxy -n kube-system
 2configmap/kube-proxy edited
 3#修改如下
 4kind: MasterConfiguration
 5apiVersion: kubeadm.k8s.io/v1alpha1
 6...
 7ipvs:
 8      excludeCIDRs: null
 9      minSyncPeriod: 0s
10      scheduler: ""
11      syncPeriod: 30s
12    kind: KubeProxyConfiguration
13    metricsBindAddress: 127.0.0.1:10249
14    mode: "ipvs"                  #修改
15...

之后重启各个节点上的kube-proxy(删除后会自动重新创建)

 1[root@master] ~$ kubectl get pod -n kube-system | grep kube-proxy |awk '{system("kubectl delete pod "$1" -n kube-system")}'
 2pod "kube-proxy-7dstj" deleted
 3pod "kube-proxy-lx887" deleted
 4pod "kube-proxy-nfsb9" deleted
 5pod "kube-proxy-pkj44" deleted
 6[root@master] ~$ kubectl get pod -n kube-system | grep kube-proxy
 7kube-proxy-47dh9                           1/1     Running   0          13s
 8kube-proxy-64qnx                           1/1     Running   0          17s
 9kube-proxy-cbm26                           1/1     Running   0          20s
10kube-proxy-xnpnn                           1/1     Running   0          15s

再次查看日志,可以看到ipvs已经启用了

1[root@master] ~$ kubectl logs kube-proxy-47dh9  -n kube-system
2I0118 22:12:10.119829       1 server_others.go:189] Using ipvs Proxier.
3W0118 22:12:10.120601       1 proxier.go:381] IPVS scheduler not specified, use rr by default
4I0118 22:12:10.120714       1 server_others.go:216] Tearing down inactive rules.
5I0118 22:12:10.158816       1 server.go:464] Version: v1.13.2
6I0118 22:12:10.163081       1 conntrack.go:52] Setting nf_conntrack_max to 131072
7I0118 22:12:10.172084       1 config.go:202] Starting service config controller