VIP Load Balance via iptables on Linux

这里所谓的VIP load balance via iptables,是指在CentOS 7系统上,基于iptables规则,利用VNI(Virtual Network Interface)创建的VIP(Virtual IP),实现网络流量的负载均衡。

========================================================================

Basic Concepts

负载均衡:建立在现有网络结构之上,它提供了一种廉价有效透明的方法扩展网络设备和服务器的带宽、增加吞吐量、加强网络数据处理能力、提高网络的灵活性和可用性[1]。
负载均衡,英文名称为Load Balance,其意思就是分摊到多个操作单元上进行执行,例如Web服务器、FTP服务器、企业关键应用服务器和其它关键任务服务器等,从而共同完成工作任务[1]。
[1]Load Balance, https://baike.baidu.com/item/%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1

三种常见的网络负载均衡模型:
1. NAT (Network Address Translation):
VS NAT(Virtual Server via NAT)是一种最简单的方式,所有的RealServer只需要将自己的网关指向Director即可。客户端可以是任意操作系统,但此方式下,一个Director能够带动的RealServer比较有限。在VS/NAT的方式下,Director也可以兼为一台RealServer。
缺点:所 有的数据包都要经由Linux Director结点转入、转出,这样就会产生单结点的瓶颈
优点: Real Servers组成的网络既可以是Internet,也可以是Intranet,而且其网络拓扑、系统架构等可以与End User分离。
NAT LB

2.DR (Direct Routing):
VS DR(Virtual Server via DR)方式是通过改写请求报文中的MAC地址部分来实现的。Director和RealServer必需在物理上有一个网卡通过不间断的局域网相连。 RealServer上绑定的VIP配置在各自Non-ARP的网络设备上(如lo或tunl),Director的VIP地址对外可见,而RealServer的VIP对外是不可见的。RealServer的地址即可以是内部地址,也可以是真实地址。
缺点:如果需要Real Servers直接返回信息给End User,那么就需要保证这两者处在同一网络,Director和Real Servers也在一个网络中
优点: Linux Director不需要拆解或是修改数据包,而是直接将数据包转发到相应的端口,而这个端口指明了某一Real Server,单点问题很小
DR LB

3.IP Tunnelling:
IP隧道(IP tunneling)是将一个IP报文封装在另一个IP报文的技术,这可以使得目标为一个IP地址的数据报文能被封装和转发到另一个IP地址。IP隧道技术亦称为IP封装技术(IP encapsulation)。IP隧道主要用于移动主机和虚拟私有网络(Virtual Private Network),在其中隧道都是静态建立的,隧道一端有一个IP地址,另一端也有唯一的IP地址。它的连接调度和管理与VS/NAT中的一样,只是它的报文转发方法不同。调度器根据各个服务器的负载情况,动态地选择一台服务器,将请求报文封装在另一个IP报文中,再将封装后的IP报文转发给选出的服务器;服务器收到报文后,先将报文解封获得原来目标地址为 VIP 的报文,服务器发现VIP地址被配置在本地的IP隧道设备上,所以就处理这个请求,然后根据路由表将响应报文直接返回给客户。
缺点:对IP包再封装,增大了IP包的大小
优点:对IP包的再封装,使得Director和Real Servers可以在不同的网络中

References:
[1] http://www.ultramonkey.org/papers/lvs_tutorial/html/
[2] http://soft.chinabyte.com/25/13169025.shtml

========================================================================
基于Linux LVS(Linux Virtual Server)的负载均衡的实现:
VIP(Virtual IP)
VIPS(Virtual IP Server)
请参考:http://www.ultramonkey.org/papers/lvs_tutorial/html/

========================================================================

Load Balance Based on IPtables

Preparations

动态开启主机的数据转发功能:
sudo sysctl net.ipv4.ip_forward=1

集群模型:一台HOST机,其上运行多个Containers作为Real Servers,它们通过bridge模式与HOST机相连

HTTP服务返回网页文件index.html:

<!DOCTYPE html>
<html>
<body>
container: 192.168.0.100
<body>
</html>
1. NAT

Containers的创建及HTTP服务的启动,Director也作为一个Real Server运行服务:

## 在一台物理机上新建swarm集群
sudo docker swarm init

## 新建bridge网络
sudo docker create --driver bridge --subnet 192.168.0.0/24 --attachable lvs-lan

## 容器启动
docker run -itd --privileged --network lvs-lan --hostname rerver1 --ip 192.168.0.10 --name server1 mlp:lvs /bin/bash
docker run -itd --privileged --network lvs-lan --hostname rerver2 --ip 192.168.0.11 --name server2 mlp:lvs /bin/bash
docker run -itd --privileged --network lvs-lan --hostname rerver3 --ip 192.168.0.100 --name server3 mlp:lvs /bin/bash

## 通过NCat工具模拟HTTP服务并监听80端口,在Director及Real Servers执行如下命令:
while((1)) do nc -4 -lvn localhost 80 < index.html; done

下面开始配置NAT模式的Load Balance:
The following example load balances the HTTP traffic to three different ip-address. For every 4th packet, it is load balanced to the appropriate server (using the counter 0).

## Director和Real Servers的定义如下:
##    D : 192.168.0.100
##    RS: 192.168.0.10 192.168.0.11
## 在Director容器中配置IP路由转发规则,分别是192.168.0.10、192.168.0.11,监听端口为80
sudo iptables -t nat -A PREROUTING -p tcp -i eth0 --dport 80 -m state --state NEW -m statistic --mode nth --every 4 --packet 0 -j DNAT --to-destination 192.168.0.10:80

sudo iptables -t nat -A PREROUTING -p tcp -i eth0 --dport 80 -m state --state NEW -m statistic --mode nth --every 4 --packet 1 -j DNAT --to-destination 192.168.0.11:80

## 设置数据包流出时,改写IP包的目标地址
sudo iptables -t nat -A POSTROUTING -j MASQUERADE

## 更新iptables中的规则
sudo iptables-save

## 配置完成后,可以使用如下的命令来查看路由转发规则,下面只截取了新添加的规则信息
[mlp@rerver3 ~]$ /usr/bin/sudo iptables --list-rules -t nat
-A PREROUTING -i eth0 -p tcp -m tcp --dport 80 -m state --state NEW -m statistic --mode nth --every 4 --packet 0 -j DNAT --to-destination 192.168.0.10:80
-A PREROUTING -i eth0 -p tcp -m tcp --dport 80 -m state --state NEW -m statistic --mode nth --every 4 --packet 1 -j DNAT --to-destination 192.168.0.11:80
-A POSTROUTING -j MASQUERADE

获取Docker的宿主机上,执行如下命令来访问容器中的HTTP服务:

[root@mercury-72ns3 ~]# curl 192.168.0.100:80
<!DOCTYPE html>
<html>
<body>
container: 192.168.0.11
<body>
</html>
[root@mercury-72ns3 ~]# curl 192.168.0.100:80
<!DOCTYPE html>
<html>
<body>
container: 192.168.0.10
<body>
</html>
[root@mercury-72ns3 ~]# curl 192.168.0.100:80
<!DOCTYPE html>
<html>
<body>
container: 192.168.0.100
<body>
</html>

从上面的结果可以看到,访问192.168.0.100端口服时,返回的是两个Real Servers的信息,符合预期。

而在客户机访问80端口时,使用tcpdump监听客户机的相应端口时采集的部分TCP转发信息如下:
11:50:56.737713 IP 192.168.0.1.21020 > 192.168.0.100.http: Flags [S], seq 2870451237, win 14600, options [mss 1460,nop,nop,sackOK,nop,wscale 9], length 0
11:50:56.737731 IP 192.168.0.1.21020 > 192.168.0.100.http: Flags [S], seq 2870451237, win 14600, options [mss 1460,nop,nop,sackOK,nop,wscale 9], length 0
11:50:56.737780 IP 192.168.0.100.21020 > 192.168.0.10.http: Flags [S], seq 2870451237, win 14600, options [mss 1460,nop,nop,sackOK,nop,wscale 9], length 0
11:50:56.737797 IP 192.168.0.1.21020 > 192.168.0.10.http: Flags [S], seq 2870451237, win 14600, options [mss 1460,nop,nop,sackOK,nop,wscale 9], length 0
11:50:56.737834 IP 192.168.0.10.http > 192.168.0.1.21020: Flags [S.], seq 2798174341, ack 2870451238, win 14600, options [mss 1460,nop,nop,sackOK,nop,wscale 9], length 0
11:50:56.737843 IP 192.168.0.10.http > 192.168.0.100.21020: Flags [S.], seq 2798174341, ack 2870451238, win 14600, options [mss 1460,nop,nop,sackOK,nop,wscale 9], length 0
11:50:56.737854 IP 192.168.0.100.http > 192.168.0.1.21020: Flags [S.], seq 2798174341, ack 2870451238, win 14600, options [mss 1460,nop,nop,sackOK,nop,wscale 9], length 0
11:50:56.737854 IP 192.168.0.100.http > 192.168.0.1.21020: Flags [S.], seq 2798174341, ack 2870451238, win 14600, options [mss 1460,nop,nop,sackOK,nop,wscale 9], length 0

从上面的打印信息可以看到NAT模式的转发路由过程如下:
1. 由于是在docker的宿主机上访问的,而192.168.0.100是通过bridge网络与宿主机相连,所以TCP请求的源路由地址被设置为了为192.168.0.1,端口为随机端口21020
2. TCP包传给Director,192.168.0.1.21020 > 192.168.0.100.http
3. Director收到socket包后,传给后端的Server,192.168.0.100.21020 > 192.168.0.10.http
4. 192.168.0.10的默认网关为192.168.0.1,所以这里又会经历一个中转,192.168.0.1.21020 > 192.168.0.10.http
5. Server1收到socket包后,返回确认信息,首先通过网关192.168.0.10.http > 192.168.0.1.21020,
6. 然后是192.168.0.10.http > 192.168.0.100.21020
7. 最后传给目标机,也就是宿主机192.168.0.1.21020
至此,一个简单的NAT模式的负载均衡网络构建成功。

另外一种使用Connmark实现的更复杂的负载均衡模型的References:
[1] Netfilter Connmark, http://home.regit.org/netfilter-en/netfilter-connmark/

VIP(Virtual IP)

  1. 在CentOS 7中创建临时的虚拟网络接口
    通过ifconfig命令,可以很便捷的创建一个临时的虚拟网络接口,示例语法:
    ifconfig eth0:0 192.168.0.2
    eth0:0指明了这个临时接口是基于eth0的,也就是说除了IP地址(IPADDR)不一样外,这个接口配置信息和/etc/sysconfig/network-scripts/ifcfg-eth0中的内容是一样的。
[mlp@rerver3 ~]$ /usr/bin/sudo ifconfig eth0:0 155.155.0.123 netmask 255.255.255.0
[mlp@rerver3 ~]$ ifconfig 
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.0.100  netmask 255.255.255.0  broadcast 0.0.0.0
        ether 02:42:c0:a8:00:64  txqueuelen 0  (Ethernet)
        RX packets 592  bytes 43463 (42.4 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 586  bytes 44836 (43.7 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

eth0:0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 155.155.0.123  netmask 255.255.0.0  broadcast 155.155.255.255
        ether 02:42:c0:a8:00:64  txqueuelen 0  (Ethernet)

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        loop  txqueuelen 0  (Local Loopback)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

[mlp@rerver3 ~]$ ping 155.155.0.123
PING 155.155.0.123 (155.155.0.123) 56(84) bytes of data.
64 bytes from 155.155.0.123: icmp_seq=1 ttl=64 time=0.070 ms
64 bytes from 155.155.0.123: icmp_seq=2 ttl=64 time=0.051 ms
^C
--- 155.155.0.123 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 999ms
rtt min/avg/max/mdev = 0.051/0.060/0.070/0.012 ms
  1. 在CentOS 7中创建持久的虚拟网络接口:
## 查看网络接口信息
[mlp@rerver3 ~]$ ifconfig eth0
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.0.100  netmask 255.255.255.0  broadcast 0.0.0.0
        ether 02:42:c0:a8:00:64  txqueuelen 0  (Ethernet)
        RX packets 592  bytes 43463 (42.4 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 586  bytes 44836 (43.7 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

## 配置ifconfig文件
cd /etc/sysconfig/network-scripts/
cp ifcfg-eth0 ifcfg-eth0:0
sed -i 's/192.168.0.100/155.155.0.123/g' ifcfg-eth0:0

## 重启network服务
systemctl restart network

=========================================================================

VIP Load Balance via iptables的简单实现

通过以上试验的两种技术,即可实现简单的基于VIP的负载均衡(Load Balance),实现思路描述如下:
假设一台物理机,一块网卡eth0,IP为192.168.0.100
1. 创建两个虚拟网络接口

/usr/bin/sudo ifconfig eth0:0 155.155.1.123 netmask 255.255.255.0
/usr/bin/sudo ifconfig eth0:0 155.155.1.124 netmask 255.255.255.0
  1. 配置路由转发规则:
sudo iptables -t nat -A PREROUTING -p tcp -i eth0 --dport 80 -m state --state NEW -m statistic --mode nth --every 4 --packet 0 -j DNAT --to-destination 155.155.1.123:80
sudo iptables -t nat -A PREROUTING -p tcp -i eth0 --dport 80 -m state --state NEW -m statistic --mode nth --every 4 --packet 1 -j DNAT --to-destination 155.155.1.124:80
sudo iptables -t nat -A POSTROUTING -j MASQUERADE
sudo iptables-save
  1. 启动服务
while((1)) do nc -4 -lvn 192.168.0.100 80 < index.html; done
while((1)) do nc -4 -lvn 155.155.1.123 80 < index.html; done
while((1)) do nc -4 -lvn 155.155.1.124 80 < index.html; done
  1. 访问服务
curl 192.168.0.100:80

注:本文只是种简单的VIP模式的负载均衡的实现,更加合理的做法是,在多台HOST上执行IP虚拟化操作,虚拟出一个集群,然后启动服务监听虚拟IP,实现负载均衡,以实现与HOST机的隔离。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值