鲲鹏平台LVS异常排查
发表于 2025/05/30
0
作者 | 姜云鹏 黄俊楷
1 背景与问题场景
1.1 环境与故障现象
硬件平台:华为鲲鹏920服务器(ARM架构)。软件架构:LVS(DR模式)+ Keepalived + Nginx。
部署架构:

1.2 技术背景
基于LVS(Linux Virtual Server,Linux虚拟服务器)和Keepalived的Nginx集群负载均衡架构,采用LVS在传输层进行负载均衡,将客户端请求通过VIP(虚拟IP)分发到后端的多个Nginx集群,而Nginx集群则在应用层进一步处理这些请求,形成多层次的负载均衡网络结构。Keepalived通过配置文件管理LVS的运行,并利用VRRP协议确保VIP的高可用性,从而为Nginx集群提供高性能和高可用性的负载均衡服务。2 部署与验证
2.1 部署步骤
2.1.1 在LVS端源码编译安装Keepalived
cd /opt/kyou
yum install -y libnl3-devel openssl-devel libnfnetlink-devel gcc make ipvsadm # 安装依赖
wget --no-check-certificate https://www.keepalived.org/software/keepalived-1.3.5.tar.gz # 下载源码包
tar -zxvf keepalived-1.3.5.tar.gz # 解压源码包
# 修改源码文件,避免安装时报错。vim到/opt/kyou/keepalived-1.3.5/keepalived/include/vrrp_if.h文件,将第130行的list garp_delay; 修改为 extern list garp_delay;
cd keepalived-1.3.5
./configure
make -j && make install
2.1.2 将Keepalived注册成服务
cp /usr/local/etc/sysconfig/keepalived /etc/sysconfig/keepalived
cp /usr/local/sbin/keepalived /usr/sbin/keepalived
mkdir /etc/keepalived
cp /usr/local/etc/keepalived/keepalived.conf /etc/keepalived/
2.1.3 备份后修改LVS端Keepalived配置文件
文件地址:/usr/local/etc/keepalived/keepalived.conf
! Configuration File for keepalived
global_defs {
router_id VI_189
script_user root
}
vrrp_instance VI_7 {
state MASTER
interface enahisic2i0 # 指定VRRP实例使用的网络接口
virtual_router_id 7
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.1.9/24 dev enahisic2i0 # 将VIP绑定到指定的网络接口
}
}
virtual_server 192.168.1.9 80 { # 定义一个虚拟服务器,绑定在192.168.1.9的80端口
delay_loop 7
lb_algo wlc
lb_kind DR # 使用DR模式
protocol TCP
persistence_timeout 60
real_server 192.168.1.204 80 { # 真实服务器,IP为192.168.1.204,端口为80
weight 1
TCP_CHECK {
connect_port 80
connect_timeout 5
nb_get_retry 1
delay_before_retry 1
}
}
real_server 192.168.1.225 80 { # 另一个真实服务器,IP为192.168.1.225,端口为80
weight 1
TCP_CHECK {
connect_port 80
connect_timeout 5
nb_get_retry 1
delay_before_retry 1
}
}
}
2.1.4 安装Nginx
yum install -y nginx
2.1.5 备份后修改Nginx配置文件
文件地址:/etc/nginx/nginx.conf
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
# Load dynamic modules. See /usr/share/doc/nginx/README.dynamic.
include /usr/share/nginx/modules/*.conf;
events {
worker_connections 1024;
}
http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 4096;
include /etc/nginx/mime.types;
default_type application/octet-stream;
# Load modular configuration files from the /etc/nginx/conf.d directory.
# See http://nginx.org/en/docs/ngx_core_module.html#include
# for more information.
include /etc/nginx/conf.d/*.conf;
server {
listen 80;
listen [::]:80;
server_name 192.168.1.204; # 这里是Nginx端的真实IP,如果是Nginx②端,需要改为192.168.1.225
root /usr/share/nginx/html;
# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;
error_page 404 /404.html;
location = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
}
2.1.6 配置Nginx端的回环IP和ARP抑制
ip addr add 192.168.1.9/32 dev lo label lo:0
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/lo/arp_ignore
echo 2 > /proc/sys/net/ipv4/conf/lo/arp_announce
2.1.7 配置Nginx页面并启动Nginx
echo "A Web Server from Nginx/openEuler/204! Hello!" > /usr/share/nginx/html/index.html # 需要分别为两个Nginx端设置不同的内容
systemctl start nginx
systemctl enable nginx
2.1.8 启动Keepalived
systemctl enable keepalived
systemctl start keepalived
2.2 服务验证及故障表现
Nginx端①已经将VIP绑定到lo网卡:

Nginx端②已经将VIP绑定到lo网卡:

LVS端已经将VIP绑定到物理网卡:

在LVS端查看路由转发情况:

客户端可以ping通VIP,并且使用curl可以直接请求Nginx。故障表现为不可以使用curl直接请求VIP:

3.1 抓包分析
在客户端向VIP发送curl请求,同时分别在LVS端和Nginx端抓包分析。发现在LVS端可以抓到数据包,但在Nginx端抓不到数据包。分析LVS端的抓包结果,发现全是客户端发送到VIP的SYN,但没有后续的ACK或RST包。初步推断问题大概率出在LVS端的转发过程中,小概率出在Nginx端的接收过程中。

LVS的DR模式要求,LVS的真实IP、VIP、RS的真实IP、客户端的IP必须处于同一物理网段(即同一局域网,同一子网)。当前环境LVS的真实IP为192.168.1.189/24,VIP为192.168.1.9/24,RS的真实IP为192.168.1.204/24和192.168.1.225/24,客户端的IP为192.168.1.221/24,是位于同一物理网段的。因此是符合要求的。
3.3 防火墙原因
关闭所有防火墙,重新测试,请求依然失败。
systemctl stop firewalld # 停止firewalld服务
iptables -F # 清空所有iptables规则
3.4 SELinux原因
SELinux严格的访问控制机制可能会影响流量转发。查看SELinux状态,如果当前是Enforcing(严格模式),就设置为宽容模式。设置完成后重新测试,请求依然失败。
getenforce # 查看SELinux状态
sudo setenforce 0 # 将SELinux设置为宽容模式
3.5 ARP抑制不完整
在Nginx端执行下列命令,显式抑制实际网卡(enp125s0f0)的 ARP 响应,重新测试,请求依然失败。
echo 1 > /proc/sys/net/ipv4/conf/enp125s0f0/arp_ignore
echo 2 > /proc/sys/net/ipv4/conf/enp125s0f0/arp_announce
3.6 日志分析
查看Keepalived的日志,无异常。
journalctl -u keepalived --since "5 minutes ago" | grep -i error
3.7 后台网关路由规则问题
经与后台管理员确认,后台交换机的路由规则没有问题。
3.8 检查ARP缓存
如果客户端缓存了错误的ARP记录,可能会导致将VIP映射到错误的MAC地址。
但是经过检查,缓存的VIP的MAC地址与实际LVS端的物理机的MAC地址相同。
arp -n # 检查ARP缓存
3.9 反向路径过滤
关闭Nginx端反向路径过滤的严格模式,因为严格的反向路径过滤会丢弃VIP与接收网卡不匹配的包。关闭后重新测试,请求依然失败。
echo 0 > /proc/sys/net/ipv4/conf/enp125s0f0/rp_filter
3.10 操作系统内核版本
LVS端使用的操作系统版本为openEuler 22.03 LTS,内核版本为5.10.0-60.139.0.166.oe2203.aarch64。在检查系统中的所有内核时,发现除了当前使用的内核外,还有一个未被使用的内核版本5.10.0-60.18.0.50.oe2203.aarch64,这个内核是openEuler 22.03 LTS的默认内核。将系统切换到默认内核并重启后,重新测试,发现LVS可以成功转发请求,问题得到解决。
uname -r # 显示当前运行的内核版本
grubby --info=ALL # 显示系统中所有可用的内核信息
grubby --set-default /boot/vmlinuz-5.10.0-60.18.0.50.oe2203.aarch64 # 设置默认启动的内核
reboot # 重启系统,使新的默认内核设置生效
4 原因分析
根据上述情况,可以推断问题的原因是:LVS端的服务器是一台公共服务器,可能之前有其他用户通过非标准流程升级内核。在这一过程中,可能因编译选项或模块冲突,无意中破坏了LVS的相关功能,导致高版本内核下的LVS无法正常工作。