kube-proxy 是一层代理,主要用于实现 Service 这个 Object。
Service 有一个 ClusterIP,这是一个虚拟 IP 应对 Service 后面的 pod,pod 的销毁和创建会有 ip 不固定的问题。除了能够屏蔽后端的 pod 的 IP 之外,Service 还可以有负载均衡的作用。
Endpoint 维护的是 Service 和 Pod 的映射关系,如果 pods 变动,Endpoint 也会变动。Service 本身指定义了 ClusterIP 和 port 的映射。Endpoints 记录了 pod 的 ip 和端口。
主要的访问方式是通过 NAT 实现的,如果使用 iptables 的话,就设置匹配目标端口以后,DNAT 转发到目的地址。
我看代码的时候,发现有个函数叫 birth cry 挺有意思的,表示打程序启动的一条 log。
Kube-proxy 主要监听两个对象,一个是 Service,一个是 Endpoint
这些 Objects 对应的处理函数有不同的实现,现在先看一下 iptables 的实现
当 Service 有更新的时候就会更新对应的 iptables 规则。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| func (c *ServiceConfig) Run(stopCh <-chan struct{}) { defer utilruntime.HandleCrash()
glog.Info("Starting service config controller") defer glog.Info("Shutting down service config controller")
if !controller.WaitForCacheSync("service config", stopCh, c.listerSynced) { return }
for i := range c.eventHandlers { glog.V(3).Infof("Calling handler.OnServiceSynced()") c.eventHandlers[i].OnServiceSynced() }
<-stopCh }
|
会调用 OnServiceSynced,然后具体调用实现者的方法。
Proxier
Netfilter
Netfilter 是内核模块的控制代码,ipvs 和 iptables 都是基于 Netfilter 实现的。
iptables
用 iptables 配置 DNAT ,然后再用概率模块做负载均衡。kube-proxy iptables 的实现主要依赖于 filter 和 nat。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| # Masquerade -A KUBE-MARK-DROP -j MARK --set-xmark 0x8000/0x8000 -A KUBE-MARK-MASQ -j MARK --set-xmark 0x4000/0x4000 -A KUBE-POSTROUTING -m comment --comment "kubernetes service traffic requiring SNAT" -m mark --mark 0x4000/0x4000 -j MASQUERADE
# clusterIP and publicIP -A KUBE-SERVICES ! -s 10.244.0.0/16 -d 10.98.154.163/32 -p tcp -m comment --comment "default/nginx: cluster IP" -m tcp --dport 80 -j KUBE-MARK-MASQ -A KUBE-SERVICES -d 10.98.154.163/32 -p tcp -m comment --comment "default/nginx: cluster IP" -m tcp --dport 80 -j KUBE-SVC-4N57TFCL4MD7ZTDA -A KUBE-SERVICES -d 12.12.12.12/32 -p tcp -m comment --comment "default/nginx: loadbalancer IP" -m tcp --dport 80 -j KUBE-FW-4N57TFCL4MD7ZTDA
# Masq for publicIP -A KUBE-FW-4N57TFCL4MD7ZTDA -m comment --comment "default/nginx: loadbalancer IP" -j KUBE-MARK-MASQ -A KUBE-FW-4N57TFCL4MD7ZTDA -m comment --comment "default/nginx: loadbalancer IP" -j KUBE-SVC-4N57TFCL4MD7ZTDA -A KUBE-FW-4N57TFCL4MD7ZTDA -m comment --comment "default/nginx: loadbalancer IP" -j KUBE-MARK-DROP
# Masq for nodePort -A KUBE-NODEPORTS -p tcp -m comment --comment "default/nginx:" -m tcp --dport 30938 -j KUBE-MARK-MASQ -A KUBE-NODEPORTS -p tcp -m comment --comment "default/nginx:" -m tcp --dport 30938 -j KUBE-SVC-4N57TFCL4MD7ZTDA
# load balance for each endpoints -A KUBE-SVC-4N57TFCL4MD7ZTDA -m comment --comment "default/nginx:" -m statistic --mode random --probability 0.33332999982 -j KUBE-SEP-UXHBWR5XIMVGXW3H -A KUBE-SVC-4N57TFCL4MD7ZTDA -m comment --comment "default/nginx:" -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-TOYRWPNILILHH3OR -A KUBE-SVC-4N57TFCL4MD7ZTDA -m comment --comment "default/nginx:" -j KUBE-SEP-6QCC2MHJZP35QQAR
# endpoint -A KUBE-SEP-6QCC2MHJZP35QQAR -s 10.244.3.4/32 -m comment --comment "default/nginx:" -j KUBE-MARK-MASQ -A KUBE-SEP-6QCC2MHJZP35QQAR -p tcp -m comment --comment "default/nginx:" -m tcp -j DNAT --to-destination 10.244.3.4:80
# endpoint -A KUBE-SEP-TOYRWPNILILHH3OR -s 10.244.2.4/32 -m comment --comment "default/nginx:" -j KUBE-MARK-MASQ -A KUBE-SEP-TOYRWPNILILHH3OR -p tcp -m comment --comment "default/nginx:" -m tcp -j DNAT --to-destination 10.244.2.4:80
# endpoint -A KUBE-SEP-UXHBWR5XIMVGXW3H -s 10.244.1.2/32 -m comment --comment "default/nginx:" -j KUBE-MARK-MASQ -A KUBE-SEP-UXHBWR5XIMVGXW3H -p tcp -m comment --comment "default/nginx:" -m tcp -j DNAT --to-destination 10.244.1.2:80
|
这是一个实例,首先通过 clusterIP 的 -d 匹配目的地址,还有 dport 匹配目的端口,转入对应的 SVC 链。
SVC 联通过 -m statistic 模块负载均衡到不同的 Endpoint 链上,每个 Endpoint 链又有一个 DNAT 到对应的 pod
的 IP:port 上,总的来说就是用 DNAT 实现 clusterIP 的代理,用 statistic 模块实现按概率的负载均衡(按概率进入不同的 Endpoint 链当中)。
ipvs
ipvs 有相对更好的性能,更复杂的负载均衡的算法以及健康状态检查等。
可以看到 kube-ipvs0 上的 10.102.128.4 对应的 Service 的 ClusterIP,而 RealServer 映射到了不同的 Endpoint 上。
iptables 的匹配是 hash 的,而不同根据一个链一个链的匹配,效率更高。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| # kubectl describe svc nginx-service Name: nginx-service ... Type: ClusterIP IP: 10.102.128.4 Port: http 3080/TCP Endpoints: 10.244.0.235:8080,10.244.1.237:8080 Session Affinity: None
# ip addr ... 73: kube-ipvs0: <BROADCAST,NOARP> mtu 1500 qdisc noop state DOWN qlen 1000 link/ether 1a:ce:f5:5f:c1:4d brd ff:ff:ff:ff:ff:ff inet 10.102.128.4/32 scope global kube-ipvs0 valid_lft forever preferred_lft forever
# ipvsadm -ln IP Virtual Server version 1.2.1 (size=4096) Prot LocalAddress:Port Scheduler Flags -> RemoteAddress:Port Forward Weight ActiveConn InActConn TCP 10.102.128.4:3080 rr -> 10.244.0.235:8080 Masq 1 0 0 -> 10.244.1.237:8080 Masq 1 0 0
|