原理看懂和能把服务跑起来是两件事。这篇只讲动手:NAT 与 DR 两种模式各一套完整实验,从网络拓扑、web 节点准备、LVS 规则下发,到
ipvsadm -Ln核实与 90 次请求验证,命令带注释、输出带解析。DR 那套的重点是「VIP 挂在哪个网卡、ARP 参数为什么必须关」,这是最容易配错的一步。原理部分见姊妹篇《LVS 凭什么比 Nginx 快?四种工作模式与调度算法拆开讲》。命令与选项的原意见文末速查表。
本文概要:
| 项目 | 内容 |
|---|---|
| 文章主题 | LVS 实操篇:NAT 模式整套实验(拓扑 → 配置 → 轮询 → 加权轮询 → 排错)与 DR 模式整套实验(dummy 网卡 + ARP 参数 + 启停脚本) |
| 所属类别 | Linux 系统管理 → Web 服务 → LVS 负载均衡 |
| 知识关键字 | ipvsadm·-A·-a·-E·-e·-m·-g·-w·dummy·arp_ignore·arp_announce·nmcli |
两套实验共用同一套主机规划,差别在网关注向哪、以及 DR 多了一步「RS 上配 VIP 并关 ARP」。
一、通用准备:主机规划与 web 节点
两套实验的拓扑与地址完全相同。
| 主机名 | IP 地址 | 服务器角色 |
|---|---|---|
| client2.zhb.cloud | 10.1.1.21 | 客户端 |
| client1.zhb.cloud | 10.1.8.21 | 客户端 |
| router.zhb.cloud | 10.1.1.20、10.1.8.20 | 路由器 |
| lvs.zhb.cloud | 10.1.1.10、10.1.8.10 | LVS 服务器 |
| web1.zhb.cloud | 10.1.8.11 | Web 服务器 |
| web2.zhb.cloud | 10.1.8.12 | Web 服务器 |
| web3.zhb.cloud | 10.1.8.13 | Web 服务器 |
网络约定三条:
- 所有主机第一块网卡为
ens33,第二块为ens36; - 第一块网卡模式为 NAT,第二块为 hostonly;
- 网关按网段走:
10.1.1.0/24指向10.1.1.x、10.1.8.0/24指向10.1.8.x,.10(NAT 实验)还是.20(DR 实验)见对应章节。
实验前提:关闭 SELinux、关闭 firewalld。
三台 web 都要装好 nginx 并写好测试页:
[root@web1-3 ~]# yum install -y nginx echo Welcome to $(hostname) > /usr/share/nginx/html/index.html systemctl enable nginx.service --now # 从客户端确认三台都活着 [root@client1 ~]# curl 10.1.8.11 Welcome to web1.zhb.cloud [root@client1 ~]# curl 10.1.8.12 Welcome to web2.zhb.cloud [root@client1 ~]# curl 10.1.8.13 Welcome to web3.zhb.cloud二、实验一:NAT 模式
本实验的网关指向 LVS 服务器(.10),这正是 NAT 模式的要求。
2.1 配置网关
# 10.1.8.0/24 网段网关为 10.1.8.10 nmcli connection modify ens33 ipv4.gateway 10.1.8.10 nmcli connection up ens33 # 10.1.1.0/24 网段网关为 10.1.1.10 nmcli connection modify ens33 ipv4.gateway 10.1.1.10 nmcli connection up ens332.2 配置 LVS
[root@lvs ~]# # 开启路由转发,NAT 模式必须开 echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf sysctl -p # 安装 ipvsadm yum install -y ipvsadm # ipvsadm.service 启动时会执行 ipvsadm-restore 读这个文件; # 文件不存在会导致启动失败,所以先建一个空的 touch /etc/sysconfig/ipvsadm systemctl enable ipvsadm --now # 创建轮询集群服务 ipvsadm -A -t 10.1.1.10:80 -s rr # 给虚拟 IP 添加三台后端真实主机,模式 masquerade(NAT) ipvsadm -a -t 10.1.1.10:80 -r 10.1.8.11 -m ipvsadm -a -t 10.1.1.10:80 -r 10.1.8.12 -m ipvsadm -a -t 10.1.1.10:80 -r 10.1.8.13 -m # 保存转发规则到文件 ipvsadm-save -n > /etc/sysconfig/ipvsadm2.3 核实与验证
# 核实配置是否生效 [root@lvs ~]# ipvsadm -Ln IP Virtual Server version 1.2.1 (size=4096) Prot LocalAddress:Port Scheduler Flags -> RemoteAddress:Port Forward Weight ActiveConn InActConn TCP 10.1.1.10:80 rr -> 10.1.8.11:80 Masq 1 0 0 -> 10.1.8.12:80 Masq 1 0 0 -> 10.1.8.13:80 Masq 1 0 0Forward列显示Masq,说明当前是 NAT 模式。90 次请求验证轮询:
[root@client2 ~]# for i in {1..90};do curl -s 10.1.1.10 ;done|sort|uniq -c 30 Welcome to web1.zhb.cloud 30 Welcome to web2.zhb.cloud 30 Welcome to web3.zhb.cloud三台各 30,均分。
2.4 改成加权轮询
[root@lvs ~]# # 把调度算法改成带权重的轮询 ipvsadm -E -t 10.1.1.10:80 -s wrr # web2 权重设为 2,web3 权重设为 3 ipvsadm -e -t 10.1.1.10:80 -r 10.1.8.12 -m -w 2 ipvsadm -e -t 10.1.1.10:80 -r 10.1.8.13 -m -w 3 # 再跑 90 次 [root@client2 ~]# for i in {1..90};do curl -s 10.1.1.10 ;done|sort|uniq -c 15 Welcome to web1.zhb.cloud 30 Welcome to web2.zhb.cloud 45 Welcome to web3.zhb.cloud15 : 30 : 45 正好是 1 : 2 : 3,权重生效(ipvsadm -Ln的 Weight 列同步显示 1、2、3)。
2.5 同网段客户端为什么访问不通
现象:client2(10.1.1.0/24)访问 VIP 正常,client1(10.1.8.0/24)访问10.1.1.10不通。
原因:client1的数据包确实被 ipvs 处理并转给了后端。但后端 web 按来源地址10.1.8.21回包时走的是直连路由,于是响应直接发给了 client1。它没经过 LVS、源地址也不是 VIP,客户端自然拼不出完整会话。
解法:在后端 web 上补一条到10.1.8.21的主机路由,强制回包走 LVS。
[root@web1-3 ~]# nmcli connection modify ens33 ipv4.routes '10.1.8.21 255.255.255.255 10.1.8.10' [root@web1-3 ~]# nmcli connection up ens33这也正是 NAT 模式「RS 网关必须指向 DIP」那条约束的由来。
三、实验二:DR 模式
与 NAT 实验的三个差别:网关指向 router(.20)而不是 LVS;RS 上要加 dummy 网卡承载 VIP;RS 要关掉 VIP 的 ARP 响应。
3.1 配置网关与 router
# 10.1.8.0/24 网段网关为 10.1.8.20 nmcli connection modify ens33 ipv4.gateway 10.1.8.20 nmcli connection up ens33 # 10.1.1.0/24 网段网关为 10.1.1.20 nmcli connection modify ens33 ipv4.gateway 10.1.1.20 nmcli connection up ens33 # router 上开启路由转发 echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf sysctl -p3.2 配置 LVS-RS:VIP 与 ARP 参数
三台后端主机都要做同样配置:
[root@web1-3 ~]# # 加一块 dummy 网卡承载 VIP,子网掩码必须是 32 位 nmcli connection add type dummy ifname dummy con-name dummy ipv4.method manual ipv4.addresses 10.1.8.100/32 nmcli connection up dummy # 配置 arp 参数,禁止用 dummy 网卡去响应 VIP 的 ARP 请求 cat >> /etc/sysctl.conf << EOF net.ipv4.conf.all.arp_ignore = 1 net.ipv4.conf.all.arp_announce = 2 net.ipv4.conf.dummy.arp_ignore = 1 net.ipv4.conf.dummy.arp_announce = 2 EOF sysctl -p⚠️ 掩码写
32而不是24:VIP 只挂在本机,不参与所在网段的广播与 ARP,否则三台 RS 会互相抢答。
两个参数的分工:
| 内核参数 | 取值 | 行为 |
|---|---|---|
arp_ignore | 0(默认) | 本机有该 IP 时,任意网卡收到请求都回响应 |
| 1(本实验) | 只有请求目标 IP 与收包网卡的主 IP一致才响应 | |
| 2 | 与收包网卡上任一 IP(含次要)一致就响应 | |
| 3 | 除环回地址外一律不响应 | |
arp_announce | 0(默认) | 可用任意本地 IP 作源 IP,易被学到错误映射 |
| 1 | 尽量选与目标 IP 同网段的本地 IP 作源 IP | |
| 2(本实验) | 严格选同网段本地 IP,没有就不发 ARP 通告 |
arp_ignore = 1让「VIP 在 dummy 口、请求从 ens33 进来」这种情况不被应答;arp_announce = 2保证本机向外发 ARP 时不用 VIP 当源地址去污染别人的 ARP 表。两条配合,路由器就只会把 VIP 的流量交给 Director。
3.3 配置 LVS-DS
[root@lvs ~]# # 配置承载 VIP 的 dummy 网卡 nmcli connection add type dummy ifname dummy con-name dummy ipv4.method manual ipv4.addresses 10.1.8.100/32 nmcli connection up dummy # ipvsadm 的安装与启停同 2.2 节,这里不再重复 # 创建轮询负载,DR 模式不加 -m ipvsadm -A -t 10.1.8.100:80 -s rr ipvsadm -a -t 10.1.8.100:80 -r 10.1.8.11:80 ipvsadm -a -t 10.1.8.100:80 -r 10.1.8.12:80 ipvsadm -a -t 10.1.8.100:80 -r 10.1.8.13:80 ipvsadm-save -n > /etc/sysconfig/ipvsadm [root@lvs ~]# ipvsadm -Ln TCP 10.1.8.100:80 rr -> 10.1.8.11:80 Route 1 0 0 -> 10.1.8.12:80 Route 1 0 0 -> 10.1.8.13:80 Route 1 0 0Forward列显示Route,代表 DR 模式(NAT 是Masq、TUN 是Tunnel)。不写-g时默认就是 DR。
3.4 访问验证
[root@client1 ~]# for i in {1..90};do curl -s 10.1.8.100 ;done|sort|uniq -c 30 Welcome to web1.zhb.cloud 30 Welcome to web2.zhb.cloud 30 Welcome to web3.zhb.cloudclient2(10.1.1.0/24)跑同样的循环,结果也是三台各 30。注意 DR 模式下client1与 RS 同网段,却照样能访问。响应由 RS 直接发出,源 IP 是 VIP、目标 IP 是 CIP,按普通路由就能回到客户端。
四、参考脚本
把上面的手工步骤写成启停脚本,重建实验环境时可以一键跑。
Real Server 端
#!/bin/bash # description : 配置 Real Server . /etc/rc.d/init.d/functions VIP=10.1.8.100 case "$1" in start) echo -n "Start LVS Real Server ... " # 设置 VIP if nmcli connection |grep -q dummy;then nmcli connection modify dummy ipv4.method manual ipv4.addresses $VIP/32 else nmcli connection add type dummy ifname dummy con-name dummy ipv4.method manual ipv4.addresses $VIP/32 fi nmcli connection up dummy # 关闭 ARP 响应与通告 echo "1" >/proc/sys/net/ipv4/conf/all/arp_ignore echo "2" >/proc/sys/net/ipv4/conf/all/arp_announce echo "1" >/proc/sys/net/ipv4/conf/dummy/arp_ignore echo "2" >/proc/sys/net/ipv4/conf/dummy/arp_announce echo OK ;; stop) echo -n "Stop LVS Real Server ... " # 关闭 VIP nmcli connection delete dummy # 恢复 ARP 默认行为 echo "0" >/proc/sys/net/ipv4/conf/dummy/arp_ignore echo "0" >/proc/sys/net/ipv4/conf/dummy/arp_announce echo "0" >/proc/sys/net/ipv4/conf/all/arp_ignore echo "0" >/proc/sys/net/ipv4/conf/all/arp_announce echo OK ;; *) echo "Usage: $0 start|stop" exit 1 ;; esacDirector Server 端
#!/bin/bash # description : 配置 Director Server . /etc/rc.d/init.d/functions # 没装 ipvsadm 就先装上 if rpm -q ipvsadm &>/dev/null;then true else yum install -y ipvsadm &>/dev/null fi VIP=10.1.8.100 PORT=80 rs1=10.1.8.11 rs2=10.1.8.12 rs3=10.1.8.13 con_name=ens33 ipv=/sbin/ipvsadm case "$1" in start) echo -n "Start LVS Director Server ... " # 设置 VIP,已经存在就不重复加 if ip -br addr | grep -q $VIP;then true else nmcli connection modify ${con_name} +ipv4.addresses $VIP/32 nmcli connection up ${con_name} fi # 设置负载均衡规则 $ipv -C $ipv -A -t $VIP:${PORT} -s wrr $ipv -a -t $VIP:${PORT} -r $rs1:${PORT} -g -w 1 $ipv -a -t $VIP:${PORT} -r $rs2:${PORT} -g -w 1 $ipv -a -t $VIP:${PORT} -r $rs3:${PORT} -g -w 1 echo OK ;; stop) echo -n "Stop LVS Director Server ... " # 关闭 VIP if ip -br addr | grep -q $VIP;then nmcli connection modify ${con_name} -ipv4.addresses $VIP/32 nmcli connection up ${con_name} fi # 清空负载均衡规则 $ipv -C echo OK ;; *) echo "Usage: $0 start|stop" exit 1 ;; esac脚本里出现的通用命令选项,统一定义如下:
| 参数 | 含义 | 英文原意 |
|---|---|---|
yum install -y | 所有交互询问自动回答 yes | yes |
systemctl enable --now | 设成开机自启,同时立刻启动 | now |
sysctl -p | 重新加载/etc/sysctl.conf里的内核参数(长选项--load) | load |
nmcli connection up | 激活指定的连接配置 | up |
ip -br addr | 用简洁格式(brief)列出网卡地址 | brief |
grep -q | 静默匹配,只返回退出码不打印内容 | quiet |
curl -s | 静默模式,不打印进度条 | silent |
uniq -c | 统计每行重复出现的次数 | count |
echo -n | 输出后不换行 | no newline |
ipvsadm-save -n | 保存规则时用数字形式,不做域名解析 | numeric |
rpm -q | 查询指定软件包是否已安装 | query |
附:命令英文全称速查表
| 命令 / 缩写 | 英文全称 / 原意 | 作用 |
|---|---|---|
LVS | LinuxVirtualServer | Linux 虚拟服务器,内核态负载均衡方案 |
ipvsadm | IPVSadministration | 用户空间管理工具 |
ipvsadm-save | IPVS adminsave | 把内核里的规则导出到文件 |
-A/-E/-D | Add /Edit /Delete | 集群服务的增 / 改 / 删 |
-a/-e/-d | add /edit /delete | Real Server 的增 / 改 / 删 |
-C/-R/-S | Clear /Restore /Save | 清空 / 重载 / 保存规则 |
-L/-Z | List /Zero | 列出规则 / 清空计数器 |
-t/-u/-f | TCP /UDP /firewall mark | 服务协议类型 |
-s/-w | scheduler /weight | 调度算法 / 权重 |
-g/-i/-m | gateway /ipip /masquerade | DR / TUN / NAT 三种转发模式 |
-n | numeric | 数字形式输出,不做域名解析 |
MASQ | masquerade | ipvsadm 回显里 NAT 模式的标记 |
Route | route | ipvsadm 回显里 DR 模式的标记 |
VIP/DIP/RIP/CIP | Virtual IP /Director IP /Real server IP /Client IP | 对外服务地址 / 调度器后端地址 / 后端服务器地址 / 客户端地址 |
dummy | dummy interface | 哑网卡,常用来承载 VIP |
ARP | AddressResolutionProtocol | 地址解析协议 |
nmcli | NetworkManagercommandline | 网卡与连接管理命令行 |
📚 参考资料(官方文档 · 中英双语)
- Linux Virtual Server 官方网站(LVS 三大模式的原始文档,含 NAT / DR / TUN 配置示例)
- IPVS 内核参数文档(kernel.org)(
expire_nodest_conn等转发行为相关参数) - 负载均衡 SLB 产品概述(阿里云)(四层 / 七层概念与适用场景)
其余手册在服务器上直接查:man 8 ipvsadm、man 1 nmcli。
总结:两套实验的配置差异只集中在三处——网关注向哪(NAT 指 LVS、DR 指 router)、VIP 挂在哪(NAT 不需要、DR 要挂 dummy 网卡且掩码写 32)、ARP 要不要关(只有 DR 需要,用
arp_ignore=1+arp_announce=2)。配完固定按这个顺序查:先ipvsadm -Ln看Forward列确认模式,再从两个网段各跑 90 次确认均分,最后才是调权重。觉得有用可以收藏;如果 DR 模式配完流量没起来,八成是 VIP 的 ARP 没关干净,欢迎在评论区贴出ipvsadm -Ln一起看。