微信公众号:LinuGo,欢送关注
Pod是怎么找到申请的Pod的,pod之间又是怎么负载平衡的(iptables模式下)
想晓得这个问题,首先须要理解一些iptables常识。
iptables常识
五条链
iptables是linux内核集成的IP信息过滤规定,负责将发往主机的网络包进行散发,转换等。当客户端申请服务器的某个服务时,申请信息会先通过网卡进入服务器内核,这时iptables会对包进行过滤,决定这些包是发往用户态的服务过程或是转发进来到别的主机。而决定这些门路的形式在iptables中称为链,刚进入内核的申请流会通过PREROUTING链,依据路由规定判断是是不是发往本机申请,是则走INPUT链进入本机用户态过程,否则会走FORWARD链并匹配对应的规定最初流出本机;如果是本机收回的申请会走OUTPUT链并进一步到POSTROUTINE链流出本机,或转发到其余机器或回复信息给客户端。
总结上述几条链:
- PREROUTINE:流入本机路由前
- POSTROUTINE:流出本机路由前
- FORWARD:转发门路
- OUTPUT:由本机用户程序收回的
- INPUT:发送至本机用户程序的
两个动作
SNAT
源地址转换,是指将报文发送方的ip地址转换,这样当相应方回复申请时,回复的是发送方的地址。
示例了解
当client发送申请给server时,须要通过gateway,如果gateway不对包进行源地址转换(SNAT),发往server的网络包携带的源地址仍然是client,server会对该源地址响应,但client并不辨认server的地址,会导致该条申请呈现谬误。
DNAT
指标地址转换,是将报文的指标地址转换,起到申请转发到别的目的地的作用。
k8s基础知识
上面理解k8s中的几种IP类型。
虚构IP
虚IP(下文称VIP)有ClusterIP(即serviceIP),是集群本人生成的,ping不通,并和PodIP不处于同一网段,防止申请产生凌乱。当创立一个service时,k8s会为该service指派一个IP地址,并会被集群中的所有kube-proxy察看到,kube-proxy从而会装置一系列的iptables规定到宿主机,kube-dns也会相应的插入一条域名解析IP的规定。申请到来的时候,如果合乎规定,iptables会将VIP转化为理论的IP并应用。
理论IP
实IP别离有PodIP等,该IP是由CNI插件调配的,在k8s集群启动时候,须要装置CNI插件,通常是一个DaemonSet控制器管制,保障每台节点都有该过程。他的作用是在集群外部产生一套网络,并给每个pod插上”网线”,保障pod与节点,pod与pod是互通的。
Pod之间通信的形式能够通过理论的PodIP,然而该IP会随着pod的变动而变动,不适宜用该形式,也能够通过ClusterIP的形式通信,比较稳定,然而不容易被记住,还能够通过svc.ns这种域名的格局,该办法申请kube-dns域名解析失去域名对应的IP。
案例学习
接下来依据一个案例探讨一下。
案例介绍
- 集群中有两个gateway-pod,service类型为NodePort,裸露端口给集群内部,接管外界申请并负载平衡,并将申请转发到上游pod。
- 有一个basedao pod,负责接管gateway pod发来的申请并响应,对应的service名称是sts-basedao,命名空间名称是basedao。
- Kube-dns pod将域名解析成IP地址,并返回给发送方。
查看一下各个pod的IP,该IP是理论的IP。
[centos@guozhao-50 ~]$ kubectl get pod --all-namespaces -owideNAMESPACE NAME IP basedao sts-basedao-0 10.34.0.2gateway sts-gateway-59d5fdbc54-4d6kv 10.40.0.0gateway sts-gateway-59d5fdbc54-dmncq 10.34.0.1 kube-system coredns-6c76c8bb89-kztxk 10.32.0.4
查看一下三种pod对应service的IP,能够看到gateway service代理的30001端口映射到了内部的31001端口。
[centos@guozhao-50 ~]$ kubectl get svc --all-namespacesNAMESPACE NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGEbasedao svc-basedao ClusterIP 10.111.143.223 <none> 30003/TCP 70mgateway svc-gateway NodePort 10.102.103.1 <none> 30001:31001/TCP 70mkube-system kube-dns ClusterIP 10.96.0.10 <none> 53/UDP,53/TCP,9153/TCP 14d
1.client发动申请
通过iptables-save命令能够查看到所有的iptables规定。
当client发动申请时,会申请服务器对应的端口,对应NodePort端口,咱们来查看对应的iptables规定,会通过PREROUTING,跳转到KUBE-SERVICES规定。
-A PREROUTING -m comment --comment "kubernetes service portals" -j KUBE-SERVICES
在KUBE-SERVICE中找到合乎的规定,--dst-type LOCAL 代表本地,会持续跳转到KUBE-NODEPORTS
-A KUBE-SERVICES -m comment --comment "kubernetes service nodeports; NOTE: this must be the last rule in this chain" -m addrtype --dst-type LOCAL -j KUBE-NODEPORTS
该申请会跳转到KUBE-MARK-MASQ给申请打一个标签,并跳转到下一条规定KUBE-SVC-4QJQIYWH2AWK2TSA。
-A KUBE-NODEPORTS -p tcp -m comment --comment "gateway/svc-gateway:gateway-port" -m tcp --dport 31001 -j KUBE-MARK-MASQ-A KUBE-NODEPORTS -p tcp -m comment --comment "gateway/svc-gateway:gateway-port" -m tcp --dport 31001 -j KUBE-SVC-4QJQIYWH2AWK2TSA
负载平衡
追随上条规定有两条规定与其对应,--probability 0.50000000000代表有0.5的概率进入下面的规定,如果没有进入下面规定,就会进入上面的规定,负载平衡也就是在iptables层面实现的。
-A KUBE-SVC-4QJQIYWH2AWK2TSA -m comment --comment "gateway/svc-gateway:gateway-port" -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-XEQTQPKSTZECBET2-A KUBE-SVC-4QJQIYWH2AWK2TSA -m comment --comment "gateway/svc-gateway:gateway-port" -j KUBE-SEP-OCFEUGRRJNZZEOHZ
别离查看两个规定对应的下一条规定,该规定指定了指标地址,执行了DNAT操作进行指标地址转发,别离对应了两个pod实例的理论IP地址,申请会追随这条规定转发到理论的gateway。
-A KUBE-SEP-XEQTQPKSTZECBET2 -p tcp -m comment --comment "gateway/svc-gateway:gateway-port" -m tcp -j DNAT --to-destination 10.34.0.1:30001-A KUBE-SEP-OCFEUGRRJNZZEOHZ -p tcp -m comment --comment "gateway/svc-gateway:gateway-port" -m tcp -j DNAT --to-destination 10.40.0.0:30001
在最终发出请求之前会走POSTROUTING链,会对该申请做一个SNAT操作,MASQUERADE代表执行了SNAT操作批改了申请源地址。
-A POSTROUTING -m comment --comment "kubernetes postrouting rules" -j KUBE-POSTROUTING-A KUBE-POSTROUTING -m comment --comment "kubernetes service traffic requiring SNAT" -j MASQUERADE
2.gateway发动申请
此时gateway收到了来自client的申请,他会向basedao发动申请,申请形式是通过域名即sts-basedao.basedao:30002格局。该申请会发送给dns服务器进行解析返回一个理论IP地址,当然,该地址也是一个VIP。
在pod被创立时候,就会在pod中创立dns服务配置文件,nameserver代表dns服务器的IP地址,默认是集群中的kube-dns地址,search代表域名拼接规定。能够看出,该地址和kube-dns的VIP是雷同的。
接下来该pod会发出请求到kube-dns的VIP
因为是在主机上收回,会走OUTPUT链,进而进入到KUBE-SERVICES
-A OUTPUT -m comment --comment "kubernetes service portals" -j KUBE-SERVICES
满足KUBE-SERVICES的该条规定,持续跳转到KUBE-SVC-ERIFXISQEP7F7OF4,再次跳转到KUBE-SEP-ZT5TVM6PMFDFQAMO。
-A KUBE-SERVICES -d 10.96.0.10/32 -p tcp -m comment --comment "kube-system/kube-dns:dns-tcp cluster IP" -m tcp --dport 53 -j KUBE-SVC-ERIFXISQEP7F7OF4-A KUBE-SVC-ERIFXISQEP7F7OF4 -m comment --comment "kube-system/kube-dns:dns-tcp" -j KUBE-SEP-ZT5TVM6PMFDFQAMO
最终进行DNAT指标地址转发到dns理论的pod,最终dns返回给gateway由域名解析到的ip。
-A KUBE-SEP-ZT5TVM6PMFDFQAMO -p tcp -m comment --comment "kube-system/kube-dns:dns-tcp" -m tcp -j DNAT --to-destination 10.32.0.4:53
当gateway失去实在的IP,该IP就是basedao的VIP,gateway会应用该VIP发动申请,仍然会对应到相应的iptables规定,实现VIP到IP的映射失去basedao pod的理论地址,并向理论地址发送数据包,这里便不再赘述。
总结
因为Pod的IP地址不是长久的,所以尽量倡议采纳ClusterIP或者域名的形式申请集群中的其余pod,而这两种形式是通过Linux内核的iptables规定实现的。应用iptables规定也有毛病,当集群中有过多的服务Pod,相应的各台宿主机iptables规定就会减少,这减少了网络的复杂度与跟踪难度,会给前期运维带来肯定的艰难。
参考文章
- 《iptables详解》http://www.zsythink.net/archives/1199
- 《k8s中文文档》https://v1-16.docs.kubernetes.io/zh/
- 《深刻分析Kubernetes》极客工夫