我已将 Keepalived 设置为负载均衡器,但没有使用主/备用配置 - 只是单个服务器。
启用了防火墙后,就会出现此问题。没有防火墙时,一切都会正常。但是,当防火墙运行时,从真实服务器返回的数据包会被 STATE_INVALID_DROP 规则阻止。
该设置涉及两个接口:enp2s0(客户端区域)和 enp3s0(服务器区域)。从 enp2s0 流向 enp3s0 的流量正常工作,但问题出现在从 enp3s0 返回 enp2s0 的流量上。
有趣的是,如果我只使用配置了到达真实服务器的路由的firewalld并删除Keepalived,流量就不会出现任何问题。只有当firewalld和Keepalived同时使用时才会出现问题。
这是我的区域配置:
router1@router1:~$ sudo firewall-cmd --zone clients --list-all
clients (active)
target: DROP
ingress-priority: 0
egress-priority: 0
icmp-block-inversion: no
interfaces: enp2s0
sources:
services: http
ports:
protocols:
forward: no
masquerade: no
forward-ports:
source-ports:
icmp-blocks:
rich rules:
router1@router1:~$ sudo firewall-cmd --zone servers --list-all
servers (active)
target: DROP
ingress-priority: 0
egress-priority: 0
icmp-block-inversion: no
interfaces: enp3s0
sources:
services: http
ports:
protocols:
forward: no
masquerade: no
forward-ports:
source-ports:
icmp-blocks:
rich rules:
这是我的政治配置:
router1@router1:~$ sudo firewall-cmd --policy fromCliToSrv --list-all
fromCliToSrv (active)
priority: -1
target: DROP
ingress-zones: clients
egress-zones: servers
services: http
ports:
protocols:
masquerade: no
forward-ports:
source-ports:
icmp-blocks:
rich rules:
router1@router1:~$ sudo firewall-cmd --policy fromSrvToCli --list-all
fromSrvToCli (active)
priority: -1
target: DROP
ingress-zones: servers
egress-zones: clients
services: http
ports:
protocols:
masquerade: no
forward-ports:
source-ports:
icmp-blocks:
rich rules:
这是我的 keepalived 配置:
router1@router1:~$ sudo cat /etc/keepalived/keepalived.conf
! Configuration File for keepalived
virtual_server 172.20.241.20 80 {
lb_algo wrr
lb_kind NAT
protocol TCP
persistence_timeout 600
persistence_granularity 255.255.255.0
real_server 10.0.1.5 {
weight 1
}
real_server 10.0.1.6 {
weight 2
}
real_server 10.0.1.7 {
weight 3
}
}
我尝试像这样将转发端口添加到客户端区域:
router1@router1:~$ sudo firewall-cmd --permanent --zone clients --add-forward-port=port=80:proto=tcp:toaddr=10.0.1.5:toport=80
success
router1@router1:~$ sudo firewall-cmd --permanent --zone clients --add-forward-port=port=80:proto=tcp:toaddr=10.0.1.6:toport=80
success
router1@router1:~$ sudo firewall-cmd --permanent --zone clients --add-forward-port=port=80:proto=tcp:toaddr=10.0.1.7:toport=80
success
router1@router1:~$ sudo firewall-cmd --reload
success
但此配置将所有请求转发到 10.0.1.5,因为它是添加的第一条规则
这是因为 keepalived 在 NAT 模式下的工作方式。
在 keepalived 中使用 NAT 时,您依靠 netfilter(iptables)规则来处理数据包以实现负载平衡(这实际上是第 4 层负载平衡)。
FirewallD 还使用 netfilter(iptables)制定流量策略来阻止特定的流量位。
我敢打赌,要么 FirewallD 破坏了 keepalived netfilter 配置,要么反之亦然,要么 keepalived 和 FirewallD 中的 netfilter 规则的排序和优先级以毫无意义的方式加在一起。
无论如何,您最务实的解决方案是不使用 FirewallD,而是直接使用不会干扰 keepalived 的规则集
nft
制定任何网络过滤策略。iptables
或者使用仅在系统本身中重新创建连接的负载平衡软件,例如 haproxy。
我还要指出的是,用于 keepalived 的旧虚拟服务器负载平衡模块(这些
ipvsadm
东西)与现代 netfilter(基于)不兼容nft
,至少上次我尝试时是这样的。我最终
keepalived
认为 VRRP 实现(故障转移)不错,但负载平衡解决方案较差。一种常见的设置是使用 keepalived 进行故障转移,使用 haproxy 进行负载平衡。这种设置可以让你鱼与熊掌兼得,网上应该有很多关于如何手动执行此操作的资料,如果你急着要操作,甚至可以使用 docker 镜像和其他预先准备好的选项。