K8s服务发现与负载均衡
服务发现
1、service
1.1、什么是Service
Service是一个抽象的概念。它通过一个虚拟的IP的形式(VIPs),映射出来指定的端口,通过代理客户端发来的请求转发到后端一组Pods中的一台(也就是endpoint)
Service定义了Pod逻辑集合和访问该集合的策略,是真实服务的抽象。Service提供了统一的服务访问入口以及服务代理和发现机制,关联多个相同Label的Pod,用户不需要了解后台Pod是如何运行。 外部系统访问Service的问题: -> 首先需要弄明白Kubernetes的三种IP这个问题 - Node IP:Node节点的IP地址 - Pod IP: Pod的IP地址 - Cluster IP:Service的IP地址
-> 首先,Node IP是Kubernetes集群中节点的物理网卡IP地址,所有属于这个网络的服务器之间都能通过这个网络直接通信。这也表明Kubernetes集群之外的节点访问Kubernetes集群之内的某个节点或者TCP/IP服务的时候,必须通过Node IP进行通信
-> 其次,Pod IP是每个Pod的IP地址,他是Docker Engine根据docker0网桥的IP地址段进行分配的,通常是一个虚拟的二层网络。
最后Cluster IP是一个虚拟的IP,但更像是一个伪造的IP网络,原因有以下几点: -> Cluster IP仅仅作用于Kubernetes Service这个对象,并由Kubernetes管理和分配P地址 -> Cluster IP无法被ping,他没有一个“实体网络对象”来响应 -> Cluster IP只能结合Service Port组成一个具体的通信端口,单独的Cluster IP不具备通信的基础,并且他们属于Kubernetes集群这样一个封闭的空间。 -> Kubernetes集群之内,Node IP网、Pod IP网于Cluster IP网之间的通信,采用的是Kubernetes自己设计的一种编程方式的特殊路由规则。
1.2、service原理
VIP 其实现原理主要是靠TCP/IP的ARP协议。因为ip地址只是一个逻辑 地址,在以太网中MAC地址才是真正用来进行数据传输的物理地址,每台主机中都有一个ARP高速缓存,存储同一个网络内的IP地址与MAC地址的对应关 系,以太网中的主机发送数据时会先从这个缓存中查询目标IP对应的MAC地址,会向这个MAC地址发送数据。操作系统会自动维护这个缓存,这就是整个实现 的关键。
2、IPTables
Iptables模式为Services的默认代理模式。在iptables 代理模式中,kube-proxy不在作为反向代理的在VIPs 和backend Pods之间进行负载均衡的分发。这个工作放给工作在四层的iptables来实现。iptables 和netfilter紧密集成,密切合作,都在kernelspace 就实现了包的转发。
在这个模式下,kube-proxy 主要有这么几步来实现实现报文转发:
- 通过watching kubernetes集群 cluster API, 获取新建、删除Services或者Endpoint Pod指令。
- kube-proxy 在node上设置iptables规则,当有请求转发到Services的 ClusterIP上后,会立即被捕获,并重定向此Services对应的一个backend的Pod。
- kube-proxy会在node上为每一个Services对应的Pod设置iptables 规则,选择Pod默认算法是随机策略。
在iptables模式中,kube-proxy把流量转发和负载均衡的策略完全委托给iptables/netfiter 来做,这些转发操作都是在kernelspace 来实现,比userspace 快很多。
在iptables 中kube-proxy 只做好watching API 同步最新的数据信息这个角色。路由规则信息和转发都放在了kernelspace 的iptables 和netfiter 来做了。但是,这个这个模式不如userspace模式的一点是,在usersapce模式下,kube-proxy做了负载均衡,如果选择的backend 一台Pod没有想要,kube-proxy可以重试,在iptables模式下,就是一条条路由规则,要转发的backend Pod 没有响应,且没有被K8S 摘除,可能会导致转发到此Pod请求超时,需要配合K8S探针一起使用。
2.1、负载均衡的方式
在Linux中使用iptables完成tcp的负载均衡有两种模式:随机、轮询
The statistic module support two different modes:
random:(随机)
the rule is skipped based on a probability
nth:(轮询)
the rule is skipped based on a round robin algorithm
2.2、随机方式
下面以一个example说明iptables两种LB方式的具体实现:
系统中提供3个servers,下面我们通过配置iptables使流量均衡访问这3台server。
# 随机:(Random balancing)
iptables -A PREROUTING -t nat -p tcp -d 192.168.1.1 --dport 27017 -m statistic --mode random --probability 0.33 -j DNAT --to-destination 10.0.0.2:1234
iptables -A PREROUTING -t nat -p tcp -d 192.168.1.1 --dport 27017 -m statistic --mode random --probability 0.5 -j DNAT --to-destination 10.0.0.3:1234
iptables -A PREROUTING -t nat -p tcp -d 192.168.1.1 --dport 27017 -j DNAT --to-destination 10.0.0.4:1234
rules说明:
第一条规则中,指定--probability 0.33 ,则说明该规则有33%的概率会命中,
第二条规则也有33%的概率命中,因为规则中指定 --probability 0.5。 则命中的概率为:50% * (1 - 33%)=0.33
第三条规则中,没有指定 --probability 参数,因此意味着当匹配走到第三条规则时,则一定命中,此时走到第三条规则的概率为:1 - 0.33 -0.33 ≈ 0.33。
由上可见,三条规则命中的几率一样的。此外,如果我们想修改三条规则的命中率,可以通过 --probability 参数调整。
假设有n个server,则可以设定n条rule将流量均分到n个server上,其中 --probability 参数的值可通过以下公式计算得到:
其中 i 代表规则的序号(第一条规则的序号为1)
n 代表规则/server的总数
p 代表第 i 条规则中 --probability 的参数值
p=1/(n−i+1)
注意:因为iptables中,规则是按顺序匹配的,由上至下依次匹配,因此设计iptables规则时,要严格对规则进行排序。因此上述三条规则的顺序也不可以调换,不然就无法实现LB均分了。
2.3、轮询方式
轮询算法中有两个参数:
n: 指每 n 个包
p:指第 p 个包
在规则中 n 和 p 代表着: 从第 p 个包开始,每 n 个包执行该规则。
这样可能有点绕口,直接看栗子吧:
还是上面的例子,有3个server,3个server轮询处理流量包,则规则配置如下:
#every:每n个包匹配一次规则
#packet:从第p个包开始
iptables -A PREROUTING -t nat -p tcp -d 192.168.1.1 --dport 27017 -m statistic --mode nth --every 3 --packet 0 -j DNAT --to-destination 10.0.0.2:1234
iptables -A PREROUTING -t nat -p tcp -d 192.168.1.1 --dport 27017 -m statistic --mode nth --every 2 --packet 0 -j DNAT --to-destination 10.0.0.3:1234
iptables -A PREROUTING -t nat -p tcp -d 192.168.1.1 --dport 27017 -j DNAT --to-destination 10.0.0.4:1234
3、IPVS
3.1、什么是IPVS
IPVS(IP虚拟服务器)实现传输层负载平衡,通常称为第4层LAN交换,是Linux内核的一部分。
IPVS在主机上运行,在真实服务器集群前充当负载均衡器。 IPVS可以将对基于TCP和UDP的服务的请求定向到真实服务器,并使真实服务器的服务在单个IP地址上显示为虚拟服务。
3.2、IPVS vs. IPTABLES
IPVS模式在Kubernetes v1.8中引入,并在v1.9中进入了beta。 IPTABLES模式在v1.1中添加,并成为自v1.2以来的默认操作模式。 IPVS和IPTABLES都基于netfilter。 IPVS模式和IPTABLES模式之间的差异如下:
- IPVS为大型集群提供了更好的可扩展性和性能。
- IPVS支持比iptables更复杂的负载平衡算法(最小负载,最少连接,位置,加权等)。
- IPVS支持服务器健康检查和连接重试等。
我们都知道,在Linux 中iptables设计是用于防火墙服务的,对于比较少规则的来说,没有太多的性能影响。但是对于,一个K8S集群来说,会有上千个Services服务,当然也会转发到Pods,每个都是一条iptables规则,对集群来说,每个node上会有大量的iptables规则,简直是噩梦。
同样IPVS可以解决可能也会遇见这样大规模的网络转发需求,但是IPVS用hash tabels来存储网络转发规则,比iptables 在这上面更有优势,而且它主要工作在kernelspace,减少了上下文切换带来的开销。
3.3、IPVS负载步骤
kube-proxy和IPVS在配置网络转发中,有这么几步:
- 通过watching kubernetes集群 cluster API, 获取新建、删除Services或者Endpoint Pod指令,有新的Service建立,kube-proxy回调网络接口,构建IPVS规则。
- 同时,kube-proxy会定期同步 Services和backend Pods的转发规则,确保失效的转发能被更新修复。
- 有请求转发到后端的集群时,IPVS的负载均衡直接转发到backend Pod。
3.4、IPVS负载算法
IPVS支持的负载均衡算法有这么几种:
- rr: 轮询
- lc: 最小连接数
- dh: 目的地址hash
- sh: 源地址hash
- sed: 最短期望延迟
- nq: 无须队列等待
在node上通过 “–ipvs-scheduler”参数,指定kube-proxy的启动算法。
转载自:https://juejin.cn/post/7380513228047188004