vxlan配置实例详解 vxlan配置实例详解思科
IPVS从入门到精通kube-proxy实现原理(转)
由前面的理论知识,ipvs的VIP必须在本地存在,我们可以验证:我们知道容器的特点是快速创建、快速销毁,Kubernetes Pod和容器一样只具有临时的生命周期,一个Pod随时有可能被终止或者漂移,随着集群的状态变化而变化,一旦Pod变化,则该Pod提供的服务也就无法访问,如果直接访问Pod则无法实现服务的连续性和高可用性,因此显然不能使用Pod地址作为服务暴露端口。
vxlan配置实例详解 vxlan配置实例详解思科
vxlan配置实例详解 vxlan配置实例详解思科
067 - Neutron 架构
解决这个问题的办法和传统数据中心解决无状态服务高可用的思路完全一样,通过负载均衡和VIP实现后端真实服务的自动转发、故障转移。
这个负载均衡在Kubernetes中称为Serv,VIP即Serv ClusterIP,因此可以认为Kubernetes的Serv就是一个四层负载均衡,Kubernetes对应的还有七层负载均衡Ingress,本文仅介绍Kubernetes Serv。
这个Serv就是由kube-proxy实现的,ClusterIP不会因为Podz状态改变而变,需要注意的是VIP即ClusterIP是个的IP,这个IP在整个集群中根本不存在,当然也就无法通过IP协议栈无法路由,底层underlay设备更无法感知这个IP的存在,因此ClusterIP只能是单主机(Host Only)作用域可见,这个IP在其他以及集群外均无法访问。
Kubernetes为了实现在集群所有的都能够访问Serv,kube-proxy默认会在所有的Node都创建这个VIP并且实现负载,所以在部署Kubernetes后发现kube-proxy是一个DaemonSet。
而Serv负载之所以能够在Node上实现是因为无论Kubernetes使用哪个网络模型,均需要保证满足如下三个条件:
至少第2点是必须满足的,有了如上几个设,Kubernetes Serv才能在Node上实现,否则Node不通Pod IP也就实现不了了。
有人说既然kube-proxy是四层负载均衡,那kube-proxy应该可以使用haproxy、nginx等作为负载后端啊?
事实上确实没有问题,不过需要考虑的就是性能问题,如上这些负载均衡功能都强大,但毕竟还是基于用户态转发或者反向实现的,性能必然不如在内核态直接转发处理好。
因此kube-proxy默认会优先选择基于内核态的负载作为后端实现机制,目前kube-proxy默认是通过iptables实现负载的,在此之前还有一种称为userspace模式,其实也是基于iptables实现,可以认为当前的iptables模式是对之前userspace模式的优化。
本节接下来将详细介绍kube-proxy iptables模式的实现原理。
首先创建了一个ClusterIP类型的Serv:
其中ClusterIP为10.106.224.41,我们可以验证这个IP在本地是不存在的:
所以 不要尝试去ping ClusterIP,它不可能通的 。
此时在Node192.168.193.172问该Serv服务,首先流量到达的是OUTPUT链,这里我们只关心nat表的OUTPUT链:
该链跳转到 KUBE-SERVICES 子链中:
我们发现与之相关的有两条规则:
其中 KUBE-SVC-RPP7DHNHMGOIIFDC 子链规则如下:
这几条规则看起来复杂,其实实现的功能很简单:
我们查看其中一个子链 KUBE-SEP-FTIQ6MSD3LWO5HZX 规则:
由此可见子链 KUBE-SVC-RPP7DHNHMGOIIFDC 的功能就是按照概率均等的原则DNAT到其中一个Endpoint IP,即Pod IP,设为10.244.1.2,
此时相当于:
接着来到POSTROUTING链:
这两条规则只做一件事就是只要标记了 0x4000/0x4000 的包就一律做MASQUERADE(SNAT),由于10.244.1.2默认是从flannel.1转发出去的,因此会把源IP改为flannel.1的IP 10.244.0.0 。
剩下的就是常规的走Vxlan隧道转发流程了,这里不再赘述,感兴趣的可以参考我之前的文章 浅聊几种主流Docker网络的实现原理 。
接下来研究下NodePort过程,首先创建如下Serv:
其中Serv的NodePort端口为30419。
设有一个外部IP 192.168.193.197,通过 192.168.193.172:30419 访问服务。
首先到达PREROUTING链:
PREROUTING的规则非常简单,凡是发给自己的包,则交给子链 KUBE-NODEPORTS 处理。注意前面省略了判断ClusterIP的部分规则。
KUBE-NODEPORTS 规则如下:
这个规则首先给包打上标记 0x4000/0x4000 ,然后交给子链 KUBE-SVC-RPP7DHNHMGOIIFDC 处理, KUBE-SVC-RPP7DHNHMGOIIFDC 刚刚已经见面过了,其功能就是按照概率均等的原则DNAT到其中一个Endpoint IP,即Pod IP,设为10.244.1.2。
此时发现10.244.1.2不是自己的IP,于是经过路由判断目标为10.244.1.2需要从flannel.1发出去。
FORWARD表在这里只是判断下,只允许打了标记 0x4000/0x4000 的包才允许转发。
来到 POSTROUTING 链,这里和ClusterIP就完全一样了,在 KUBE-POSTROUTING 中 MASQUERADE (SNAT),结果:
我们发现基于iptables模式的kube-proxy ClusterIP和NodePort都是基于iptables规则实现的,我们至少发现存在如下几个问题:
本文接下来将介绍kube-proxy的ipvs实现,由于本人之前也是对ipvs很陌生,没有用过,专门学习了下ipvs,因此在第二章简易介绍了下ipvs,如果已经很熟悉ipvs了,可以直接跳过,这一章和Kubernetes几乎没有任何关系。
另外由于本人对ipvs也是初学,水平有限,难免出错,欢迎指正!
我们接触比较多的是应用层负载均衡,比如haproxy、nginx、F5等,这些负载均衡工作在用户态,因此会有对应的进程和socket,一般能同时支持4层负载和7层负载,使用起来也比较方便。
LVS是国内章文嵩博士开发并贡献给社区的(章文嵩博士和他背后的负载均衡帝国 ),主要由ipvs和ipvsadm组成,ipvs是工作在内核态的4层负载均衡,和iptables一样都是基于内核底层netfilter实现,netfilter主要通过各个链的钩子实现包处理和转发。ipvsadm和ipvs的关系,就好比netfilter和iptables的关系,它运行在用户态,提供简单的CLI接口进行ipvs配置。
由于ipvs工作在内核态,直接基于内核处理包转发,所以的特点就是性能非常好。又由于它工作在4层,因此不会处理应用层数据,经常有人问ipvs能不能做SSL证书卸载、或者修改HTTP头部数据,显然这些都不可能做的。
我们知道应用层负载均衡大多数都是基于反向实现负载的,工作在应用层,当用户的包到达负载均衡listening后,基于一定的算法从后端服务列表中选择其中一个后端服务进行转发。当然中间可能还会有一些额外作,最常见的如SSL证书卸载。
而ipvs工作在内核态,只处理四层协议,因此只能基于路由或者NAT进行数据转发,可以把ipvs当作一个特殊的路由器,这个可以根据一定的算法自动选择下一跳,或者把ipvs当作一个多重DNAT,按照一定的算法把ip包的目标地址DNAT到其中真实服务的目标IP。针对如上两种情况分别对应ipvs的两种模式--模式和NAT模式,另外ipip模式则是对模式的扩展,本文下面会针对这几种模式的实现原理进行详细介绍。
ipvsadm命令行用法和iptables命令行用法非常相似,毕竟是兄弟,比如 -L 列举, -A 添加, -D 删除。
如下命令创建一个serv实例 172.17.0.1:32016 , -t 指定的为 TCP 端口, -s 指定算法为轮询算法rr(Round Robin),ipvs支持简单轮询(rr)、加权轮询(wrr)、最少连接(lc)、源地址或者目标地址散列(sh、dh)等10种调度算法。
然后把10.244.1.2:8080、10.244.1.3:8080、10.244.3.2:8080添加到serv后端member中。
其中 -t 指定serv实例, -r 指定server地址, -w 指定权值, -m 即前面说的转发模式,其中 -m 表示为 masquerading ,即NAT模式, -g 为 gatewaying ,即直连路由模式, -i 为 ipip ,ji即IPIP隧道模式。
NAT模式由字面意思理解就是通过NAT实现的,但究竟是如何NAT转发的,我们通过实验环境验证下。
现环境中LBIP为192.168.193.197,三个RS如下:
为了模拟LBIP和RS不在同一个网络的情况,在LB中添加一个虚拟IP地址:
这里需要注意的是,和应用层负载均衡如haproxy、nginx不一样的是,haproxy、nginx进程是运行在用户态,因此会创建socket,本地会端口,而 ipvs的负载是直接运行在内核态的,因此不会出现端口 :
IP为192.168.193.226,为了和LB的虚拟IP 10.222.0.1通,我们手动添加静态路由如下:
此时能够ping通LBVIP:
可见到VIP的链路没有问题,那是否能够访问我们的Serv呢?
我们验证下:
非常意外的结果是并不通。
在RS抓包如下:
我们发现数据包的源IP为 IP,目标IP为RS IP,换句话说,LBIPVS只做了DNAT,把目标IP改成RS IP了,而没有修改源IP。此时虽然RS和在同一个子网,链路连通性没有问题,但是由于发出去的包的目标IP和收到的包源IP不一致,因此会被直接丢弃,相当于给张三发信,李四回的信,显然不受信任。
既然IPVS没有给我们做SNAT,那自然想到的是我们手动做SNAT,在LB添加如下iptables规则:
再次检查Serv是否可以访问:
服务依然不通。并且在LB的iptables日志为空:
那mangle表呢?我们打开LOG查看下:
此时查看日志如下:
我们发现在mangle表中可以看到DNAT后的包。
只是mangle表的POSTROUTING并不支持NAT功能:
对比Kubernetes配置发现需要设置如下系统参数:
再次验证:
终于通了,查看RS抓包:
如期望,修改了源IP为LB IP。
原来需要配置 net.ipv4.vs.conntrack=1 参数,这个问题折腾了一个晚上,不得不说目前ipvs的文档都太老了。
前面是通过手动iptables实现SNAT的,性能可能会有损耗,于是如下开源项目通过修改lvs直接做SNAT:
除了SNAT的办法,是否还有其他办法呢?想想我们最初的问题,发出去的包的目标IP和收到的包源IP不一致导致包被丢弃,那解决问题的办法就是把包重新引到LB上,只需要在所有的RS增加如下路由即可:
此时我们再次检查我们的Serv是否可连接:
结果没有问题。
不过我们是通过手动添加 IP到所有RS的明细路由实现的,如果不固定,这种方案仍然不太可行,所以通常做法是干脆把所有RS默认路由指向LB,即把LB当作所有RS的默认。
由此可知,用户通过LB地址访问服务,LBIPVS会把用户的目标IP由LB IP改为RS IP,源IP不变,包不经过iptables的OUTPUT直接到达POSTROUTING转发出去,包回来的时候也必须先到LB,LB把目标IP再改成用户的源IP,转发给用户。
显然这种模式来回都需要经过LB,因此又称为双臂模式。
模式(Gatewaying)又称为直连路由模式(Direct Routing)、透传模式, 所谓透传即LB不会修改数据包的源IP、端口以及目标IP、端口 ,LB做的仅仅是路由转发出去,可以把LB看作一个特殊的路由器,而RS则是的下一跳,这就相当于对于同一个目标地址,会有多个下一跳,这个路由器的特殊之处在于能够根据一定的算法选择其中一个RS作为下一跳,达到负载均衡和冗余的效果。
既然是通过直连路由的方式转发,那显然LB必须与所有的RS在同一个子网,不能跨子网,否则路由不可达。换句话说, 这种模式只支持内部负载均衡(Internal LoadBalancer) 。
另外如前面所述,LB不会修改源端口和目标端口,因此这种模式也无法支持端口映射,换句话说 LB的端口和所有RS的端口必须一致 。
现在设有LBIP为 192.168.193.197 ,有三个RS如下:
注意到我们的Serv的端口30620和RS的端口是一样的,并且通过 -g 参数指定为直连路由模式(模式)。
IP为192.168.193.226,我们验证Serv是否可连接:
我们发现并不通,在其中一个RS192.168.193.172上抓包:
正如前面所说,LB是通过路由转发的,根据路由的原理,源MAC地址修改为LB的MAC地址,而目标MAC地址修改为RS MAC地址,相当于RS是LB的下一跳。
并且源IP和目标IP都不会修改。问题就来了,我们期望访问的是RS,但RS收到的目标IP却是LB的IP,发现这个目标IP并不是自己的IP,因此不会通过INPUT链转发到用户空间,这时要不直接丢弃这个包,要不根据路由再次转发到其他地方,总之两种情况都不是我们期望的结果。
那怎么办呢?为了让RS接收这个包,必须得让RS有这个目标IP才行。于是不妨在lo上添加个虚拟IP,IP地址伪装成LB IP 192.168.193.197:
此时再次从客户端c:
终于通了。
我们从前面的抓包中知道,源IP为 IP 192.168.193.226,因此直接回包给即可,不可能也不需要再回到LB了,即A->B,B->C,C->A,流量方向是三角形状的,因此这种模式又称为三角模式。
我们从原理中不难得出如下结论:
前面介绍了直连路由模式,要求所有的在同一个子网,而ipip隧道模式则主要解决这种限制,LBIP和RS可以不在同一个子网,此时需要通过ipip隧道进行传输。
现在设有LBIP为 192.168.193.77/25 ,在该上增加一个VIP地址:
有三个RS如下:
如上三个RS子网掩码均为255.255.255.128,即25位子网,显然和VIP 192.168.193.48/25不在同一个子网。
注意到我们的Serv的端口30620和RS的端口是一样的,并且通过 -i 参数指定为ipip隧道模式。
Serv可访问,我们在RS上抓包如下:
我们发现和直连路由一样,源IP和目标IP没有修改。
所以IPIP模式和(Gatewaying)模式原理基本一样,不同的是(Gatewaying)模式要求所有的RS和LB在同一个子网,而IPIP模式则可以支持跨子网的情况,为了解决跨子网通信问题,使用了ipip隧道进行数据传输。
ipvs是一个内核态的四层负载均衡,支持NAT、Gateway以及IPIP隧道模式,Gateway模式性能,但LB和RS不能跨子网,IPIP性能次之,通过ipip隧道解决跨网段传输问题,因此能够支持跨子网。而NAT模式没有限制,这也是一种支持端口映射的模式。
我们不难猜想,由于Kubernetes Serv需要使用端口映射功能,因此kube-proxy必然只能使用ipvs的NAT模式。
需要修改为如下配置:
可以通过如下命令确认kube-proxy是否修改为ipvs:
创建一个ClusterIP类似的Serv如下:
ClusterIP 10.96.54.11为我们查看ipvs配置如下:
可见ipvs的LB IP为ClusterIP,算法为rr,RS为Pod的IP。
另外我们发现使用的模式为NAT模式,这是显然的,因为除了NAT模式支持端口映射,其他两种均不支持端口映射,所以必须选择NAT模式。
可见kube-proxy首先会创建一个dummy虚拟网卡kube-ipvs0,然后把所有的Serv IP添加到kube-ipvs0中。
我们知道基于iptables的Serv,ClusterIP是一个虚拟的IP,因此这个IP是ping不通的,但ipvs中这个IP是在每个上真实存在的,因此可以ping通:
当然由于这个IP就是配置在本地虚拟网卡上,所以对诊断问题没有一点用处的。
我们接下来研究下ClusterIP如何传递的。
当我们通过如下命令连接服务时:
此时由于10.96.54.11就在本地,所以会以这个IP作为出口地址,即源IP和目标IP都是10.96.54.11,此时相当于:
其中xxxx为随机端口。
然后经过ipvs,ipvs会从RS ip列中选择其中一个Pod ip作为目标IP,设为10.244.2.2:
我们从iptables LOG可以验证:
我们查看OUTPUT安全组规则如下:
其中ipset KUBE-CLUSTER-IP 保存着所有的ClusterIP以及端口。
如上规则的意思就是除了Pod以外访问ClusterIP的包都打上 0x4000/0x4000 。
如上规则的意思就是只要匹配mark 0x4000/0x4000 的包都做SNAT,由于10.244.2.2是从flannel.1出去的,因此源ip会改成flannel.1的ip 10.244.0.0 :
通过Vxlan 隧道发到Pod的Node上,转发给Pod的v,回包通过路由到达源Node,源Node通过之前的MASQUERADE再把目标IP还原为10.96.54.11。
查看Serv如下:
现在设集群外的一个IP 192.168.193.197访问192.168.193.172:32016:
到达PREROUTING链:
如上4条规则看起来复杂,其实就做一件事,如果目标地址为NodeIP,则把包标记 0x4000 , 0x4000 。
我们查看ipvs:
我们发现和ClusterIP实现原理非常相似,ipvs Serv的VIP为Node IP,端口为NodePort。ipvs会选择其中一个Pod IP作为DNAT目标,这里设为10.244.3.2:
Kubernetes的ClusterIP和NodePort都是通过ipvs serv实现的,Pod当作ipvs serv的server,通过NAT MQSQ实现转发。
简单来说kube-proxy主要在所有的Node做如下三件事:
使用ipvs作为kube-proxy后端,不仅提高了转发性能,结合ipset还使iptables规则变得更“干净”清楚,从此再也不怕iptables。
更多关于kube-proxy ipvs参考IPVS-Based In-Cluster Load Balancing Deep Dive.
本文首先介绍了kube-proxy的功能以及kube-proxy基于iptables的实现原理,然后简单介绍了ipvs,了解了ipvs支持的三种转发模式,介绍了kube-proxy基于ipvs的实现原理。
ipvs是专门设计用来做内核态四层负载均衡的,由于使用了hash表的数据结构,因此相比iptables来说性能会更好。基于ipvs实现Serv转发,Kubernetes几乎能够具备无限的水平扩展能力。随着Kubernetes的部署规模越来越大,应用越来越广泛,ipvs必然会取代iptables成为Kubernetes Serv的默认实现后端。
IPVS从入门到精通kube-proxy实现原理
我们知道容器的特点是快速创建、快速销毁,Kubernetes Pod和容器一样只具有临时的生命周期,一个Pod随时有可能被终止或者漂移,随着集群的状态变化而变化,一旦Pod变化,则该Pod提供的服务也就无法访问,如果直接访问Pod则无法实现服务的连续性和高可用性,因此显然不能使用Pod地址作为服务暴露端口。
解决这个问题的办法和传统数据中心解决无状态服务高可用的思路完全一样,通过负载均衡和VIP实现后端真实服务的自动转发、故障转移。
这个负载均衡在Kubernetes中称为Serv,VIP即Serv ClusterIP,因此可以认为Kubernetes的Serv就是一个四层负载均衡,Kubernetes对应的还有七层负载均衡Ingress,本文仅介绍Kubernetes Serv。
这个Serv就是由kube-proxy实现的,ClusterIP不会因为Podz状态改变而变,需要注意的是VIP即ClusterIP是个的IP,这个IP在整个集群中根本不存在,当然也就无法通过IP协议栈无法路由,底层underlay设备更无法感知这个IP的存在,因此ClusterIP只能是单主机(Host Only)作用域可见,这个IP在其他以及集群外均无法访问。
Kubernetes为了实现在集群所有的都能够访问Serv,kube-proxy默认会在所有的Node都创建这个VIP并且实现负载,所以在部署Kubernetes后发现kube-proxy是一个DaemonSet。
而Serv负载之所以能够在Node上实现是因为无论Kubernetes使用哪个网络模型,均需要保证满足如下三个条件:
至少第2点是必须满足的,有了如上几个设,Kubernetes Serv才能在Node上实现,否则Node不通Pod IP也就实现不了了。
有人说既然kube-proxy是四层负载均衡,那kube-proxy应该可以使用haproxy、nginx等作为负载后端啊?
事实上确实没有问题,不过需要考虑的就是性能问题,如上这些负载均衡功能都强大,但毕竟还是基于用户态转发或者反向实现的,性能必然不如在内核态直接转发处理好。
因此kube-proxy默认会优先选择基于内核态的负载作为后端实现机制,目前kube-proxy默认是通过iptables实现负载的,在此之前还有一种称为userspace模式,其实也是基于iptables实现,可以认为当前的iptables模式是对之前userspace模式的优化。
本节接下来将详细介绍kube-proxy iptables模式的实现原理。
首先创建了一个ClusterIP类型的Serv:
其中ClusterIP为10.106.224.41,我们可以验证这个IP在本地是不存在的:
所以 不要尝试去ping ClusterIP,它不可能通的 。
此时在Node192.168.193.172问该Serv服务,首先流量到达的是OUTPUT链,这里我们只关心nat表的OUTPUT链:
该链跳转到 KUBE-SERVICES 子链中:
我们发现与之相关的有两条规则:
这几条规则看起来复杂,其实实现的功能很简单:
我们查看其中一个子链 KUBE-SEP-FTIQ6MSD3LWO5HZX 规则:
由此可见子链 KUBE-SVC-RPP7DHNHMGOIIFDC 的功能就是按照概率均等的原则DNAT到其中一个Endpoint IP,即Pod IP,设为10.244.1.2,
此时相当于:
接着来到POSTROUTING链:
这两条规则只做一件事就是只要标记了 0x4000/0x4000 的包就一律做MASQUERADE(SNAT),由于10.244.1.2默认是从flannel.1转发出去的,因此会把源IP改为flannel.1的IP 10.244.0.0 。
剩下的就是常规的走Vxlan隧道转发流程了,这里不再赘述,感兴趣的可以参考我之前的文章 浅聊几种主流Docker网络的实现原理 。
接下来研究下NodePort过程,首先创建如下Serv:
其中Serv的NodePort端口为30419。
设有一个外部IP 192.168.193.197,通过 192.168.193.172:30419 访问服务。
首先到达PREROUTING链:
PREROUTING的规则非常简单,凡是发给自己的包,则交给子链 KUBE-NODEPORTS 处理。注意前面省略了判断ClusterIP的部分规则。
KUBE-NODEPORTS 规则如下:
这个规则首先给包打上标记 0x4000/0x4000 ,然后交给子链 KUBE-SVC-RPP7DHNHMGOIIFDC 处理, KUBE-SVC-RPP7DHNHMGOIIFDC 刚刚已经见面过了,其功能就是按照概率均等的原则DNAT到其中一个Endpoint IP,即Pod IP,设为10.244.1.2。
此时发现10.244.1.2不是自己的IP,于是经过路由判断目标为10.244.1.2需要从flannel.1发出去。
接着到了 FORWARD 链,
FORWARD表在这里只是判断下,只允许打了标记 0x4000/0x4000 的包才允许转发。
来到 POSTROUTING 链,这里和ClusterIP就完全一样了,在 KUBE-POSTROUTING 中 MASQUERADE (SNAT),结果:
我们发现基于iptables模式的kube-proxy ClusterIP和NodePort都是基于iptables规则实现的,我们至少发现存在如下几个问题:
本文接下来将介绍kube-proxy的ipvs实现,由于本人之前也是对ipvs很陌生,没有用过,专门学习了下ipvs,因此在第二章简易介绍了下ipvs,如果已经很熟悉ipvs了,可以直接跳过,这一章和Kubernetes几乎没有任何关系。
另外由于本人对ipvs也是初学,水平有限,难免出错,欢迎指正!
我们接触比较多的是应用层负载均衡,比如haproxy、nginx、F5等,这些负载均衡工作在用户态,因此会有对应的进程和socket,一般能同时支持4层负载和7层负载,使用起来也比较方便。
LVS是国内章文嵩博士开发并贡献给社区的( 章文嵩博士和他背后的负载均衡帝国 ),主要由ipvs和ipvsadm组成,ipvs是工作在内核态的4层负载均衡,和iptables一样都是基于内核底层netfilter实现,netfilter主要通过各个链的钩子实现包处理和转发。ipvsadm和ipvs的关系,就好比netfilter和iptables的关系,它运行在用户态,提供简单的CLI接口进行ipvs配置。
由于ipvs工作在内核态,直接基于内核处理包转发,所以的特点就是性能非常好。又由于它工作在4层,因此不会处理应用层数据,经常有人问ipvs能不能做SSL证书卸载、或者修改HTTP头部数据,显然这些都不可能做的。
我们知道应用层负载均衡大多数都是基于反向实现负载的,工作在应用层,当用户的包到达负载均衡listening后,基于一定的算法从后端服务列表中选择其中一个后端服务进行转发。当然中间可能还会有一些额外作,最常见的如SSL证书卸载。
而ipvs工作在内核态,只处理四层协议,因此只能基于路由或者NAT进行数据转发,可以把ipvs当作一个特殊的路由器,这个可以根据一定的算法自动选择下一跳,或者把ipvs当作一个多重DNAT,按照一定的算法把ip包的目标地址DNAT到其中真实服务的目标IP。针对如上两种情况分别对应ipvs的两种模式–模式和NAT模式,另外ipip模式则是对模式的扩展,本文下面会针对这几种模式的实现原理进行详细介绍。
ipvsadm命令行用法和iptables命令行用法非常相似,毕竟是兄弟,比如 -L 列举, -A 添加, -D 删除。
但是其实ipvsadm相对iptables命令简直太简单了,因为没有像iptables那样存在各种table,table嵌套各种链,链里串着一堆规则,ipvsadm就只有两个核心实体,分别为serv和server,serv就是一个负载均衡实例,而server就是后端member,ipvs术语中叫做real server,简称RS。
然后把10.244.1.2:8080、10.244.1.3:8080、10.244.3.2:8080添加到serv后端member中。
其中 -t 指定serv实例, -r 指定server地址, -w 指定权值, -m 即前面说的转发模式,其中 -m 表示为 masquerading ,即NAT模式, -g 为 gatewaying ,即直连路由模式, -i 为 ipip ,ji即IPIP隧道模式。
NAT模式由字面意思理解就是通过NAT实现的,但究竟是如何NAT转发的,我们通过实验环境验证下。
现环境中LBIP为192.168.193.197,三个RS如下:
为了模拟LBIP和RS不在同一个网络的情况,在LB中添加一个虚拟IP地址:
这里需要注意的是,和应用层负载均衡如haproxy、nginx不一样的是,haproxy、nginx进程是运行在用户态,因此会创建socket,本地会端口,而 ipvs的负载是直接运行在内核态的,因此不会出现端口 :
IP为192.168.193.226,为了和LB的虚拟IP 10.222.0.1通,我们手动添加静态路由如下:
此时能够ping通LBVIP:
可见到VIP的链路没有问题,那是否能够访问我们的Serv呢?
我们验证下:
非常意外的结果是并不通。
在RS抓包如下:
我们发现数据包的源IP为 IP,目标IP为RS IP,换句话说,LBIPVS只做了DNAT,把目标IP改成RS IP了,而没有修改源IP。此时虽然RS和在同一个子网,链路连通性没有问题,但是由于发出去的包的目标IP和收到的包源IP不一致,因此会被直接丢弃,相当于给张三发信,李四回的信,显然不受信任。
既然IPVS没有给我们做SNAT,那自然想到的是我们手动做SNAT,在LB添加如下iptables规则:
再次检查Serv是否可以访问:
服务依然不通。并且在LB的iptables日志为空:
那mangle表呢?我们打开LOG查看下:
此时查看日志如下:
我们发现在mangle表中可以看到DNAT后的包。
只是可惜mangle表的POSTROUTING并不支持NAT功能:
对比Kubernetes配置发现需要设置如下系统参数:
再次验证:
终于通了,查看RS抓包:
如期望,修改了源IP为LB IP。
原来需要配置 net.ipv4.vs.conntrack=1 参数,这个问题折腾了一个晚上,不得不说目前ipvs的文档都太老了。
前面是通过手动iptables实现SNAT的,性能可能会有损耗,于是如下开源项目通过修改lvs直接做SNAT:
除了SNAT的办法,是否还有其他办法呢?想想我们最初的问题,发出去的包的目标IP和收到的包源IP不一致导致包被丢弃,那解决问题的办法就是把包重新引到LB上,只需要在所有的RS增加如下路由即可:
此时我们再次检查我们的Serv是否可连接:
结果没有问题。
不过我们是通过手动添加 IP到所有RS的明细路由实现的,如果不固定,这种方案仍然不太可行,所以通常做法是干脆把所有RS默认路由指向LB,即把LB当作所有RS的默认。
由此可知,用户通过LB地址访问服务,LBIPVS会把用户的目标IP由LB IP改为RS IP,源IP不变,包不经过iptables的OUTPUT直接到达POSTROUTING转发出去,包回来的时候也必须先到LB,LB把目标IP再改成用户的源IP,转发给用户。
显然这种模式来回都需要经过LB,因此又称为双臂模式。
模式(Gatewaying)又称为直连路由模式(Direct Routing)、透传模式, 所谓透传即LB不会修改数据包的源IP、端口以及目标IP、端口 ,LB做的仅仅是路由转发出去,可以把LB看作一个特殊的路由器,而RS则是的下一跳,这就相当于对于同一个目标地址,会有多个下一跳,这个路由器的特殊之处在于能够根据一定的算法选择其中一个RS作为下一跳,达到负载均衡和冗余的效果。
既然是通过直连路由的方式转发,那显然LB必须与所有的RS在同一个子网,不能跨子网,否则路由不可达。换句话说, 这种模式只支持内部负载均衡(Internal LoadBalancer) 。
另外如前面所述,LB不会修改源端口和目标端口,因此这种模式也无法支持端口映射,换句话说 LB的端口和所有RS的端口必须一致 。
现在设有LBIP为 192.168.193.197 ,有三个RS如下:
注意到我们的Serv的端口30620和RS的端口是一样的,并且通过 -g 参数指定为直连路由模式(模式)。
IP为192.168.193.226,我们验证Serv是否可连接:
我们发现并不通,在其中一个RS192.168.193.172上抓包:
正如前面所说,LB是通过路由转发的,根据路由的原理,源MAC地址修改为LB的MAC地址,而目标MAC地址修改为RS MAC地址,相当于RS是LB的下一跳。
并且源IP和目标IP都不会修改。问题就来了,我们期望访问的是RS,但RS收到的目标IP却是LB的IP,发现这个目标IP并不是自己的IP,因此不会通过INPUT链转发到用户空间,这时要不直接丢弃这个包,要不根据路由再次转发到其他地方,总之两种情况都不是我们期望的结果。
那怎么办呢?为了让RS接收这个包,必须得让RS有这个目标IP才行。于是不妨在lo上添加个虚拟IP,IP地址伪装成LB IP 192.168.193.197:
问题又来了,这就相当于有两个相同的IP,IP重复了怎么办?办法是隐藏这个虚拟网卡,不让它回复ARP,其他主机的neigh也就不可能知道有这么个网卡的存在了,参考 Using arp announce/arp ignore to disable ARP 。
此时再次从客户端c:
终于通了。
我们从前面的抓包中知道,源IP为 IP 192.168.193.226,因此直接回包给即可,不可能也不需要再回到LB了,即A->B,B->C,C->A,流量方向是三角形状的,因此这种模式又称为三角模式。
我们从原理中不难得出如下结论:
前面介绍了直连路由模式,要求所有的在同一个子网,而ipip隧道模式则主要解决这种限制,LBIP和RS可以不在同一个子网,此时需要通过ipip隧道进行传输。
现在设有LBIP为 192.168.193.77/25 ,在该上增加一个VIP地址:
ip addr add 192.168.193.48问题又来了,这就相当于有两个相同的IP,IP重复了怎么办?办法是隐藏这个虚拟网卡,不让它回复ARP,其他主机的neigh也就不可能知道有这么个网卡的存在了,参考Using arp announce/arp ignore to disable ARP。/25 dev 0
有三个RS如下:
如上三个RS子网掩码均为255.255.255.128,即25位子网,显然和VIP 192.168.193.48/25不在同一个子网。
注意到我们的Serv的端口30620和RS的端口是一样的,并且通过 -i 参数指定为ipip隧道模式。
Serv可访问,我们在RS上抓剩下的到了POSTROUTING链就和Serv ClusterIP完全一样了,只要匹配 0x4000/0x4000 的包就会做SNAT。包如下:
我们发现和直连路由一样,源IP和目标IP没有修改。
所以IPIP模式和(Gatewaying)模式原理基本一样,不同的是(Gatewaying)模式要求所有的RS和LB在同一个子网,而IPIP模式则可以支持跨子网的情况,为了解决跨子网通信问题,使用了ipip隧道进行数据传输。
ipvs是一个内核态的四层负载均衡,支持NAT、Gateway以及IPIP隧道模式,Gateway模式性能,但LB和RS不能跨子网,IPIP性能次之,通过ipip隧道解决跨网段传输问题,因此能够支持跨子网。而NAT模式没有限制,这也是一种支持端口映射的模式。
我们不难猜想,由于Kubernetes Serv需要使用端口映射功能,因此kube-proxy必然只能使用ipvs的NAT模式。
使用kubeadm安装Kubernetes可参考文档 Cluster Created by Kubeadm ,不过这个文档的安装配置有问题 kubeadm #1182 ,如下配置不生效:
需要修改为如下配置:
可以通过如下命令确认kube-proxy是否修改为ipvs:
创建一个ClusterIP类似的Serv如下:
ClusterIP 10.96.54.11为我们查看ipvs配置如下:
可见ipvs的LB IP为ClusterIP,算法为rr,RS为Pod的IP。
另外我们发现使用的模式为NAT模式,这是显然的,因为除了NAT模式支持端口映射,其他两种均不支持端口映射,所以必须选择NAT模式。
可见kube-proxy首先会创建一个dummy虚拟网卡kube-ipvs0,然后把所有的Serv IP添加到kube-ipvs0中。
我们知道基于iptables的Serv,ClusterIP是一个虚拟的IP,因此这个IP是ping不通的,但ipvs中这个IP是在每个上真实存在的,因此可以ping通:
当然由于这个IP就是配置在本地虚拟网卡上,所以对诊断问题没有一点用处的。
我们接下来研究下ClusterIP如何传递的。
当我们通过如下命令连接服务时:
此时由于10.96.54.11就在本地,所以会以这个IP作为出口地址,即源IP和目标IP都是10.96.54.11,此时相当于:
其中xxxx为随机端口。
然后经过ipvs,ipvs会从RS ip列中选择其中一个Pod ip作为目标IP,设为10.244.2.2:
我们从iptables LOG可以验证:
我们查看OUTPUT安全组规则如下:
其中ipsetj KUBE-CLUSTER-IP 保存着所有的ClusterIP以及端口。
如上规则的意思就是除了Pod以外访问ClusterIP的包都打上 0x4000/0x4000 。
如上规则的意思就是只要匹配mark 0x4000/0x4000 的包都做SNAT,由于10.244.2.2是从flannel.1出去的,因此源ip会改成flannel.1的ip 10.244.0.0 :
通过Vxlan 隧道发到Pod的Node上,转发给Pod的v,回包通过路由到达源Node,源Node通过之前的MASQUERADE再把目标IP还原为10.96.54.11。
查看Serv如下:
现在设集群外的一个IP 192.168.193.197访问192.168.193.172:32016:
到达PREROUTING链:
如上4条规则看起来复杂,其实就做一件事,如果目标地址为NodeIP,则把包标记 0x4000 , 0x4000 。
我们查看ipvs:
我们发现和ClusterIP实现原理非常相似,ipvs Serv的VIP为Node IP,端口为NodePort。ipvs会选择其中一个Pod IP作为DNAT目标,这里设为10.244.3.2:
剩下的到了POSTROUTING链就和Serv ClusterIP完全一样了,只要匹配 0x4000/0x4000 的包就会做SNAT。
Kubernetes的ClusterIP和NodePort都是通过ipvs serv实现的,Pod当作ipvs serv的server,通过NAT MQSQ实现转发。
简单来说kube-proxy主要在所有的Node做如下三件事:
使用ipvs作为kube-proxy后端,不仅提高了转发性能,结合ipset还使iptables规则变得更“干净”清楚,从此再也不怕iptables。
更多关于kube-proxy ipvs参考 IPVS-Based In-Cluster Load Balancing Deep Dive .
本文首先介绍了kube-proxy的功能以及kube-proxy基于iptables的实现原理,然后简单介绍了ipvs,了解了ipvs支持的三种转发模式,介绍了kube-proxy基于ipvs的实现原理。
ipvs是专门设计用来做内核态四层负载均衡的,由于使用了hash表的数据结构,因此相比iptables来说性能会更好。基于ipvs实现Serv转发,Kubernetes几乎能够具备无限的水平扩展能力。随着Kubernetes的部署规模越来越大,应用越来越广泛,ipvs必然会取代iptables成为Kubernetes Serv的默认实现后端。
转自
vxlan和sdn是什么关系?
与iptables-se、iptables-restore对应的工具ipvs也有ipvsadm-se、ipvsadm-restore。一、VLAN介绍VLAN,是英文VirtualLocalAreaNetwork的缩写,中文名为"虚拟局域网",VLAN是 一种将局域网(LAN)设备从逻辑上划分(注意,不是从物理上划分)成一个个网段(或者 说是更小的局域网LAN),从而实现虚拟工作组(单元)的数据交换技术。 VLAN这一新兴技术主要应用于交换机和路由器中,但目前主流应用还是在交换机之中 。不过不是所有交换机都具有此功能,只有三层以上交换机才具有此功能,这一点可以查 看相应交换机的说明书即可得知。VLAN的好处主要有三个: (1)端口的分隔。即便在同一个交换机上,处于不同VLAN的端口也是不能通信的。这 样一个物理的交换机可以当作多个逻辑的交换机使用。 (2)网络的安全。不同VLAN不能直接通信,杜绝了广播信息的不安全性。 (3)灵活的管理。更改用户所属的网络不必换端口和连线,只更改软件配置就可以了。 二、VXLAN介绍什么是VXLANVXLAN全称VirtualeXtensibleLAN,是一种覆盖网络技术或隧道技术。VXLAN将虚拟机发出的数据包封装在UDP中,并使用物理网络的IP/MAC作为outer-header进行封装,然后在物理IP网上传输,到达目的地后由隧道终结点解封并将数据发送给目标虚拟机。为什么需要Vxlanvlan的数量限制 4096个vlan远不能满足大规模云计算数据中心的需求2.物理网络基础设施的限制 基于IP子网的区域划分限制了需要二层网络连通性的应用负载的部署3.TOR交换机MAC表耗尽 虚拟化以及东西向流量导致的MAC表项4.多租户场景 IP地址重叠?什么是隧道技术隧道技术(Tunneling)是一种通过使用互联网络的基础设施在网络之间传递数据的方式。使用隧道传递的数据(或负载)可以是不同协议的数据帧或包。隧道协议将其它协议的数据帧或包重新封装然后通过隧道发送。新的帧头提供路由信息,以便通过互联网传递被封装的负载数据。 这里所说的隧道类似于点到点的连接,这种方式能够使来自许多信息源的网络业务在同一个基础设施中通过不同的隧道进行传输。隧道技术使用点对点通信协议代替了交换连接,通过路由网络来连接数据地址。隧道技术允许授权移动用户或已授权的用户在任何时间、任何地点访问企业网络。 通过隧道的建立,可实现:将数据流强制送到特定的地址隐藏私有的网络地址在IP网上传递非IP数据包提供数据安全支持隧道技术好处隧道协议有很多好处,例如在拨号网络中,用户大都接受ISP分配的动态IP地址,而企业网一般均采用防火墙、NAT等安全措施来保护自己的网络,企业员工通过ISP拨号上网时就不能穿过防火墙访问企业内部网资源。采用隧道协议后,企业拨号用户就可以得到企业内部网IP地址,通过对PPP帧进行封装,用户数据包可以穿过防火墙到达企业内部网。隧道的应用VPN具体实现是采用隧道技术,将企业网的数据封装在隧道中进行传输。隧道协议可分为第二层隧道协议PPTP、L2F、L2TP和第三层隧道协议GRE、IPsec。它们的本质区别在于用户的数据包是被封装在哪种数据包中在隧道中传输的。 三、GRE介绍GRE特点跨不同网络实现二次IP通信2.L3上面包装L33.封装在IP报文中4.点对点隧道GRE好处不用变更底层网络架构重建L2、L3通信实现不同host之间网络guest互通方便guest迁移支持网络数量扩大对于GRE遂道,缺点主要是一是增加了GRE表头会导致本应由交换机硬件来分片的变成由软件来分片(STT技术可以弥补这一点);二是GRE广播,且遂道将虚拟二层打通了,广播风暴更厉害。但对于虚机来说,因为虚拟交换机是完全能够知道虚机的IP和MAC地址的映射关系的,根本不需要通过ARP广播来根据IP找MAC地址,目前Neutron中有这类似的blueprint可以禁止广播。所以个人比较看好STT技术,因为目前openvswitch与linuxkernel还未实现STT,所以Neutron目前没有STT插件(但有VXLAN和GRE插件)。
其中 KUBE-SVC-RPP7DHNHMGOIIFDC 子链规则如下:vxlan和sdn是什么关系?
074 - 两张图总结 Neutron 架构一、VLAN介绍VLAN,是英文VirtualLocalAreaNetwork的缩写,中文名为"虚拟局域网",VLAN是 一种将局域网(LAN)设备从逻辑上划分(注意,不是从物理上划分)成一个个网段(或者 说是更小的局域网LAN),从而实现虚拟工作组(单元)的数据交换技术。 VLAN这一新兴技术主要应用于交换机和路由器中,但目前主流应用还是在交换机之中 。不过不是所有交换机都具有此功能,只有三层以上交换机才具有此功能,这一点可以查 看相应交换机的说明书即可得知。VLAN的好处主要有三个: (1)端口的分隔。即便在同一个交换机上,处于不同VLAN的端口也是不能通信的。这 样一个物理的交换机可以当作多个逻辑的交换机使用。 (2)网络的安全。不同VLAN不能直接通信,杜绝了广播信息的不安全性。 (3)灵活的管理。更改用户所属的网络不必换端口和连线,只更改软件配置就可以了。 二、VXLAN介绍什么是VXLANVXLAN全称VirtualeXtensibleLAN,是一种覆盖网络技术或隧道技术。VXLAN将虚拟机发出的数据包封装在UDP中,并使用物理网络的IP/MAC作为outer-header进行封装,然后在物理IP网上传输,到达目的地后由隧道终结点解封并将数据发送给目标虚拟机。为什么需要Vxlanvlan的数量限制 4096个vlan远不能满足大规模云计算数据中心的需求2.物理网络基础设施的限制 基于IP子网的区域划分限制了需要二层网络连通性的应用负载的部署3.TOR交换机MAC表耗尽 虚拟化以及东西向流量导致的MAC表项4.多租户场景 IP地址重叠?什么是隧道技术隧道技术(Tunneling)是一种通过使用互联网络的基础设施在网络之间传递数据的方式。使用隧道传递的数据(或负载)可以是不同协议的数据帧或包。隧道协议将其它协议的数据帧或包重新封装然后通过隧道发送。新的帧头提供路由信息,以便通过互联网传递被封装的负载数据。 这里所说的隧道类似于点到点的连接,这种方式能够使来自许多信息源的网络业务在同一个基础设施中通过不同的隧道进行传输。隧道技术使用点对点通信协议代替了交换连接,通过路由网络来连接数据地址。隧道技术允许授权移动用户或已授权的用户在任何时间、任何地点访问企业网络。 通过隧道的建立,可实现:将数据流强制送到特定的地址隐藏私有的网络地址在IP网上传递非IP数据包提供数据安全支持隧道技术好处隧道协议有很多好处,例如在拨号网络中,用户大都接受ISP分配的动态IP地址,而企业网一般均采用防火墙、NAT等安全措施来保护自己的网络,企业员工通过ISP拨号上网时就不能穿过防火墙访问企业内部网资源。采用隧道协议后,企业拨号用户就可以得到企业内部网IP地址,通过对PPP帧进行封装,用户数据包可以穿过防火墙到达企业内部网。隧道的应用VPN具体实现是采用隧道技术,将企业网的数据封装在隧道中进行传输。隧道协议可分为第二层隧道协议PPTP、L2F、L2TP和第三层隧道协议GRE、IPsec。它们的本质区别在于用户的数据包是被封装在哪种数据包中在隧道中传输的。 三、GRE介绍GRE特点跨不同网络实现二次IP通信2.L3上面包装L33.封装在IP报文中4.点对点隧道GRE好处不用变更底层网络架构重建L2、L3通信实现不同host之间网络guest互通方便guest迁移支持网络数量扩大对于GRE遂道,缺点主要是一是增加了GRE表头会导致本应由交换机硬件来分片的变成由软件来分片(STT技术可以弥补这一点);二是GRE广播,且遂道将虚拟二层打通了,广播风暴更厉害。但对于虚机来说,因为虚拟交换机是完全能够知道虚机的IP和MAC地址的映射关系的,根本不需要通过ARP广播来根据IP找MAC地址,目前Neutron中有这类似的blueprint可以禁止广播。所以个人比较看好STT技术,因为目前openvswitch与linuxkernel还未实现STT,所以Neutron目前没有STT插件(但有VXLAN和GRE插件)。
013 - 动手实践 Linux VLANvxlan和vlan区别是什么?
如下命令创建一个serv实例 172.17.0.1:32016 , -t 指定的为 TCP 端口, -s 指定算法为轮询算法rr(Round Robin),ipvs支持简单轮询(rr)、加权轮询(wrr)、最少连接(lc)、源地址或者目标地址散列(sh、dh)等10种调度算法。vxlan和vlan区别是:
VXLAN是一种网络虚拟化技术,可以改进大型云计算在部署时的扩展问题,是对VLAN的一种扩展。VXLAN是一种功能强大的工具,可以穿透三层网络对二层进行扩展。它可通过封装流量并将其扩展到第三层,以此来解决VMS(虚拟内存系统)的可移植性限制,使其可以访问在外部IP子网上的。
VLAN(Virtual Local Area Network)的中文名为"虚拟局域网"。
虚拟局域网(VLAN)是一组逻辑上的设备和用户,这些设备和用户并不受物理位置的限制,可以根据功能、部门及应用等因素将它们组织起来,相互之间的通信就好像它们在同一个网段中一样,由此得名虚拟局域网。
基本也就是说,ipvs的包根本不会经过iptables nat表POSTROUTING链?原理
VXLAN采取了将原始以太网报文封装在UDP数据包里的封装格式。将原来的二层数据帧加上VXLAN头部一起封装在一个UDP数据包里。
VXLAN头部包含有一个VXLAN标识(即VNI,VXLAN Network Identifier),只有在同一个VXLAN上的虚拟机之间才能相互通信。VNI在数据包之中占24比特,故可支持1600万个VXLAN的同时存在,远多于VLAN的4094个,因此可适应大规模租户的部署。
VXLAN一般通过安装在上的软件实现报文的封装与解封装,网络只要IP路由可达即可。VXLAN实现了应用与物理网络的解耦,但网络与虚拟机还是相互的。业界一般通过网络(如SDN,Software Defined Network)实现VXLAN网络与云业务的联动。
当虚拟机发生迁移后,虚机/存储会把虚拟机迁移信息通知给网络,网络根据虚拟机迁移的新位置,重新调整网络配置,从而实现网络与云业务的联动。也就是说,物理网络可以是传统的三层IP网络,路由可达即可。
虚拟机可跨三层IP网络远距离迁移,不再受限于二层技术。物理网络也无需允许所有VLAN通过。接入交换机需要学习的MAC地址的数量也大大减少,削弱了网络设备MAC地址表项规格对虚拟机规模的约束。
《每天5分钟玩转 OpenStack》教程目录
书籍:
《每天5分钟玩转OpenStack》
(点击 “阅读原文” 直达)
第 1 部分 预备知识
第 1 章
虚拟化
002 - 虚拟化
003 - 准备 KVM 实验环境
004 - 启动个 KVM 虚机
005 - 远程管理 KVM 虚机
006 - CPU 和内存虚拟化原理
007 - KVM 存储虚拟化
008 - LVM 类型的 Storage Pool
009 - KVM 网络虚拟化基础
010 - 动手实践虚拟网络
011 - 理解 virbr0
012 - Linux 如何实现 VLAN
014 - 云计算与 OpenStack
第 2 部分 OpenStack 核心
第 2 章
OpenStack 架构
015 - OpenStack 架构
016 - 搭建 OpenStack 实验环境
017 - 部署 DevStack
第 3 章
Keystone
018 - 理解 Keystone 核心概念
019 - 通过例子学习 Keystone
第 4 章
Glance
020 - 理解 Glance
021 - 创建 Image
022 - 如何使用 OpenStack CLI
第 5 章
Nova
023 - 理解 Nova 架构
024 - Nova 组件如何协同工作
025 - OpenStack 通用设计思路
026 - Nova 组件详解
027 - 看 nova-scheduler 如何选择计算
028 - nova-com 部署 instance 详解
029 - 教你看懂 OpenStack 日志
030 - Launch和Shut Off作详解
031 - Start Instance 作详解
032 - Nova reboot 和 lock 作
033 - Terminate Instance 作详解
034 - Pause/Resume Instance 作详解
035 - Suspend/Rescue Instance 作详解
036 - Snapshot Instance 作详解
037 - Rebuild Instance 作详解
038 - Shelve Instance 作详解
040 - Migrate Instance 作详解
041 - Resize Instance 作详解
042 - Live Migrate 作
043 - 计算宕机了怎么办?
第 6 章
Cinder
045 - 理解 Cinder 架构
046 - 掌握 Cinder 设计思想
047 - Cinder 组件详解
048 - 掌握 cinder-scheduServ kubernetes-bootcamp-v1的NodePort为32016。ler 调度逻辑
049 - 准备 LVM Volume Provider
050 - Create Volume 作(Part I)
051 - Create Volume 作(Part II)
052 - Create Volume 作(Part III)
053 - Attach Volume 作(Part I)
054 - Attach Volume 作(Part II)
055 - Detach Volume 作
056 - Extend Volume 作
057 - Delete Volume 作
058 - Snapshot Volume 作
059 - Backup Volume 作
060 - Restore Volume 作
061 - Boot from Volume
062 - NFS Volume Provider(Part I)
063 - NFS Volume Provider(Part II)
064 - NFS Volume Provider(Part III)
Neutron
065 - Neutron 功能概述
066 - Neutron 网络基本概念
068 - Neutron 物理部署方案
069 - 理解 Neutron 分层模型
070 - Neutron 如何支持多种 network provider
071 - 详解 ML2 Core Plugin(I)
072 - 详解 ML2 Core Plugin(II)
073 - Serv Plugin / Agent
075 - 为 Neutron 准备物理基础设施(I)
076 - 为 Neutron 准备物理基础设施(II)
077 - 配置 linux-bridge mechani driver
078 - 实践 Neutron 前的两个准备工作
079 - 在 ML2 中 enable local network
080 - 创建个 local network(I)
081 - 创建个 local network(II)
082 - 将 instance 连接到 first_local_net
083 - 连接第二个 insance 到 first_local_net
084 - 创建第二个 local network
085 - 将 instance 连接到 second_local_net
086 - flat network 原理与配置
087 - 创建 flat network
088 - 将 instance 连接到 flat_net
089 - 配置 DHCP 服务
090 - 用 namspace 隔离 DHCP 服务
0 - 获取 dhcp IP 过程分析
092 - Neutron Vlan Network 原理
093 - 在 ML2 中配置 Vlan Network
094 - 创建个 vlan network "vlan100"
095 - 将 instance 连接到 vlan100
096 - 创建第二个 vlan network "vlan101"
098 - Routing 功能概述
099 - 配置 L3 agent
100 - 创建 router 连通 subnet
101 - 虚拟 router 原理分析
102 - Why Namespace?
103 - 访问外网 ML2 的配置
104 - 创建外网 ext_net
105 - 外网访问原理分析
106 - 创建 floating IP
107 - floating IP 原理分析
108 - VXLAN 概念(Part I)
110 - 在 ML2 中配置 VXLAN
111 - 创建 VXLAN
112 - 部署 instance 到 VXLAN
113 - L2 Population 原理
114 - 配置 L2 Population
115 - Neutron 默认安全组规则
116 - 应用新安全组
117 - 理解 Neutron FWaaS
118 - 实践 Neutron FWaaS
119 - FWaaS 实践: 允许 ssh
120 - 理解 Neutorn LBaaS
121 - 配置 LBaaS
122 - 创建 Pool & VIP
123 - 添加 Pool Member
124 - 创建 Monitor 并测试
125 - LBaaS 实现机制
126 - 通过 floating IP 访问 VIP
127 - 启用 Open vSwitch
128 - OVS 中的各种网络设备
129 - 创建 OVS Local Network
130 - 将 instance 部署到 OVS Local Network
131 - 部署 cirros_vm2 和 second_local_net
132 - OVS local network 连通性分析
133 - 在 ML2 中配置 OVS flat network
134 - 创建 OVS flat network
135 - 部署 instance 到 OVS flat network
136 - 在 ML2 中配置 OVS vlan network
137 - 创建 OVS vlan100 netwrok
138 - 部署 instance 到 OVS vlan100 139 - 创建 OVS vlan101 并部署 instance
140 - 分析 OVS 如何实现 vlan 隔离
141 - 用虚拟 router 连通 subnet
142 - Neutron Router 工044 - 1 张图秒懂 Nova 16 种作作原理
144 - 创建 OVS 外部网络 ext_net
145 - 将 ext_net 连接到 router
146 - ML2 中配置 OVS VxLAN
147 - 创建 vxlan 并部署 instance
148 - OVS vxlan 底层结构分析
149 - OVS VxLAN Flow 分析
经验分享
150 - 学习 OpenStack 的方
151 - 制作 OpenStack Linux 镜像
152 - 制作 OpenStack Windows 镜像
153 - 解决 Windows instance 时间不同步问题
154 - cloudbase-init 自动扩盘的副作用
155 - 定制 Linux cloud-init
156 -
《每天5分钟玩转 OpenStack》教程目录
可见并没有10.222.0.1:8080 Socket 。书籍:
《每天5分钟玩转OpenStack》
(点击 “阅读原文” 直达)
第 1 部分 预备知识
第 1 章
虚拟化
002 - 虚拟化
003 - 准备 KVM 实验环境
004 - 启动个 KVM 虚机
005 - 远程管理 KVM 虚机
006 - CPU 和内存虚拟化原理
007 - KVM 存储虚拟化
008 - LVM 类型的 Storage Pool
009 - KVM 网络虚拟化基础
010 - 动手实践虚拟网络
011 - 理解 virbr0
012 - Linux 如何实现 VLAN
014 - 云计算与 OpenStack
第 2 部分 OpenStack 核心
第 2 章
OpenStack 架构
015 - OpenStack 架构
016 - 搭建 OpenStack 实验环境
017 - 部署 DevStack
第 3 章
Keystone
018 - 理解 Keystone 核心概念
019 - 通过例子学习 Keystone
第 4 章
Glance
020 - 理解 Glance
021 - 创建 Image
022 - 如何使用 OpenStack CLI
第 5 章
Nova
023 - 理解 Nova 架构
024 - Nova 组件如何协同工作
025 - OpenStack 通用设计思路
026 - Nova 组件详解
027 - 看 nova-scheduler 如何选择计算
028 - nova-com 部署 instance 详解
029 - 教你看懂 OpenStack 日志
030 - Launch和Shut Off作详解
031 - Start Instance 作详解
032 - Nova reboot 和 lock 作
033 - Terminate Instance 作详解
034 - Pause/Resume Instance 作详解
035 - Suspend/Rescue Instance 作详解
036 - Snapshot Instance 作详解
037 - Rebuild Instance 作详解
038 - Shelve Instance 作详解
040 - Migrate Instance 作详解
041 - Resize Instance 作详解
042 - Live Migrate 作
043 - 计算宕机了怎么办?
第 6 章
Cinder
045 - 理解 Cinder 架构
046 - 掌握 Cinder 设计思想
047 - Cinder 组件详解
048 - 掌握 cinder-scheduler 调度逻辑
049 - 准备 LVM Volume Provider
050 - Create Volume 作(Part I)
051 - Create Volume 作(Part II)
052 - Create Volume 作(Part III)
053 - Attach Volume 作(Part I)
054 - Attach Volume 作(Part II)
055 - Detach Volume 作
056 - Extend Volume 作
057 - Delete Volume 作
058 - Snapshot Volume 作
059 - Backup Volume 作
060 - Restore Volume 作
061 - Boot from Volume
062 - NFS Volume Provider(Part I)
063 - NFS Volume Provider(Part II)
064 - NFS Volume Provider(Part III)
Neutron
065 - Neutron 功能概述
066 - Neutron 网络基本概念
068 - Neutron 物理部署方案
069 - 理解 Neutron 分层模型
070 - Neutron 如何支持多种 network provider
071 - 详解 ML2 Core Plugin(I)
072 - 详解 ML2 Core Plugin(II)
073 - Serv Plugin / Agent
075 - 为 Neutron 准备物理基础设施(I)
076 - 为 Neutron 准备物理基础设施(II)
077 - 配置 linux-bridge mechani driver
078 - 实践 Neutron 前的两个准备工作
079 - 在 ML2 中 enable local network
080 - 创建个 local network(I)
081 - 创建个 local network(II)
082 - 将 instance 连接到 first_local_net
083 - 连接第二个 insance 到 first_local_net
084 - 创建第二个 local network
085 - 将 instance 连接到 second_local_net
086 - flat network 原理与配置
087 - 创建 flat network
088 - 将 instance 连接到 flat_net
089 - 配置 DHCP 服务
090 - 用 namspace 隔离 DHCP 服务
0 - 获取 dhcp IP 过程分析
092 - Neutron Vlan Network 原理
093 - 在 ML2 中配置 Vlan Network
094 - 创建个 vlan network "vlan100"
095 - 将 instance 连接到 vlan100
096 - 创建第二个 vlan network "vlan101"
098 - Routing 功能概述
099 - 配置 L3 agent
100 - 创建 router 连通 subnet
101 - 虚拟 router 原理分析
102 - Why Namespace?
103 - 访问外网 ML2 的配置
104 - 创建外网 ext_net
105 - 外网访问原理分析
106 - 创建 floating IP
107 - floating IP 原理分析
108 - VXLAN 概念(Part I)
110 - 在 ML2 中配置 VXLAN
111 - 创建 VXLAN
112 - 部署 instance 到 VXLA097 - 将 instance 连接到 vlan101N
113 - L2 Population 原理
114 - 配置 L2 Population
115 - Neutron 默认安全组规则
116 - 应用新安全组
117 - 理解 Neutron FWaaS
118 - 实践 Neutron FWaaS
119 - FWaaS 实践: 允许 ssh
120 - 理解 Neutorn LBaaS
121 - 配置 LBaaS
122 - 创建 Pool & VIP
123 - 添加 Pool Member
124 - 创建 Monitor 并测试
125 - LBaaS 实现机制
126 - 通过 floating IP 访问 VIP
127 - 启用 Open vSwitch
128 - OVS 中的各种网络设备
129 - 创建 OVS Local Network
130 - 将 instance 部署到 OVS Local Network
131 - 部署 cirros_vm2 和 second_local_net
132 - OVS local network 连通性分析
133 - 在 ML2 中配置 OVS flat network
134 - 创建 OVS flat network
135 - 部署 instance 到 OVS flat network
136 - 在 ML2 中配置 OVS vlan network
137 - 创建 OVS vlan100 netwrok
138 - 部署 instance 到 OVS vlan100 139 - 创建 OVS vlan101 并部署 instance
140 - 分析 OVS 如何实现 vlan 隔离
141 - 用虚拟 router 连通 subnet
142 - Neutron Router 工作原理
144 - 创建 OVS 外部网络 ext_net
145 - 将 ext_net 连接到 router
146 - ML2 中配置 OVS VxLAN
147 - 创建 vxlan 并部署 instance
148 - OVS vxlan 底层结构分析
149 - OVS VxLAN Flow 分析
经验分享
150 - 学习 OpenStack 的方
151 - 制作 OpenStack Linux 镜像
152 - 制作 OpenStack Windows 镜像
153 - 解决 Windows instance 时间不同步问题
154 - cloudbase-init 自动扩盘的副作用
155 - 定制 Linux cloud-init
156 -
IPVS从入门到精通kube-proxy实现原理
IP为192.168.193.226/25,我们验证Serv是否可连接:我们知道容器的特点是快速创建、快速销毁,Kubernetes Pod和容器一样只具有临时的生命周期,一个Pod随时有可能被终止或者漂移,随着集群的状态变化而变化,一旦Pod变化,则该Pod提供的服务也就无法访问,如果直接访问Pod则无法实现服务的连续性和高可用性,因此显然不能使用Pod地址作为服务暴露端口。
解决这个问题的办法和传统数据中心解决无状态服务高可用的思路完全一样,通过负载均衡和VIP实现后端真实服务的自动转发、故障转移。
这个负载均衡在Kubernetes中称为Serv,VIP即Serv ClusterIP,因此可以认为Kubernetes的Serv就是一个四层负载均衡,Kubernetes对应的还有七层负载均衡Ingress,本文仅介绍Kubernetes Serv。
这个Serv就是由kube-proxy实现的,ClusterIP不会因为Podz状态改变而变,需要注意的是VIP即ClusterIP是个的IP,这个IP在整个集群中根本不存在,当然也就无法通过IP协议栈无法路由,底层underlay设备更无法感知这个IP的存在,因此ClusterIP只能是单主机(Host Only)作用域可见,这个IP在其他以及集群外均无法访问。
Kubernetes为了实现在集群所有的都能够访问Serv,kube-proxy默认会在所有的Node都创建这个VIP并且实现负载,所以在部署Kubernetes后发现kube-proxy是一个DaemonSet。
而Serv负载之所以能够在Node上实现是因为无论Kubernetes使用哪个网络模型,均需要保证满足如下三个条件:
至少第2点是必须满足的,有了如上几个设,Kubernetes Serv才能在Node上实现,否则Node不通Pod IP也就实现不了了。
有人说既然kube-proxy是四层负载均衡,那kube-proxy应该可以使用haproxy、nginx等作为负载后端啊?
事实上确实没有问题,不过需要考虑的就是性能问题,如上这些负载均衡功能都强大,但毕竟还是基于用户态转发或者反向实现的,性能必然不如在内核态直接转发处理好。
因此kube-proxy默认会优先选择基于内核态的负载作为后端实现机制,目前kube-proxy默认是通过iptables实现负载的,在此之前还有一种称为userspace模式,其实也是基于iptables实现,可以认为当前的iptables模式是对之前userspace模式的优化。
本节接下来将详细介绍kube-proxy iptables模式的实现原理。
首先创建了一个ClusterIP类型的Serv:
其中ClusterIP为10.106.224.41,我们可以验证这个IP在本地是不存在的:
所以 不要尝试去ping ClusterIP,它不可能通的 。
此时在Node192.168.193.172问该Serv服务,首先流量到达的是OUTPUT链,这里我们只关心nat表的OUTPUT链:
该链跳转到 KUBE-SERVICES 子链中:
我们发现与之相关的有两条规则:
这几条规则看起来复杂,其实实现的功能很简单:
我们查看其中一个子链 KUBE-SEP-FTIQ6MSD3LWO5HZX 规则:
由此可见子链 KUBE-SVC-RPP7DHNHMGOIIFDC 的功能就是按照概率均等的原则DNAT到其中一个Endpoint IP,即Pod IP,设为10.244.1.2,
此时相当于:
接着来到POSTROUTING链:
这两条规则只做一件事就是只要标记了 0x4000/0x4000 的包就一律做MASQUERADE(SNAT),由于10.244.1.2默认是从flannel.1转发出去的,因此会把源IP改为flannel.1的IP 10.244.0.0 。
剩下的就是常规的走Vxlan隧道转发流程了,这里不再赘述,感兴趣的可以参考我之前的文章 浅聊几种主流Docker网络的实现原理 。
接下来研究下NodePort过程,首先创建如下Serv:
其中Serv的NodePort端口为30419。
设有一个外部IP 192.168.193.197,通过 192.168.193.172:30419 访问服务。
首先到达PREROUTING链:
PREROUTING的规则非常简单,凡是发给自己的包,则交给子链 KUBE-NODEPORTS 处理。注意前面省略了判断ClusterIP的部分规则。
KUBE-NODEPORTS 规则如下:
这个规则首先给包打上标记 0x4000/0x4000 ,然后交给子链 KUBE-SVC-RPP7DHNHMGOIIFDC 处理, KUBE-SVC-RPP7DHNHMGOIIFDC 刚刚已经见面过了,其功能就是按照概率均等的原则DNAT到其中一个Endpoint IP,即Pod IP,设为10.244.1.2。
此时发现10.244.1.2不是自己的IP,于是经过路由判断目标为10.244.1.2需要从flannel.1发出去。
接着到了 FORWARD 链,
FORWARD表在这里只是判断下,只允许打了标记 0x4000/0x4000 的包才允许转发。
来到 POSTROUTING 链,这里和ClusterIP就完全一样了,在 KUBE-POSTROUTING 中 MASQUERADE (SNAT),结果:
我们发现基于iptables模式的kube-proxy ClusterIP和NodePort都是基于iptables规则实现的,我们至少发现存在如下几个问题:
本文接下来将介绍kube-proxy的ipvs实现,由于本人之前也是对ipvs很陌生,没有用过,专门学习了下ipvs,因此在第二章简易介绍了下ipvs,如果已经很熟悉ipvs了,可以直接跳过,这一章和Kubernetes几乎没有任何关系。
另外由于本人对ipvs也是初学,水平有限,难免出错,欢迎指正!
我们接触比较多的是应用层负载均衡,比如haproxy、nginx、F5等,这些负载均衡工作在用户态,因此会有对应的进程和socket,一般能同时支持4层负载和7层负载,使用起来也比较方便。
LVS是国内章文嵩博士开发并贡献给社区的( 章文嵩博士和他背后的负载均衡帝国 ),主要由ipvs和ipvsadm组成,ipvs是工作在内核态的4层负载均衡,和iptables一样都是基于内核底层netfilter实现,netfilter主要通过各个链的钩子实现包处理和转发。ipvsadm和ipvs的关系,就好比netfilter和iptables的关系,它运行在用户态,提供简单的CLI接口进行ipvs配置。
由于ipvs工作在内核态,直接基于内核处理包转发,所以的特点就是性能非常好。又由于它工作在4层,因此不会处理应用层数据,经常有人问ipvs能不能做SSL证书卸载、或者修改HTTP头部数据,显然这些都不可能做的。
我们知道应用层负载均衡大多数都是基于反向实现负载的,工作在应用层,当用户的包到达负载均衡listening后,基于一定的算法从后端服务列表中选择其中一个后端服务进行转发。当然中间可能还会有一些额外作,最常见的如SSL证书卸载。
而ipvs工作在内核态,只处理四层协议,因此只能基于路由或者NAT进行数据转发,可以把ipvs当作一个特殊的路由器,这个可以根据一定的算法自动选择下一跳,或者把ipvs当作一个多重DNAT,按照一定的算法把ip包的目标地址DNAT到其中真实服务的目标IP。针对如上两种情况分别对应ipvs的两种模式–模式和NAT模式,另外ipip模式则是对模式的扩展,本文下面会针对这几种模式的实现原理进行详细介绍。
ipvsadm命令行用法和iptables命令行用法非常相似,毕竟是兄弟,比如 -L 列举, -A 添加, -D 删除。
但是其实ipvsadm相对iptables命令简直太简单了,因为没有像iptables那样存在各种table,table嵌套各种链,链里串着一堆规则,ipvsadm就只有两个核心实体,分别为serv和server,serv就是一个负载均衡实例,而server就是后端member,ipvs术语中叫做real server,简称RS。
然后把10.244.1.2:8080、10.244.1.3:8080、10.244.3.2:8080添加到serv后端member中。
其中 -t 指定serv实例, -r 指定server地址, -w 指定权值, -m 即前面说的转发模式,其中 -m 表示为 masquerading ,即NAT模式, -g 为 gatewaying ,即直连路由模式, -i 为 ipip ,ji即IPIP隧道模式。
NAT模式由字面意思理解就是通过NAT实现的,但究竟是如何NAT转发的,我们通过实验环境验证下。
现环境中LBIP为192.168.193.197,三个RS如下:
为了模拟LBIP和RS不在同一个网络的情况,在LB中添加一个虚拟IP地址:
这里需要注意的是,和应用层负载均衡如haproxy、nginx不一样的是,haproxy、nginx进程是运行在用户态,因此会创建socket,本地会端口,而 ipvs的负载是直接运行在内核态的,因此不会出现端口 :
IP为192.168.193.226,为了和LB的虚拟IP 10.222.0.1通,我们手动添加静态路由如下:
此时能够ping通LBVIP:
可见到VIP的链路没有问题,那是否能够访问我们的Serv呢?
我们验证下:
非常意外的结果是并不通。
在RS抓包如下:
我们发现数据包的源IP为 IP,目标IP为RS IP,换句话说,LBIPVS只做了DNAT,把目标IP改成RS IP了,而没有修改源IP。此时虽然RS和在同一个子网,链路连通性没有问题,但是由于发出去的包的目标IP和收到的包源IP不一致,因此会被直接丢弃,相当于给张三发信,李四回的信,显然不受信任。
既然IPVS没有给我们做SNAT,那自然想到的是我们手动做SNAT,在LB添加如下iptables规则:
再次检查Serv是否可以访问:
服务依然不通。并且在LB的iptables日志为空:
那mangle表呢?我们打开LOG查看下:
此时查看日志如下:
我们发现在mangle表中可以看到DNAT后的包。
只是可惜mangle表的POSTROUTING并不支持NAT功能:
对比Kubernetes配置发现需要设置如下系统参数:
再次验证:
终于通了,查看RS抓包:
如期望,修改了源IP为LB IP。
原来需要配置 net.ipv4.vs.conntrack=1 参数,这个问题折腾了一个晚上,不得不说目前ipvs的文档都太老了。
前面是通过手动iptables实现SNAT的,性能可能会有损耗,于是如下开源项目通过修改lvs直接做SNAT:
除了SNAT的办法,是否还有其他办法呢?想想我们最初的问题,发出去的包的目标IP和收到的包源IP不一致导致包被丢弃,那解决问题的办法就是把包重新引到LB上,只需要在所有的RS增加如下路由即可:
此时我们再次检查我们的Serv是否可连接:
结果没有问题。
不过我们是通过手动添加 IP到所有RS的明细路由实现的,如果不固定,这种方案仍然不太可行,所以通常做法是干脆把所有RS默认路由指向LB,即把LB当作所有RS的默认。
由此可知,用户通过LB地址访问服务,LBIPVS会把用户的目标IP由LB IP改为RS IP,源IP不变,包不经过iptables的OUTPUT直接到达POSTROUTING转发出去,包回来的时候也必须先到LB,LB把目标IP再改成用户的源IP,转发给用户。
显然这种模式来回都需要经过LB,因此又称为双臂模式。
模式(Gatewaying)又称为直连路由模式(Direct Routing)、透传模式, 所谓透传即LB不会修改数据包的源IP、端口以及目标IP、端口 ,LB做的仅仅是路由转发出去,可以把LB看作一个特殊的路由器,而RS则是的下一跳,这就相当于对于同一个目标地址,会有多个下一跳,这个路由器的特殊之处在于能够根据一定的算法选择其中一个RS作为下一跳,达到负载均衡和冗余的效果。
既然是通过直连路由的方式转发,那显然LB必须与所有的RS在同一个子网,不能跨子网,否则路由不可达。换句话说, 这种模式只支持内部负载均衡(Internal LoadBalancer) 。
另外如前面所述,LB不会修改源端口和目标端口,因此这种模式也无法支持端口映射,换句话说 LB的端口和所有RS的端口必须一致 。
现在设有LBIP为 192.168.193.197 ,有三个RS如下:
注意到我们的Serv的端口30620和RS的端口是一样的,并且通过 -g 参数指定为直连路由模式(模式)。
IP为192.168.193.226,我们验证Serv是否可连接:
我们发现并不通,在其中一个RS192.168.193.172上抓包:
正如前面所说,LB是通过路由转发的,根据路由的原理,源MAC地址修改为LB的MAC地址,而目标MAC地址修改为RS MAC地址,相当于RS是LB的下一跳。
并且源IP和目标IP都不会修改。问题就来了,我们期望访问的是RS,但RS收到的目标IP却是LB的IP,发现这个目标IP并不是自己的IP,因此不会通过INPUT链转发到用户空间,这时要不直接丢弃这个包,要不根据路由再次转发到其他地方,总之两种情况都不是我们期望的结果。
那怎么办呢?为了让RS接收这个包,必须得让RS有这个目标IP才行。于是不妨在lo上添加个虚拟IP,IP地址伪装成LB IP 192.168.193.197:
问题又来了,这就相当于有两个相同的IP,IP重复了怎么办?办法是隐藏这个虚拟网卡,不让它回复ARP,其他主机的neigh也就不可能知道有这么个网卡的存在了,参考 Using arp announce/arp ignore to disable ARP 。
此时再次从客户端c:
终于通了。
我们从前面的抓包中知道,源IP为 IP 192.168.193.226,因此直接回包给即可,不可能也不需要再回到LB了,即A->B,B->C,C->A,流量方向是三角形状的,因此这种模式又称为三角模式。
我们从原理中不难得出如下结论:
前面介绍了直连路由模式,要求所有的在同一个子网,而ipip隧道模式则主要解决这种限制,LBIP和RS可以不在同一个子网,此时需要通过ipip隧道进行传输。
现在设有LBIP为 192.168.193.77/25 ,在该上增加一个VIP地址:
ip addr add 192.168.193.48/25 dev 0
有三个RS如下:
如上三个RS子网掩码均为255.255.255.128,即25位子网,显然和VIP 192.168.193.48/25不在同一个子网。
注意到我们的Serv的端口30620和RS的端口是一样的,并且通过 -i 参数指定为ipip隧道模式。
Serv可访问,我们在RS上抓包如下:
我们发现和直连路由一样,源IP和目标IP没有修改。
所以IPIP模式和(Gatewaying)模式原理基本一样,不同的是(Gatewaying)模式要求所有的RS和LB在同一个子网,而IPIP模式则可以支持跨子网的情况,为了解决跨子网通信问题,使用了ipip隧道进行数据传输。
ipvs是一个内核态的四层负载均衡,支持NAT、Gateway以及IPIP隧道模式,Gateway模式性能,但LB和RS不能跨子网,IPIP性能次之,通过ipip隧道解决跨网段传输问题,因此能够支持跨子网。而NAT模式没有限制,这也是一种支持端口映射的模式。
我们不难猜想,由于Kubernetes Serv需要使用端口映射功能,因此kube-proxy必然只能使用ipvs的NAT模式。
使用kubeadm安装Kubernetes可参考文档 Cluster Created by Kubeadm ,不过这个文档的安装配置有问题 kubeadm #1182 ,如下配置不生效:
需要修改为如下配置:
可以通过如下命令确认kube-proxy是否修改为ipvs:
创建一个ClusterIP类似的Serv如下:
ClusterIP 10.96.54.11为我们查看ipvs配置如下:
可见ipvs的LB IP为ClusterIP,算法为rr,RS为Pod的IP。
另外我们发现使用的模式为NAT模式,这是显然的,因为除了NAT模式支持端口映射,其他两种均不支持端口映射,所以必须选择NAT模式。
可见kube-proxy首先会创建一个dummy虚拟网卡kube-ipvs0,然后把所有的Serv IP添加到kube-ipvs0中。
我们知道基于iptables的Serv,ClusterIP是一个虚拟的IP,因此这个IP是ping不通的,但ipvs中这个IP是在每个上真实存在的,因此可以ping通:
当然由于这个IP就是配置在本地虚拟网卡上,所以对诊断问题没有一点用处的。
我们接下来研究下ClusterIP如何传递的。
当我们通过如下命令连接服务时:
此时由于10.96.54.11就在本地,所以会以这个IP作为出口地址,即源IP和目标IP都是10.96.54.11,此时相当于:
其中xxxx为随机端口。
然后经过ipvs,ipvs会从RS ip列中选择其中一个Pod ip作为目标IP,设为10.244.2.2:
我们从iptables LOG可以验证:
我们查看OUTPUT安全组规则如下:
其中ipsetj KUBE-CLUSTER-IP 保存着所有的ClusterIP以及端口。
如上规则的意思就是除了Pod以外访问ClusterIP的包都打上 0x4000/0x4000 。
如上规则的意思就是只要匹配mark 0x4000/0x4000 的包都做SNAT,由于10.244.2.2是从flannel.1出去的,因此源ip会改成flannel.1的ip 10.244.0.0 :
通过Vxlan 隧道发到Pod的Node上,转发给Pod的v,回包通过路由到达源Node,源Node通过之前的MASQUERADE再把目标IP还原为10.96.54.11。
查看Serv如下:
现在设集群外的一个IP 192.168.193.197访问192.168.193.172:32016:可见这条规则的目的是做了一次DNAT,DNAT目标为其中一个Endpoint,即Pod服务。
到达PREROUTING链:
如上4条规则看起来复杂,其实就做一件事,如果目标地址为NodeIP,则把包标记 0x4000 , 0x4000 。
我们查看ipvs:
我们发现和ClusterIP实现原理非常相似,ipvs Serv的VIP为Node IP,端口为NodePort。ipvs会选择其中一个Pod IP作为DNAT目标,这里设为10.244.3.2:
剩下的到了POSTROUTING链就和Serv ClusterIP完全一样了,只要匹配 0x4000/0x4000 的包就会做SNAT。
Kubernetes的ClusterIP和NodePort都是通过ipvs serv实现的,Pod当作ipvs serv的server,通过NAT MQSQ实现转发。
简单来说kube-proxy主要在所有的Node做如下三件事:
使用ipvs作为kube-proxy后端,不仅提高了转发性能,结合ipset还使iptables规则变得更“干净”清楚,从此再也不怕iptables。
更多关于kube-proxy ipvs参考 IPVS-Based In-Cluster Load Balancing Deep Dive .
本文首先介绍了kube-proxy的功能以及kube-proxy基于iptables的实现原理,然后简单介绍了ipvs,了解了ipvs支持的三种转发模式,介绍了kube-proxy基于ipvs的实现原理。
ipvs是专门设计用来做内核态四层负载均衡的,由于使用了hash表的数据结构,因此相比iptables来说性能会更好。基于ipvs实现Serv转发,Kubernetes几乎能够具备无限的水平扩展能力。随着Kubernetes的部署规模越来越大,应用越来越广泛,ipvs必然会取代iptables成为Kubernetes Serv的默认实现后端。
转自
vxlan和vlan的区别有哪些
到了POSTROUTING链:vxlan和vlan区别是:
但是其实ipvsadm相对iptables命令简直太简单了,因为没有像iptables那样存在各种table,table嵌套各种链,链里串着一堆规则,ipvsadm就只有两个核心实体,分别为serv和server,serv就是一个负载均衡实例,而server就是后端member,ipvs术语中叫做real server,简称RS。VXLAN是一种网络虚拟化技术,可以改进大型云计算在部署时的扩展问题,是对VLAN的一种扩展。VXLAN是一种功能强大的工具,可以穿透三层网络对二层进行扩展。它可通过封装流量并将其扩展到第三层,以此来解决VMS(虚拟内存系统)的可移植性限制,使其可以访问在外部IP子网上的。
VLAN(Virtual Local Area Network)的中文名为"虚拟局域网"。
虚拟局域网(VLAN)是一组逻辑上的设备和用户,这些设备和用户并不受物理位置的限制,可以根据功能、部门及应用等因素将它们组织起来,相互之间的通信就好像它们在同一个网段中一样,由此得名虚拟局域网。
基本原理
VXLAN采取了将原始以太网报文封装在UDP数据包里的封装格式。将原来的二层数据帧加上VXLAN头部一起封装在一个UDP数据包里。
VXLAN头部包含有一个VXLAN标识(即VNI,VXLAN Network Identifier),只有在同一个VXLAN上的虚拟机之间才能相互通信。VNI在数据包之中占24比特,故可支持1600万个VXLAN的同时存在,远多于VLAN的4094个,因此可适应大规模租户的部署。
VXLAN一般通过安装在上的软件实现报文的封装与解封装,网络只要IP路由可达即可。VXLAN实现了应用与物理网络的解耦,但网络与虚拟机还是相互的。业界一般通过网络(如SDN,Software Defined Network)实现VXLAN网络与云业务的联动。
当虚拟机发生迁移后,虚机/存储会把虚拟机迁移信息通知给网络,网络根据虚拟机迁移的新位置,重新调整网络配置,从而实现网络与云业务的联动。也就是说,物理网络可以是传统的三层IP网络,路由可达即可。
虚拟机可跨三层IP网络远距离迁移,不再受限于二层技术。物理网络也无需允许所有VLAN通过。接入交换机需要学习的MAC地址的数量也大大减少,削弱了网络设备MAC地址表项规格对虚拟机规模的约束。
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系 836084111@qq.com 删除。