lxm00 2017-05-19
译者简介:郑敏先,就职于诺云系统(上海)有限公司。工作地点为南京的诺云研发中心。担任解决方案工程师。
概述
基于我的上一篇文章,接下来我将介绍OVN的负载平衡特性。 但在开始之前,我们来看看上一个实验中的配置。
OVN 负载均衡器
OVN负载均衡器旨在为OVN逻辑网络空间内的工作负载提供非常基本的负载均衡服务。由于其简单的功能集,它不是设计用于替换那些为高级用例提供更多花里胡哨的功能的硬件负载均衡器。
其它负载均衡器大多使用基于哈希的算法来平衡VIP的请求到逻辑空间内的相关IP地址池。由于哈希算法是使用客户端请求的头来计算的,所以平衡应当是随机性的,其中每个单独的客户端请求在连接的持续时间内始终选择同一个负载均衡池的特定成员。
实验物理网络拓扑:
OVN 逻辑网络拓扑:
OVN中的负载平衡可以应用于逻辑交换机或逻辑路由器。选择何种方式取决于您的具体要求。每种方法都有注意事项。
当应用于逻辑路由器时,需要牢记以下注意事项:
应用于逻辑交换机时,需要牢记以下注意事项:
使用我们的的“伪虚拟机”作为Web服务器
为了演示负载均衡器,我们希望在我们的“dmz”中创建一对Web服务器,Web服务器提供一个可识别它们身份的文件。 为了简化实验,我们将使用在我们的vm1/vm2命名空间中分别运行的一个python web服务器。
让我们启动web服务器吧。
在ubuntu2上:
mkdir /tmp/www echo "i am vm1" > /tmp/www/index.html cd /tmp/www ip netns exec vm1 python -m SimpleHTTPServer 8000
在ubuntu3上:
mkdir /tmp/www echo "i am vm2" > /tmp/www/index.html cd /tmp/www ip netns exec vm2 python -m SimpleHTTPServer 8000
上面的命令将创建一个web服务器,监听TCP 8000。
我们还希望能够测试与我们的网络服务器的连通性。 为此,我们将从Ubuntu主机的全局命名空间使用curl。如果curl还没有被安装,那么需要先安装它。
apt-get -y install curl
配置负载均衡器规则
首先,需要定义我们的负载均衡规则,即VIP和后端服务器IP池。 这里涉及的是在OVN北向数据库中创建一个条目,并捕获生成的UUID。 在的这次实验中,我们将使用位于实验室“数据”网络中的VIP 10.127.0.254。 我们将使用vm1/vm2的地址作为池IP。
在ubuntu1上:
uuid=`ovn-nbctl create load_balancer vips:10.127.0.254="172.16.255.130,172.16.255.131"` echo $uuid
上述命令在北向数据库的load_balancer表中创建一个条目,并将生成的UUID存储到变量“uuid”。 我们将在后面的命令中引用这个变量。
在网关路由器上配置负载均衡
在OVN网关路由器“edge1”上开启负载均衡器功能。
在ubuntu1上:
ovn-nbctl set logical_router edge1 load_balancer=$uuid
您可以通过检查edge1的数据库条目来验证是否成功开启负载均衡器功能。
ovn-nbctl get logical_router edge1 load_balancer
现在,我们可以从任何Ubuntu主机的全局命名空间连接到VIP。
root@ubuntu1:~# curl 10.127.0.254:8000 i am vm2 root@ubuntu1:~# curl 10.127.0.254:8000 i am vm1 root@ubuntu1:~# curl 10.127.0.254:8000 i am vm2
测试多次之后,可以确认负载平衡是相当随机的。
让我们看看禁用一个Web服务器会发生什么。 尝试停止在vm1命名空间中运行的python进程。 这是我得到的输出结果:
root@ubuntu1:~# curl 10.127.0.254:8000 curl: (7) Failed to connect to 10.127.0.254 port 8000: Connection refused root@ubuntu1:~# curl 10.127.0.254:8000 i am vm2
如您所见,负载均衡器未执行任何类型的运行状态检查。 目前的计划是,运行状态检查将由协调解决方案(如Kubernetes)执行,该功能将在未来某个时间点被加入。
在进行下一个测试之前,在vm1上重新启动python Web服务器。
负载均衡器在虚拟机外部运行着,让我们来看看从内部虚拟机访问VIP时会发生什么。
在ubuntu2上调用vm3的curl:
root@ubuntu2:~# ip netns exec vm3 curl 10.127.0.254:8000 i am vm1 root@ubuntu2:~# ip netns exec vm3 curl 10.127.0.254:8000 i am vm2
很棒, 这似乎也正常工作了,但有个地方很有意思。 来看我们的OVN网络的逻辑图,并考虑来自vm3的curl请求的流量。 另外,看看python web服务器的部分日志:
10.127.0.130 - - [29/Sep/2016 09:53:44] "GET / HTTP/1.1" 200 - 10.127.0.129 - - [29/Sep/2016 09:57:42] "GET / HTTP/1.1" 200 -
注意日志中的客户端IP地址。第一个IP是上一轮测试的ubuntu1。第二个IP是edge1(来自vm3的请求)。为什么请求来自edge1而不是直接来自vm3?答案是,实现负载平衡的OVN开发人员使用了一种称为“代理模式”的方法,其中负载均衡器在某些情况下隐藏了客户端IP。为什么这是必要的?想想如果Web服务器看到vm3的真实IP会发生什么。来自服务器的响应将直接路由回到vm3,绕过edge1上的负载均衡器。从vm3的角度来看,它看起来像是向VIP发出请求,但收到了来自其中一个Web服务器的真实IP的回复。(如果不使用代理模式)负载均衡器就不工作了,这就是为什么代理模式功能很重要。
为了进行第二轮测试,先删除负载均衡器配置
ovn-nbctl clear logical_router edge1 load_balancer ovn-nbctl destroy load_balancer $uuid
在逻辑交换机上配置负载均衡
接下来的实验将负载均衡规则应用到逻辑交换机,会发生什么呢? 由于我们将负载均衡从边缘移开,第一步需要创建一个带有内部VIP的新的负载均衡器。 我们将使用172.16.255.62作为VIP。
在ubuntu1上:
uuid=`ovn-nbctl create load_balancer vips:172.16.255.62="172.16.255.130,172.16.255.131"` echo $uuid
第一个测试:将负载均衡器应用于“内部”逻辑交换机。
在ubuntu1上:
# apply and verify ovn-nbctl set logical_switch inside load_balancer=$uuid ovn-nbctl get logical_switch inside load_balancer
然后从vm3测试(位于“inside”):
root@ubuntu2:~# ip netns exec vm3 curl 172.16.255.62:8000 i am vm1 root@ubuntu2:~# ip netns exec vm3 curl 172.16.255.62:8000 i am vm1 root@ubuntu2:~# ip netns exec vm3 curl 172.16.255.62:8000 i am vm2
实验貌似成功了。
再从“inside”删除负载均衡器,并将其应用于“dmz”。在ubuntu1上:
ovn-nbctl clear logical_switch inside load_balancer ovn-nbctl set logical_switch dmz load_balancer=$uuid ovn-nbctl get logical_switch dmz load_balancer
然后再次从 vm3测试:
root@ubuntu2:~# ip netns exec vm3 curl 172.16.255.62:8000 ^C
不好,它挂起了。 那我们试试从vm1(它也驻留在“dmz”)测试:
root@ubuntu2:~# ip netns exec vm1 curl 172.16.255.62:8000 ^C
也不行。 这强烈说明了对客户端的逻辑交换机而不是服务器的逻辑交换机应用负载平衡的要求。一定要清理环境。
在ubuntu1上:
ovn-nbctl clear logical_switch dmz load_balancer ovn-nbctl destroy load_balancer $uuid