Overview
基于前面几篇文章的基础之上,我们接下来将要探索OVN中的load balancingz这一特性。但是在开始之前,我们先来回顾一下上一个lab中创建好的拓扑结构。
The lab network
The OVN logical network
The OVN Load Balancer
The OVN load balancer用于为OVN逻辑网络空间中的负载提供基本的负载均衡的功能。由于它的简单特性,它并不是用来替代基于应用的,专有的load balancer,后者往往提供了更多高级特性。
The load balancer利用一种基于哈希的算法来将对于VIP的请求均衡到逻辑地址空间中一个相关的IP地址池中。因为哈希值是根据用户请求的头部计算的,因此均衡的结果会非常随机。而每个用户的请求都会在连接期间和负载池中的某个成员互相绑定。OVN中的Load balancing既可以应用到logical switch中,也可以应用到logical router中。我们需要根据具体的需求来确定在什么地方应用该特性。下面是对各种方法的说明:
当将该特性应用到logical routers时,我们需要考虑以下事项:
- 负载均衡可能被应用到一个"centralized" router(或者说一个gateway router)
- 基于上一点,路由器中的负载均衡将不是一个分布式的服务
当将该特性应用到logical switch时,我们需要考虑以下事项:
- 负载均衡是“分布式”的,它可能会应用到多个OVS hosts中
- logical switch上的负载均衡只能被应用于来自VIF的流量。这意味着它只能用于"client" logical switch而不是"server" logical switch
- 基于上一点,你可能需要根据你设计所需的扩展性将负载均衡应用到多个logical switch中
Using Our Fake "VMs" as Web Servers
为了模拟load balancer,我们需要在"dmz"上创建一对web server,每一个server都提供可识别的服务。为了让演示更为简单,我们将在vm1/vm2的namespace中用一行python代码来启动一个web server。下面就来启动我们的web servers。
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 server,并且在TCP端口8000进行监听,它会通过显示不同的文件内容来标识不同的虚拟机。
同时我们还想要测试到达web server的连通性。对此,我们将在Ubuntu host的global namespace利用curl进行检测。确保已经安装了curl命令
apt-get -y install curl
Configuring the Load Balancer Rules
首先,我们需要定义load balancing rules,VIP以及后端的IP池。下文命令的内容就是在OVN northbound DB中创建一个记录,并且获取它的UUID。为了测试,我们将使用"data" network中的10.127.0.254作为VIP,并且将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
上述命令在northbound DB的load_balancer表中创建了一个记录,并且将结果UUID存放在了变量"uuid"中。我们将在下面的命令中引用该变量。
The Gateway Router As a Load Balancer
首先,让我们将load balancer profile应用到OVN gateway router "edge1"中
ubuntu1
ovn-nbctl set logical_router edge1 load_balancer=$uuid
我们可以通过如下命令来确认
ovn-nbctl get logical_router edge1 load_balancer
现在,从任意Ubuntu host的global namespace中,我们都能连接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 server会发生什么。因此我们停止了vm1 namespace中的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
我们可以发现,the load balancer并不会做任何健康检查。因为我们现在假设健康检查将由Kubernetes这样的编排方案来解决,但是我们可以相信,这个特性会在以后添加进来的。
在进行下一个测试前先重启vm1中的python web server。
负载均衡在外部是可以正常工作的,接着我们来看看,从内部的虚拟机访问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 network的拓扑结构,再仔细想想在vm3上发出curl请求之后的网络流。同时再观察一下python web server的日志。我的日志如下所示:
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 -
我们来看一下日志中的client IP address。第一个IP来自ubuntu1,而第二个IP则是edge1。但是为什么请求来自edge1而不是直接来自vm3呢?这是因为实现OVN负载均衡特性的开发者考虑了所谓的"proxy mode",对于这种模式,某些情况下,load balancer会隐藏client side IP。那么为什么要这么做呢?想想如果web server看到了vm3的真实的IP会怎么样。那么server的应答会直接路由到vm3,绕过edge1中的load balancer。从vm3的角度来看,它对VIP发出了一个请求,但是却从其中一个web server收到了应答,用的是web server的真实的IP地址。这显然不是我们想要的,这也就是proxy-mode存在的原因。
现在让我们先删除load balancer profile,进入下一轮的实验。
Configure the Load Balancer On a Logical Switch
接下去让我们来看看,将load balancing rule应用到各个logical switch中会有什么情况。因为之前我们从edge移除了load balancing,因此我们要做的第一步就是用internal VIP创建一个新的load balancer profile。这次我们将使用172.16.255.62。
ubuntu1
uuid=`ovn-nbctl create load_balancer vips:172.16.255.62="172.16.255.130,172.16.255.131"` echo $uuid
首先,我们将它设置到"inside" 这个logical switch
ubuntu1
# apply and verify ovn-nbctl set logical_switch inside load_balancer=$uuid ovn-nbctl get logical_switch inside load_balancer
从vm3测试连通性(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
看起来好像工作正常。接着将load balancer从"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发起测试(vm1位于"dmz"中)
root@ubuntu2:~# ip netns exec vm1 curl 172.16.255.62:8000 ^C
结果同样不令人满意。这也就说明负载均衡应该设置到用户的logical switch而不是server的logical switch
最后,清理配置
ubuntu1
ovn-nbctl clear logical_switch dmz load_balancer ovn-nbctl destroy load_balancer $uuid
Final Words
基础的负载均衡是一个非常好的特性。将它内置于OVN中意味着在部署你自己的SDN时可以减少一些依赖。尽管这个特性非常小,但是我认为它已经覆盖了绝大多数客户的需求。希望经过一段时间后,它的某些限制,例如缺少健康检查,能够被解决。
在下一篇文章中,我将进一步探索OVN中的网络安全相关的内容
原文链接:http://blog.spinhirne.com/2016/09/the-ovn-load-balancer.html