Appearance
VIP + LVS-NAT 案例
1. 环境准备
使用 VMware 搭建三台虚拟机(均采用 Debian 12 系统):
Director1
- 服务网络:IP
10.10.0.11/24,VIP10.10.0.20,网关10.10.0.1 - LVS-NAT 网络:IP
192.168.211.11/24,VIP192.168.211.20,无网关
- 服务网络:IP
Director2
- 服务网络:IP
10.10.0.12/24,VIP10.10.0.20,网关10.10.0.1 - LVS-NAT 网络:IP
192.168.211.12/24,VIP192.168.211.20,无网关
- 服务网络:IP
Real Server
- 管理网络(可选):IP
10.10.0.13/24,网关10.10.0.1 - LVS-NAT 网络:IP
192.168.211.13/24,无网关
- 管理网络(可选):IP
1.1. Real Server 单/双网卡
虽然 Real Server 仅需一个网卡(用于 LVS-NAT 配置)即可,但为了便于管理和实现更精细的流量分流(例如,使公网流量通过其他网关而不经过 Director),我们为其额外配置了一张网卡。
单网卡配置:
将 Real Server 的默认网关设置为 LVS-NAT VIP(
192.168.211.20),以确保响应流量经过 Director。双网卡配置:
首先将默认网关设置为管理网络的网关;
为了确保响应到服务网络的流量经过 Director,可采取以下两种方法:
- 在 Real Server 上配置特定的路由规则;
- 在 Director 上配置
iptablesSNAT,以实现类似 FULLNAT 的效果;
但上述两种方式均有各自的优缺点,后续再做进一步的说明。
2. 配置步骤
2.1. Director
网卡配置:
Bash$ sudo nano /etc/network/interfacesDirector1:
Bash# The service network interface allow-hotplug ens33 iface ens33 inet static address 10.10.0.11 netmask 255.255.255.0 gateway 10.10.0.1 dns-nameservers 218.85.152.99 # LVS-NAT network interfaces allow-hotplug ens36 iface ens36 inet static address 192.168.211.11 netmask 255.255.255.01
2
3
4
5
6
7
8
9
10
11
12
13Director2:
Bash# The service network interface allow-hotplug ens33 iface ens33 inet static address 10.10.0.12 netmask 255.255.255.0 gateway 10.10.0.1 dns-nameservers 218.85.152.99 # LVS-NAT network interfaces allow-hotplug ens36 iface ens36 inet static address 192.168.211.12 netmask 255.255.255.01
2
3
4
5
6
7
8
9
10
11
12
13
Warning:Director 上 LVS-NAT 网卡不需要配置网关。
启用 IP 转发:
Bash$ echo "net.ipv4.ip_forward = 1" | sudo tee -a /etc/sysctl.confBash$ sudo sysctl -p安装
keepalived:Bash$ sudo apt update && sudo apt install keepalived -y配置
/etc/keepalived/keepalived.conf:Bash$ sudo touch /etc/keepalived/keepalived.confBash$ sudo nano /etc/keepalived/keepalived.confDirector1:
Nginxglobal_defs { router_id LVS_NAT1 } vrrp_instance VI_1 { state MASTER interface ens33 virtual_router_id 51 priority 100 advert_int 1 authentication { auth_type PASS auth_pass 123456 } virtual_ipaddress { 10.10.0.20 # Service Network VIP } } vrrp_instance VI_2 { state MASTER interface ens36 virtual_router_id 61 priority 100 advert_int 1 authentication { auth_type PASS auth_pass 123456 } virtual_ipaddress { 192.168.211.20 # LVS-NAT Network VIP } } virtual_server 10.10.0.20 80 { # Service Network VIP delay_loop 6 lb_algo rr lb_kind NAT protocol TCP real_server 192.168.211.13 8081 { # Real Server 1 weight 1 TCP_CHECK { connect_timeout 3 nb_get_retry 3 delay_before_retry 3 } } real_server 192.168.211.13 8082 { # Real Server 2 weight 1 TCP_CHECK { connect_timeout 3 nb_get_retry 3 delay_before_retry 3 } } real_server 192.168.211.13 8083 { # Real Server 3 weight 1 TCP_CHECK { connect_timeout 3 nb_get_retry 3 delay_before_retry 3 } } }Note:关于配置文件的详细说明可以参考这篇文章。
这里我们需要配置两个 VIP,
VI_1作为服务网络中客户端请求的服务 IP,VI_2作为 LVS-NAT 网络的网关 IP(即当前的 Master Director)。此外,虚拟服务器(virtual_server)的 IP 应该与VI_1的 VIP 保持一致。Director2:
diffglobal_defs { - router_id LVS_NAT1 + router_id LVS_NAT2 } vrrp_instance VI_1 { - state MASTER + state BACKUP interface ens33 virtual_router_id 51 - priority 100 + priority 50 advert_int 1 authentication { auth_type PASS ... } vrrp_instance VI_2 { - state MASTER + state BACKUP interface ens36 virtual_router_id 61 - priority 100 + priority 50 advert_int 1 authentication { auth_type PASS ...这里有几个关键点:
global_defs.router_id:因保持每个实例唯一;- 不同实例中相同的
vrrp_instance组:- 名称建议保持一致(非强制);
- 建议只有一个
MASTER,其余为BACKUP; virtual_router_id应保持一致;priority各不相同,值越大优先级越高(通常MASTER的值最大);
- 同一实例中的
vrrp_instance组之间:- 名称应各不相同;
virtual_router_id应各不相同;
启动
keepalived:Bash$ sudo systemctl enable --now keepalived
2.2. Real Server
网卡配置:
Bash$ sudo nano /etc/network/interfaces单网卡配置:
Bash# LVS-NAT network interfaces allow-hotplug ens36 iface ens36 inet static address 192.168.211.13 netmask 255.255.255.0 gateway 192.168.211.20 # import: LVS-NAT VIP1
2
3
4
5
6Real Server 仅配置单网卡时只需要将默认网关设置为 LVS-NAT VIP(
192.168.211.20),以确保响应流量经过 Director 即可。双网卡配置方案 1,通过路由规则确保响应流量经过 Director:
创建路由表:
Bashecho "100 lvs" | sudo tee -a /etc/iproute2/rt_tables配置网卡、路由规则:
Bash# The manager network interface allow-hotplug ens33 iface ens33 inet static address 10.10.0.13 netmask 255.255.255.0 gateway 10.10.0.1 dns-nameservers 218.85.152.99 # LVS-NAT network interfaces allow-hotplug ens36 iface ens36 inet static address 192.168.211.13 netmask 255.255.255.0 post-up ip route add default via 192.168.211.20 dev ens36 table lvs post-up ip rule add to 10.10.0.0/24 table lvs pre-down ip rule del to 10.10.0.0/24 table lvs pre-down ip route del default via 192.168.211.20 dev ens36 table lvs1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18上述配置中:
- 将默认网关设置为管理网络的网关(只配置管理网络网关,不配置 LVS-NAT 网络网关);
- 配置路由规则:为发送到
10.10.0.0/24网段的流量指定192.168.211.20网关;
这里假定所有客户端的请求都来自
10.10.0.0/24网段。如果有非该网段的客户端请求服务,则会因路由规则不匹配,而使用默认网关(即管理网络的网关)直接发送响应到客户端,这将导致客户端响应异常,因为客户端请求的 IP 与响应的服务器 IP 不一致。双网卡配置方案 2,在 Director 上配置 SNAT:
默认情况下 Director 转发给 Real Server 的数据包并不会修改源 IP,只会将目标 IP 改为 Real Server IP 并转发给它,即 DNAT。我们可以在 Director 上配置
iptablesSNAT,以实现类似 FULLNAT 的效果,这样 Real Server 发送响应数据时自然就会发送回给 Director。首先需要在 Director 上启用 IPVS 连接跟踪(Connection Tracking):
Bash$ echo "net.ipv4.vs.conntrack = 1" | sudo tee -a /etc/sysctl.confBash$ sudo sysctl -p接着在 Director 上配置
iptablesSNAT 规则:Bash$ sudo iptables -t nat -A POSTROUTING -p tcp -d 192.168.211.13 --dport 8081 -j MASQUERADE && \ sudo iptables -t nat -A POSTROUTING -p tcp -d 192.168.211.13 --dport 8082 -j MASQUERADE && \ sudo iptables -t nat -A POSTROUTING -p tcp -d 192.168.211.13 --dport 8083 -j MASQUERADEReal Server 网卡配置:
Bash# The manager network interface allow-hotplug ens33 iface ens33 inet static address 10.10.0.13 netmask 255.255.255.0 gateway 10.10.0.1 dns-nameservers 218.85.152.99 # LVS-NAT network interfaces allow-hotplug ens36 iface ens36 inet static address 192.168.211.13 netmask 255.255.255.0也是只配置管理网络网关,不配置 LVS-NAT 网络网关。
优点是所有网段的客户端 IP 都能正常访问服务而不需要在 Real Server 上进行额外的路由规则配置。但缺点就是,Real Server 将无法看到真实的客户端 IP 地址。
安装 Docker,并启动三个 Nginx 实例:
Bash$ docker run --name nginx1 -d -p 8081:80 -v nginx1-html:/usr/share/nginx/html nginxBash$ docker run --name nginx2 -d -p 8082:80 -v nginx2-html:/usr/share/nginx/html nginxBash$ docker run --name nginx3 -d -p 8083:80 -v nginx3-html:/usr/share/nginx/html nginx修改三个 Nginx 实例的页面,便于后续测试负载均衡效果:
Bash$ docker volume inspect nginx1-htmlBash$ sudo nano /var/lib/docker/volumes/nginx1-html/_data/index.htmlBash$ sudo nano /var/lib/docker/volumes/nginx2-html/_data/index.htmlBash$ sudo nano /var/lib/docker/volumes/nginx3-html/_data/index.html
3. 测试
负载均衡测试:
在客户端上使用服务网络中的 VIP 进行多次请求,能够看到每次展示的页面在三个实例之间进行轮询变换:
Bash$ curl 10.10.0.20 <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> <style> html { color-scheme: light dark; } body { width: 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; } </style> </head> <body> <h1>Welcome to A nginx!</h1> <p>If you see this page, the nginx web server is successfully installed and working. Further configuration is required.</p> <p>For online documentation and support please refer to <a href="http://nginx.org/">nginx.org</a>.<br/> Commercial support is available at <a href="http://nginx.com/">nginx.com</a>.</p> <p><em>Thank you for using nginx.</em></p> </body> </html>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24高可用,自动故障转移测试:
- Director 高可用:任意停机其中一台 Director;
- Real Server 高可用:任意停止其中 1 ~ 2 个 Nginx 实例;
均不影响客户端正常访问服务。