LVS 实战:利用防火墙标记与持久连接优化调度
目的:在 LVS/IPVS 环境中将 VIP 的 HTTP(80) 与 HTTPS(443) 流量"捆绑"到同一调度逻辑,结合持久(persistence)机制实现会话粘滞,避免 HTTP→HTTPS 跳转导致的会话丢失或调度不一致问题。实验背景与目标(简要)
问题:
默认情况下,LVS 把 80 和 443 视为两个独立 service,分别轮询,导致 HTTP 和 HTTPS 的请求被独立调度。
用户在 HTTP 登录后跳转到 HTTPS,若被分配到不同 RS,则会话(Session/cookie)丢失。
目标:
- 使用防火墙标记(fwmark)把 80/443 流量打同一个标记并由 IPVS 基于该标记统一调度。
- 在该调度上启用持久(persistence)实现简单的基于源 IP 的粘滞。
2. 前提与检查项
- IPVS 所需内核模块已加载(例如 ip_vs, ip_vs_rr)。
- RS(真实服务器)可达并提供 HTTP/HTTPS 服务(httpd、nginx 等)。
- 若使用 DR(Direct Routing),需要在 RS 上配置 VIP 到本地回环并做好 ARP 控制。
- 系统可能使用 iptables 或 nftables;此笔记以 iptables(tables v4) 的 mangle MARK 为示例,若使用 nftables,请用等价的 nft mark 规则。
3. 环境准备:在 RS 上启用 HTTPS
在每台后端 RS(RS1、RS2)上安装并启动 SSL 模块(以 RHEL/CentOS 为例):
bash
# 在 RS1 和 RS2 上
dnf install mod_ssl -y
systemctl restart httpd
(测试时可使用自签证书;curl 测试 HTTPS 时可加 -k 忽略证书验证)
4. 问题复现:80 与 443 分别为独立 service 导致的调度不统一
示例:分别为 80 与 443 建 service(vsnode):
bash
# HTTP (80)
ipvsadm -A -t 192.168.0.200:80 -s rr
ipvsadm -a -t 192.168.0.200:80 -r 192.168.0.20 -g
ipvsadm -a -t 192.168.0.200:80 -r 192.168.0.10 -g
# HTTPS (443)
ipvsadm -A -t 192.168.0.200:443 -s rr
ipvsadm -a -t 192.168.0.200:443 -r 192.168.0.10:443 -g
ipvsadm -a -t 192.168.0.200:443 -r 192.168.0.20:443 -g
测试(客户端):
bash
curl 192.168.0.200; curl -k https://192.168.0.200
# 可能输出(示例):
RS2 - 192.168.0.20
RS2 - 192.168.0.20
说明:HTTP 与 HTTPS 各自独立轮询,调度状态不共享,容易出现"同一用户连续请求被分发到不同 RS"或逻辑混乱的情况。
5. 解决方案:用防火墙标记(fwmark)统一调度
思路:在 PREROUTING 阶段把访问 VIP(192.168.0.200) 的 80/443 TCP 包打上同一 mark(例如 6666),然后在 ipvs 中基于该 fwmark 创建一个 service,把后端都加入该表。
步骤示例(在 vsnode 上):
- 给到 VIP 的 80/443 打标(mangle 表 PREROUTING):
bash
iptables -t mangle -A PREROUTING -d 192.168.0.200 -p tcp -m multiport --dports 80,443 -j MARK --set-mark 6666
- 在 IPVS 中基于 fwmark 建 service 并添加 RS:
bash
ipvsadm -A -f 6666 -s rr
ipvsadm -a -f 6666 -r 192.168.0.10 -g
ipvsadm -a -f 6666 -r 192.168.0.20 -g
- 测试:
bash
curl 192.168.0.200; curl -k https://192.168.0.200
# 可能输出(示例):
RS2 - 192.168.0.20
RS1 - 192.168.0.10
:80/443 流量被打相同标记,进入同一调度表,轮询在同一表中进行,调度行为更可控。
6. 进阶:在 fwmark service 上启用持久(persistence)实现会话粘滞
为了保证短时间内同一客户端的请求都到同一 RS(解决登录后跳转 HTTPS 导致 Session 丢失),在创建 fwmark service 时启用持久:
示例(持久超时设为 1 秒,实际生产应根据需求设更长,例如 300s、600s 等):
bash
# 启用持久(示例 timeout=1,单位秒)
ipvsadm -A -f 6666 -s rr -p 1
# 或如果已经存在 service,先删除再创建带 -p 的:
# ipvsadm -D -f 6666
# ipvsadm -A -f 6666 -s rr -p 600
查看:Flags 应显示 persistent
bash
ipvsadm -Ln
# 输出示例中会看到:
# FWM 6666 rr persistent 1
测试粘滞:
bash
curl 192.168.0.200
# RS1 - 192.168.0.10
curl 192.168.0.200
# RS1 - 192.168.0.10

7. 验证与排查命令
- 查看 ipvs 服务条目: ipvsadm -Ln
- 查看 ipvs 连接条目(含 conntrack 状态): ipvsadm -Lnc
- 查看 mangle 规则是否生效: iptables -t mangle -L -nv --line-numbers
- 检查包是否命中规则: tcpdump -i host 192.168.0.200 and ( port 80 or port 443 )
- 若使用 nftables: nft list ruleset(转换相应 mark 语法)
- 若使用 DR(-g/-i):确认 RS 上已配置 VIP 到本机并关闭 ARP 响应以避免冲突
示例观察(连接表):
bash
watch -n 1 ipvsadm -Lnc
# 可看到 TCP/FIN_WAIT、IP ASSURED 等状态,反映连接条目与持久行为
8. 注意事项与最佳实践
- persistence 以源 IP 为 key:若客户端后端有 NAT、共享出口 IP 或随时间变化的源 IP,粘滞可能不准确。对需要更严格 L7 粘滞的场景,使用 HAProxy/Nginx 等 L7 代理(基于 cookie 或 session)更可靠。
- 持久超时设置:生产环境不要用过短的值(1秒通常太短),应根据应用会话特性设置(例如 300s、600s)。
- fwmark 值检查:ipvsadm 使用的 mark 为十进制,iptables MARK 时也使用相同十进制值;注意一致性。
- 规则持久化:在重启后保持 iptables 规则(iptables-save / iptables-restore,或使用 firewalld direct 或系统启动脚本)。
- nftables 环境下请用 nft 的 mark 语法替换 iptables 命令。
- DR 模式注意:RS 需要在 loopback 上配置 VIP、并设置
sysctl以避免 ARP 广播冲突(例如设置 arp_ignore/arp_announce 等)。 - NAT/masquerade 模式:若使用 NAT(-t/--nat),需处理 SNAT 与返回路径问题。
- HTTPS 证书:测试时可用自签证书并在客户端使用 curl -k;生产中请使用有效证书并考虑 SNI。
9. 常见故障与排查提示
- 打标规则未生效:检查 mangle 表链顺序、目标 IP 是否正确、是否被其他规则覆盖;用 tcpdump 确认包流。
- ipvsadm 未显示 FWM 项:确认 ipvsadm 命令是否正确(-f 十进制 mark);重载/重启 ipvs 相关模块(谨慎)。
- 会话仍丢失:检查是否有中间负载或代理改变了源 IP;检查持久超时设置是否足够。
- HTTPS 与 HTTP 仍不同步:确认所有到 VIP 的 80/443 流量都被打上标记(包括本地产生或转发的流量)。
10. 快速备忘命令汇总
bash
# 在 RS 上启用 HTTPS(示例)
dnf install mod_ssl -y
systemctl restart httpd
# 在 vsnode 打标 80/443
iptables -t mangle -A PREROUTING -d 192.168.0.200 -p tcp -m multiport --dports 80,443 -j MARK --set-mark 6666
# 在 ipvs 中基于 fwmark 建 service 并添加后端
ipvsadm -A -f 6666 -s rr -p 600 # 建议持久超时按需调整,如 600s
ipvsadm -a -f 6666 -r 192.168.0.10 -g
ipvsadm -a -f 6666 -r 192.168.0.20 -g
# 查看
ipvsadm -Ln
ipvsadm -Lnc
iptables -t mangle -L -nv --line-numbers
# 测试(客户端)
curl 192.168.0.200
curl -k https://192.168.0.200
# 保存 iptables(以 CentOS/RHEL 为例)
iptables-save > /etc/sysconfig/iptables
11. 总结
将 HTTP 与 HTTPS 的流量用防火墙标记统一到一个 IPVS 调度表,配合 IPVS 的持久(persistence)功能,是一个轻量、可控且在 L4 层实现会话粘滞的有效方案。对于复杂的会话需求(基于 cookie、token、路径等),建议引入 L7 代理(HAProxy、Nginx)做更精细的会话保持与健康检查。
ptables
---
## 11. 总结
将 HTTP 与 HTTPS 的流量用防火墙标记统一到一个 IPVS 调度表,配合 IPVS 的持久(persistence)功能,是一个轻量、可控且在 L4 层实现会话粘滞的有效方案。对于复杂的会话需求(基于 cookie、token、路径等),建议引入 L7 代理(HAProxy、Nginx)做更精细的会话保持与健康检查。
-- 结束 --