1 问题现象

在一个新搭建的 OpenStack 环境中启动 HAproxy 后发现 HAProxy 服务启动报错:

[ALERT] 045/145120 (10) : Starting proxy rabbitmq_management: cannot bind socket [172.10.10.15:15672]
[ALERT] 045/145120 (10) : Starting proxy keystone_internal: cannot bind socket [172.10.10.15:5000]
[ALERT] 045/145120 (10) : Starting proxy keystone_admin: cannot bind socket [172.10.10.15:35357]
[ALERT] 045/145120 (10) : Starting proxy glance_registry: cannot bind socket [172.10.10.15:9191]
[ALERT] 045/145120 (10) : Starting proxy glance_api: cannot bind socket [172.10.10.15:9292]
[ALERT] 045/145120 (10) : Starting proxy nova_api: cannot bind socket [172.10.10.15:8774]
[ALERT] 045/145120 (10) : Starting proxy nova_metadata: cannot bind socket [172.10.10.15:8775]
[ALERT] 045/145120 (10) : Starting proxy placement_api: cannot bind socket [172.10.10.15:8780]
[ALERT] 045/145120 (10) : Starting proxy nova_novncproxy: cannot bind socket [172.10.10.15:6080]
[ALERT] 045/145120 (10) : Starting proxy neutron_server: cannot bind socket [172.10.10.15:9696]

2 问题分析

2.1 端口占用

HAProxy 常见的 bind socket 报错一般是由于端口占用导致,对服务器端口占用情况进行检查:

[root@*** ~]# netstat -lntp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 172.10.10.11:11211      0.0.0.0:*               LISTEN      37620/memcached     
tcp        0      0 172.10.10.11:9292       0.0.0.0:*               LISTEN      27851/python        
tcp        0      0 172.10.10.11:8780       0.0.0.0:*               LISTEN      20512/httpd          
tcp        0      0 172.10.10.11:6640       0.0.0.0:*               LISTEN      25010/ovsdb-server  
tcp        0      0 172.10.10.11:8080       0.0.0.0:*               LISTEN      11864/httpd          
tcp        0      0 172.10.10.11:8022       0.0.0.0:*               LISTEN      22706/sshd           
tcp        0      0 172.10.10.11:16509      0.0.0.0:*               LISTEN      14738/libvirtd      
tcp        0      0 172.10.10.11:6080       0.0.0.0:*               LISTEN      30538/python2       
tcp        0      0 172.10.10.11:8774       0.0.0.0:*               LISTEN      19284/httpd         
tcp        0      0 172.10.10.11:9191       0.0.0.0:*               LISTEN      28548/python        
tcp        0      0 172.10.10.11:8775       0.0.0.0:*               LISTEN      19284/httpd         
tcp        0      0 172.10.10.11:25672      0.0.0.0:*               LISTEN      21607/beam.smp      
tcp        0      0 172.10.10.11:8776       0.0.0.0:*               LISTEN      25659/httpd       

通过命令输出可以发现,没有端口占用冲突,可以排除是端口占用所致。

172.10.10.15 为集群VIP,172.10.10.11 为本机IP,本机服务只工作在本机IP地址:端口

2.2 SELinux

HAProxy 绑定 Socket 失败还有可能是由 SELinux 未关闭导致,检查操作系统 SELinux 开启状况:

[root@*** ~]# getenforce
enforcing

可以看到当前 SELinux 处于开启状态,下面将进行关闭操作:

首先执行命令临时关闭 SELinux

[root@*** ~]# setenforce 0

随后加入永久关闭 SELinux 配置

[root@*** ~]# vim /etc/selinux/config

将 SELINUX 参数从 SELINUX=enforcing 修改为 SELINUX=disabled

# This file controls the state of SELinux on the system.
# SELINUX= can take one of these three values:
#     enforcing - SELinux security policy is enforced.
#     permissive - SELinux prints warnings instead of enforcing.
#     disabled - No SELinux policy is loaded.
SELINUX=disabled
# SELINUXTYPE= can take one of three two values:
#     targeted - Targeted processes are protected,
#     minimum - Modification of targeted policy. Only selected processes are protected. 
#     mls - Multi Level Security protection.
SELINUXTYPE=targeted

完成操作后重启 HAProxy 服务观察运行状态,发现 HAProxy 仍然报错 cannot bind socket

说明该问题出现的原因并不是 SELinux 导致

2.3 ip_nonlocal_bind

通过日志进一步观察,发现都是 [vip:port] 的形式绑定失败,其它监听地址比如 [本机IP:port] 是绑定成功的,怀疑是 VIP 绑定受到了限制。

查阅文档发现,Linux 内核网络参数中有一个 net.ipv4.ip_nonlocal_bind 参数控制了本机是否允许绑定非本机 IP,于是对该参数进行检查:

参考文档:redhat.com: initial-setup-forwarding-vsa
[root@*** ~]# sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 0

该参数处于关闭状态,当前 Linux 系统禁止绑定非本机 IP 地址,问题原因已确定,下面进行修复:开启非本机 IP 地址绑定。

[root@*** ~]# cat >> /etc/sysctl.conf << EOF
net.ipv4.ip_nonlocal_bind = 1
EOF
[root@*** ~]# sysctl -p
...
net.ipv4.ip_nonlocal_bind = 1

完成操作后重启 HAProxy 服务观察运行状态,发现 HAProxy 已正常完成端口绑定,运行状态正常。

感谢阅读,如需交流可通过邮件与我沟通:hczhang.cn@gmail.com