鲲鹏社区首页
中文
注册
鲲鹏平台LVS异常排查

鲲鹏平台LVS异常排查

编译调试

发表于 2025/05/30

0

作者 | 姜云鹏 黄俊楷


1 背景与问题场景

1.1 环境与故障现象

硬件平台:华为鲲鹏920服务器(ARM架构)。
软件架构:LVS(DR模式)+ Keepalived + Nginx。
部署架构


故障现象:客户端通过VIP(192.168.1.9)访问服务返回“No route to host”,但直连后端Nginx(192.168.1.204和192.168.1.225)正常。各节点间网络互通,VIP可被Ping通。

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 排查过程
3.1 抓包分析
在客户端向VIP发送curl请求,同时分别在LVS端和Nginx端抓包分析。发现在LVS端可以抓到数据包,但在Nginx端抓不到数据包。分析LVS端的抓包结果,发现全是客户端发送到VIP的SYN,但没有后续的ACK或RST包。初步推断问题大概率出在LVS端的转发过程中,小概率出在Nginx端的接收过程中。
3.2 网段原因
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无法正常工作。

本页内容