HAProxy+Nginx+NFS+DNS 部署笔记
一、环境规划
| 主机名 | IP 地址 | 安装软件 | 角色说明 |
|---|---|---|---|
| haproxy | 192.168.72.100/24 | haproxy | 负载均衡器 |
| nginx1 | 192.168.72.10/24 | nginx、nfs-utils | Web 节点 1(挂载 NFS 共享) |
| nginx2 | 192.168.72.20/24 | nginx、nfs-utils | Web 节点 2(挂载 NFS 共享) |
| nfs | 192.168.72.30/24 | nfs-utils | NFS 文件共享服务器 |
| dns | 192.168.72.40/24 | bind | DNS 域名解析服务器 |
二、部署步骤(按服务器角色拆分)
2.1 NFS 服务器部署(192.168.72.30)
2.1.1 环境准备
1# 1. 设置主机名(永久生效并立即生效) 2hostnamectl set-hostname nfs && bash 3# hostnamectl set-hostname nfs:修改系统主机名为nfs 4# && bash:重新加载shell,使主机名修改立即生效 5 6# 2. 关闭防火墙(禁用并立即停止) 7systemctl disable --now firewalld.service 8# disable:设置防火墙开机不自启 9# --now:立即停止防火墙服务 10 11# 3. 关闭SELinux(临时+永久) 12setenforce 0 13# setenforce 0:临时将SELinux切换为宽容模式(不拦截仅记录) 14sed -i "s/SELINUX=enforcing/SELINUX=permissive/" /etc/selinux/config 15# sed:文本替换工具 16# -i:直接修改文件内容 17# "s/旧内容/新内容/":替换规则,将强制模式改为宽容模式 18 19# 4. 配置静态IP 20nmcli c m ens160 ipv4.method manual ipv4.addresses 192.168.72.30/24 ipv4.gateway 192.168.72.2 ipv4.dns 223.5.5.5 connection.autoconnect yes 21# nmcli c m:修改网络连接配置 22# ens160:网卡名称(根据实际环境调整) 23# ipv4.method manual:手动配置IP(非DHCP) 24# ipv4.addresses:设置IP地址和子网掩码 25# ipv4.gateway:网关地址 26# ipv4.dns:DNS服务器地址(临时,后续可修改) 27# connection.autoconnect yes:开机自动连接该网络 28 29nmcli c up ens160 30# 重启网络连接,使IP配置生效 31
以上操作都可以用脚本来完成快速部署
1#!/bin/bash 2 3# useage: sudo ./init_sys.sh <hostname> <ip_address> [gateway] [dns] 4 5RED='\033[0;31m' 6GREEN='\033[0;32m' 7YELLOW='\033[1;33m' 8NC='\033[0m' 9 10log_info() { 11 echo -e "${GREEN}[INFO]${NC} $1" 12} 13log_warn() { 14 echo -e "${YELLOW}[WARN]${NC} $1" 15} 16log_error() { 17 echo -e "${RED}[ERROR]${NC} $1" 18} 19 20check_root() { 21 if [[ $EUID -ne 0 ]]; then 22 log_error "此脚本必须以root权限运行" 23 exit 1 24 fi 25} 26 27usage() { 28 echo "用法: $0 <hostname> <ip_address> [gateway] [dns_servers]" 29 echo "" 30 echo "参数说明:" 31 echo " hostname 要设置的主机名" 32 echo " ip_address 要设置的静态IP地址 (如: 192.168.72.100)" 33 echo " gateway 网关地址 (如: 192.168.72.2)" 34 echo " dns_servers DNS服务器,逗号分隔 (可选,默认: 8.8.8.8,223.5.5.5)" 35 echo "" 36 echo "示例:" 37 echo " $0 myserver 192.168.72.100 192.168.72.2 8.8.8.8,223.5.5.5" 38 echo " $0 webserver 10.0.0.50" 39 exit 1 40} 41 42get_interface() { 43 # 尝试获取第一个活动的非环回接口 44 local interface=$(ip route | grep default | head -1 | awk '{print $5}' 2>/dev/null) 45 46 if [[ -z "$interface" ]]; then 47 # 如果没有默认路由,获取第一个非环回接口 48 interface=$(ip link show | grep -v lo | grep 'state UP' | head -1 | awk -F': ' '{print $2}') 49 fi 50 51 if [[ -z "$interface" ]]; then 52 log_error "无法自动检测网络接口" 53 read -p "请输入网络接口名称 (如: eth0, ens160): " interface 54 fi 55 56 echo "$interface" 57} 58 59set_hostname() { 60 local hostname=$1 61 62 log_info "正在设置主机名为: $hostname" 63 64 /usr/bin/hostnamectl set-hostname $hostname 65 66 log_info "主机名设置完成" 67} 68 69close_selinux_firewalld() { 70 log_info "关闭selinux" 71 setenforce 0 72 sed -i "s/SELINUX=enforcing/SELINUX=permissive/" /etc/selinux/config 73 74 log_info "关闭防火墙" 75 /usr/bin/systemctl disable --now firewalld 76} 77 78set_static_ip() { 79 local interface=$(get_interface) 80 local ip=$1 81 local gateway=${2:-"192.168.72.2"} 82 local dns=${3:-"223.5.5.5,8.8.8.8"} 83 84 log_info "正在为接口 $interface 配置静态IP: $ip" 85 86 nmcli c modify $interface ipv4.method manual ipv4.addresses $ip/24 ipv4.gateway $gateway ipv4.dns $dns connection.autoconnect yes 87 nmcli c up $interface 88} 89 90main() { 91 if [[ $# -lt 2 ]]; then 92 usage 93 fi 94 95 check_root 96 97 set_hostname "$1" 98 99 close_selinux_firewalld 100 101 set_static_ip "$2" "$3" "$4" 102} 103 104main "$@"
2.1.2 安装并配置 NFS
1# 1. 创建NFS共享目录 2mkdir /share 3# 创建用于共享的目录 4 5# 2. 创建测试页面(共享给Nginx节点) 6vim /share/index.html 7# 编辑index.html文件,写入内容:nfs 192.168.72.30 8# 作用:Nginx节点挂载后,访问Web时展示该内容 9 10# 3. 设置共享目录权限(NFS默认使用nobody用户) 11chown -R nobody: /share 12# chown:修改文件所属用户和组 13# -R:递归修改目录下所有文件 14# nobody::设置所属用户为nobody,组为空(继承父级) 15 16# 4. 安装NFS服务端工具 17dnf install nfs-utils -y 18# dnf:RHEL/CentOS 8+包管理器 19# install nfs-utils:安装NFS核心工具 20# -y:自动确认安装 21 22# 5. 配置NFS共享规则 23vim /etc/exports 24# 编辑NFS主配置文件,添加以下内容: 25/share 192.168.72.0/24(rw,sync,no_subtree_check) 26# /share:要共享的目录 27# 192.168.72.0/24:允许访问的客户端网段 28# rw:读写权限 29# sync:同步写入(数据先写入磁盘再返回成功) 30# no_subtree_check:关闭子树检查(提升性能) 31 32# 6. 加载NFS配置并验证 33exportfs -rv 34# exportfs:管理NFS共享 35# -r:重新加载配置 36# -v:详细输出(显示共享的目录和网段) 37# 输出:exporting 192.168.72.0/24:/share 表示配置生效 38 39# 7. 启动NFS服务 40systemctl start nfs-server.service 41# 启动NFS服务端 42 43# 8. 验证NFS共享 44showmount -e 192.168.72.30 45# showmount:查看NFS共享信息 46# -e:显示导出的共享目录 47# 输出:/share 192.168.72.0/24 表示共享成功 48
2.2 Nginx1 部署(192.168.72.10)
2.2.1 环境准备(同 NFS,仅 IP 和主机名不同)
1# 1. 设置主机名 2hostnamectl set-hostname nginx1 && bash 3 4# 2. 关闭防火墙 5systemctl disable --now firewalld.service 6 7# 3. 关闭SELinux 8setenforce 0 9sed -i "s/SELINUX=enforcing/SELINUX=permissive/" /etc/selinux/config 10 11# 4. 配置静态IP 12nmcli c m ens160 ipv4.method manual ipv4.addresses 192.168.72.10/24 ipv4.gateway 192.168.72.2 ipv4.dns 223.5.5.5 connection.autoconnect yes 13nmcli c up ens160 14
2.2.2 安装 Nginx 并挂载 NFS
1# 1. 安装Nginx 2dnf install nginx -y 3# 安装Nginx Web服务 4 5# 2. 安装NFS客户端工具(用于挂载共享目录) 6dnf install nfs-utils -y 7 8# 3. 挂载NFS共享目录到Nginx根目录 9mount -t nfs 192.168.72.30:/share /usr/share/nginx/html/ 10# mount:挂载命令 11# -t nfs:指定文件系统类型为NFS 12# 192.168.72.30:/share:NFS服务器的共享目录 13# /usr/share/nginx/html/:Nginx默认网页根目录(挂载后,访问Nginx即访问NFS共享文件) 14 15# 4. 验证挂载结果 16ls /usr/share/nginx/html/ 17# 输出index.html,表示挂载成功 18 19cat /usr/share/nginx/html/index.html 20# 输出nfs 192.168.72.30,验证文件内容正确 21 22# 5. 启动Nginx服务 23systemctl start nginx 24 25# 6. 本地访问测试 26curl 192.168.72.10 27# 输出nfs 192.168.72.30,表示Nginx+NFS挂载成功 28
2.3 Nginx2 部署(192.168.72.20)
步骤与 Nginx1 完全一致,仅修改以下内容:
1# 1. 设置主机名 2hostnamectl set-hostname nginx2 && bash 3 4# 2. 配置IP 5nmcli c m ens160 ipv4.method manual ipv4.addresses 192.168.72.20/24 ipv4.gateway 192.168.72.2 ipv4.dns 223.5.5.5 connection.autoconnect yes 6 7# 3. 访问测试 8curl 192.168.72.20 9# 输出nfs 192.168.72.30 即成功 10
2.4 HAProxy 部署(192.168.72.100)
2.4.1 环境准备
1# 1. 设置主机名 2hostnamectl set-hostname haproxy && bash 3 4# 2. 关闭防火墙 5systemctl disable --now firewalld.service 6 7# 3. 关闭SELinux 8setenforce 0 9sed -i "s/SELINUX=enforcing/SELINUX=permissive/" /etc/selinux/config 10 11# 4. 配置静态IP 12nmcli c m ens160 ipv4.method manual ipv4.addresses 192.168.72.100/24 ipv4.gateway 192.168.72.2 ipv4.dns 223.5.5.5 connection.autoconnect yes 13nmcli c up ens160 14
2.4.2 安装并配置 HAProxy
1# 1. 安装HAProxy 2dnf install haproxy -y 3 4# 2. 备份原配置文件(防止配置错误无法回滚) 5cp -p /etc/haproxy/haproxy.cfg{,.bak} 6# cp -p:保留文件属性(权限、时间戳) 7# {,.bak}:快捷写法,等价于 cp /etc/haproxy/haproxy.cfg /etc/haproxy/haproxy.cfg.bak 8 9# 3. 编辑HAProxy配置文件 10vim /etc/haproxy/haproxy.cfg 11# 配置内容及每行解释: 12global # 全局配置段(进程级配置) 13 log 127.0.0.1 local2 # 日志输出到本地syslog的local2设备 14 chroot /var/lib/haproxy # 切换根目录(安全隔离) 15 pidfile /var/run/haproxy.pid # 进程PID文件路径 16 maxconn 4000 # 最大并发连接数 17 user haproxy # 运行HAProxy的用户 18 group haproxy # 运行HAProxy的组 19 daemon # 以守护进程方式运行 20 stats socket /var/lib/haproxy/stats mode 600 level admin # 统计信息套接字(权限600,管理员级别) 21 ssl-default-bind-ciphers PROFILE=SYSTEM # 绑定SSL时使用系统默认加密套件 22 ssl-default-server-ciphers PROFILE=SYSTEM # 后端服务器SSL加密套件 23 24defaults # 默认配置段(继承到frontend/backend) 25 mode http # 工作模式:HTTP(七层代理) 26 log global # 继承global的日志配置 27 option httplog # 记录HTTP详细日志 28 option dontlognull # 不记录空请求日志 29 option http-server-close # 关闭客户端与服务器的连接(复用连接) 30 option forwardfor except 127.0.0.0/8 # 传递客户端真实IP(排除本地地址) 31 option redispatch # 后端服务器不可用时,重新分发请求 32 retries 3 # 后端连接失败重试次数 33 timeout http-request 10s # HTTP请求超时时间 34 timeout queue 1m # 请求排队超时时间 35 timeout connect 10s # 与后端服务器连接超时时间 36 timeout client 1m # 客户端连接超时时间 37 timeout server 1m # 后端服务器响应超时时间 38 timeout http-keep-alive 10s # 长连接超时时间 39 timeout check 10s # 健康检查超时时间 40 maxconn 3000 # 每个进程最大并发连接数 41 42frontend webserver # 前端配置段(接收客户端请求) 43 bind *:80 # 监听所有网卡的80端口 44 default_backend webcluster # 默认转发到webcluster后端集群 45 46backend webcluster # 后端配置段(负载均衡规则) 47 balance roundrobin # 负载均衡算法:轮询(依次分发请求) 48 server web1 192.168.72.10:80 check inter 2000 rise 2 fall 3 weight 1 49 # server 节点名 IP:端口 配置项 50 # check:启用健康检查 51 # inter 2000:健康检查间隔2秒 52 # rise 2:连续2次检查成功则标记为可用 53 # fall 3:连续3次检查失败则标记为不可用 54 # weight 1:权重(值越大,分配到的请求越多) 55 server web2 192.168.72.20:80 check inter 2000 rise 2 fall 3 weight 1 # 同web1 56 57# 4. 验证配置文件语法 58haproxy -c -f /etc/haproxy/haproxy.cfg 59# -c:检查配置语法 60# -f:指定配置文件 61# 输出Configuration file is valid 表示语法正确 62 63# 5. 启动HAProxy 64systemctl start haproxy 65 66# 6. 访问测试(轮询访问nginx1/nginx2) 67curl 192.168.72.100 68# 输出nfs 192.168.72.30 表示负载均衡生效 69
2.5 DNS 服务器部署(192.168.72.40)
2.5.1 环境准备
1# 1. 设置主机名 2hostnamectl set-hostname dns && bash 3 4# 2. 关闭防火墙 5systemctl disable --now firewalld.service 6 7# 3. 关闭SELinux 8setenforce 0 9sed -i "s/SELINUX=enforcing/SELINUX=permissive/" /etc/selinux/config 10 11# 4. 配置静态IP 12nmcli c m ens160 ipv4.method manual ipv4.addresses 192.168.72.40/24 ipv4.gateway 192.168.72.2 ipv4.dns 223.5.5.5 connection.autoconnect yes 13nmcli c up ens160 14
2.5.2 安装并配置 BIND(DNS 服务)
1# 1. 安装BIND 2dnf install bind -y 3# bind:DNS服务核心包 4 5# 2. 编辑BIND主配置文件 6vim /etc/named.conf 7# 配置内容及解释: 8options { 9 listen-on port 53 { 127.0.0.1; 192.168.72.40; }; # 监听53端口(DNS默认端口),仅允许本地和自身IP 10 directory "/var/named"; # 区域文件存储目录 11 dump-file "/var/named/data/cache_dump.db"; # 缓存转储文件 12 statistics-file "/var/named/data/named_stats.txt"; # 统计信息文件 13 memstatistics-file "/var/named/data/named_mem_stats.txt"; # 内存统计文件 14 secroots-file "/var/named/data/named.secroots"; # 安全根文件 15 recursing-file "/var/named/data/named.recursing"; # 递归查询文件 16 allow-query { localhost; 192.168.72.0/24; }; # 允许查询的客户端网段 17 recursion yes; # 启用递归查询(DNS服务器主动向其他服务器查询) 18 dnssec-validation no; # 关闭DNSSEC验证(简化配置) 19 managed-keys-directory "/var/named/dynamic"; # 托管密钥目录 20 geoip-directory "/usr/share/GeoIP"; # GeoIP数据库目录 21 pid-file "/run/named/named.pid"; # PID文件路径 22 session-keyfile "/run/named/session.key"; # 会话密钥文件 23 include "/etc/crypto-policies/back-ends/bind.config"; # 加密策略配置 24}; 25 26logging { # 日志配置 27 channel default_debug { 28 file "data/named.run"; # 日志文件路径 29 severity dynamic; # 日志级别(动态调整) 30 }; 31}; 32 33zone "." IN { # 根区域(指向根DNS服务器) 34 type hint; # 提示类型(使用根区域文件) 35 file "named.ca"; # 根区域文件路径 36}; 37 38include "/etc/named.rfc1912.zones"; # 包含自定义区域配置 39include "/etc/named.root.key"; # 根密钥文件 40 41# 3. 配置自定义区域(chengke.com) 42vim /etc/named.rfc1912.zones 43# 添加以下内容: 44zone "chengke.com" IN { # 定义chengke.com区域 45 type master; # 主DNS服务器 46 file "chengke.com.zone"; # 区域数据文件路径 47}; 48 49# 4. 创建区域数据解析文件 50cp -p /var/named/named.localhost /var/named/chengke.com.zone 51# 复制模板文件(保留属性) 52 53vim /var/named/chengke.com.zone 54# 编辑解析文件,内容及解释: 55$TTL 1D # 缓存时间(1天) 56@ IN SOA ns1 root.chengk.com. ( # SOA记录(起始授权机构) 57 0 ; serial(序列号,修改配置需递增) 58 1D ; refresh(刷新时间,1天) 59 1H ; retry(重试时间,1小时) 60 1W ; expire(过期时间,1周) 61 3H ) ; minimum(最小缓存时间,3小时) 62 IN NS ns1 # NS记录(域名服务器):chengke.com的DNS服务器是ns1.chengke.com 63ns1 IN A 192.168.72.40 # A记录:ns1.chengke.com对应IP 64www IN A 192.168.72.100 # A记录:www.chengke.com对应HAProxy的IP 65 66# 5. 语法校验 67named-checkconf -i /etc/named.conf 68# 检查主配置文件语法(无输出即正确) 69 70named-checkzone chengke.com /var/named/chengke.com.zone 71# 检查区域文件语法 72# 输出zone chengke.com/IN: loaded serial 0 OK 表示正确 73 74# 6. 启动BIND服务 75systemctl start named 76 77# 7. 验证DNS解析 78dig -t A www.chengke.com @192.168.72.40 79# dig:DNS查询工具 80# -t A:查询A记录 81# www.chengke.com:要查询的域名 82# @192.168.72.40:指定DNS服务器 83# 输出中ANSWER SECTION显示www.chengke.com IN A 192.168.72.100 表示解析成功 84
2.6 配置 HAProxy 使用自定义 DNS
1# 1. 查看当前DNS配置 2nmcli d show ens160 | grep DNS 3# 输出当前DNS服务器(默认223.5.5.5) 4 5# 2. 修改HAProxy的DNS为自定义DNS服务器 6nmcli c m ens160 ipv4.dns 192.168.72.40 7# 修改网络连接的DNS地址为192.168.72.40 8 9nmcli c up ens160 10# 重启网络连接使DNS生效 11 12# 3. 验证DNS修改 13nmcli d show ens160 | grep DNS 14# 输出IP4.DNS[1]: 192.168.72.40 表示修改成功 15 16# 4. 域名访问测试 17curl www.chengke.com 18# 输出nfs 192.168.72.30 表示DNS解析+HAProxy负载均衡+Nginx+NFS全流程生效 19
可以去测试,只开一台web服务器,和两台web服务器都关闭来验证负载均衡
3. keepalived+haproxy+nginx+nfs+dns
在此基础上我们来添加haproxy集群高可用
3.1 主机规划
| 主机名 | IP 地址 | 安装软件 | 角色说明 |
|---|---|---|---|
| VIP | 192.168.72.200 | 虚拟 IP(HAProxy 高可用入口) | |
| haproxy01 | 192.168.72.100 | haproxy,keepalived | 负载均衡器(主) |
| haproxy02 | 192.168.72.101 | haproxy,keepalived | 负载均衡器(备) |
| nginx1 | 192.168.72.10 | nginx,nfs-utils | Web 节点 1(挂载 NFS 共享) |
| nginx2 | 192.168.72.20 | nginx,nfs-utils | Web 节点 2(挂载 NFS 共享) |
| nfs | 192.168.72.30 | nfs-utils | NFS 文件共享服务器 |
| dns | 192.168.72.40 | bind | DNS 域名解析服务器 |
3.2 前期准备
在原有 HAProxy+Nginx+NFS+DNS 基础上,增加 HAProxy 高可用能力:
- 克隆 haproxy01 得到 haproxy02,实现 HAProxy 双节点;
- 通过 keepalived 实现双节点故障自动切换,并提供 VIP(192.168.72.200)作为统一访问入口;
- 编写高可用检测脚本,确保 HAProxy 故障时自动切换 VIP。
3.3 原有基础环境部署(补充 HAProxy 双节点)
3.3.1 搭建 haproxy01(原 HAProxy 节点改造)
1# 1. 修改主机名 2[root@haproxy ~]# hostnamectl set-hostname haproxy01 && bash 3 4# 2. 环境准备(复用原有配置:关闭防火墙、SELinux、静态IP 192.168.72.100) 5# 3. 原有HAProxy配置保持不变(负载均衡指向nginx1/nginx2) 6# 4. 验证HAProxy正常运行 7[root@haproxy01 ~]# systemctl restart haproxy 8[root@haproxy01 ~]# curl 192.168.72.100 9nfs 192.168.72.30 10
3.3.2 搭建 haproxy02(HAProxy 备节点)
- 克隆 haproxy01 虚拟机,命名为 haproxy02 并启动;
- 修改主机名和 IP:
1# 修改主机名 2[root@haproxy01 ~]# hostnamectl set-hostname haproxy02 && bash 3 4# 修改静态IP为192.168.72.101 5[root@haproxy02 ~]# nmcli c m ens160 ipv4.addresses 192.168.72.101/24 6[root@haproxy02 ~]# nmcli c up ens160 7 8# 启动HAProxy并验证 9[root@haproxy02 ~]# systemctl start haproxy 10[root@haproxy02 ~]# curl 192.168.72.101 11nfs 192.168.72.30 12 13当然curl www.chengke.com这个域名更好理解 14
3.4 搭建 keepalived(实现 HAProxy 高可用)
3.4.1 在 haproxy01(主节点)安装配置 keepalived
1# 1. 安装keepalived 2[root@haproxy01 ~]# dnf install keepalived -y 3 4# 2. 备份默认配置 5[root@haproxy01 ~]# cp -p /etc/keepalived/keepalived.conf{,.bak} 6 7# 3. 编辑keepalived主配置(MASTER节点) 8[root@haproxy01 ~]# vim /etc/keepalived/keepalived.conf 9
配置内容:
global_defs原配置中有一个vrrp_strict,这是开启严格模式
- 禁止无 VIP 配置:必须配置虚拟 IP,否则服务无法启动。
- 禁止单播邻居:只能用组播(224.0.0.18),不能配置
unicast_peer。 - VRRPv2 禁止 IPv6:v2 仅支持 IPv4,v3 才可混用 IPv4/IPv6。
- 禁用 VRRP 认证:配置
authentication会被忽略。 - VIP 默认不响应流量:仅当优先级 = 255 或 VRRPv3+
accept时才响应 ICMP/TCP。
生产环境常单播,这时候需要注释掉。
1global_defs { 2 router_id LVS_master # 节点标识(唯一) 3} 4 5# HAProxy健康检查脚本配置 6vrrp_script chk_haproxy { 7 script "/etc/keepalived/check_haproxy.sh" # 检测脚本路径 8 interval 2 # 检测间隔(秒) 9 rise 2 # 连续2次检测成功标记为可用 10 fall 3 # 连续3次检测失败标记为不可用 11 weight -20 # 检测失败后优先级降低20 12} 13 14vrrp_instance VI_1 { 15 state MASTER # 节点角色(主) 16 interface ens160 # 绑定网卡(与IP配置一致) 17 virtual_router_id 51 # 虚拟路由ID(主备节点需一致,范围0-255) 18 priority 100 # 优先级(主节点高于备节点) 19 advert_int 1 # 心跳检测间隔(秒) 20 # 认证配置(主备节点需一致) 21 authentication { 22 auth_type PASS 23 auth_pass 1111 24 } 25 virtual_ipaddress { 26 192.168.72.200/24 # 虚拟VIP(统一访问入口) 27 } 28 # 关联健康检查脚本 29 track_script { 30 chk_haproxy 31 } 32} 33
3.4.2 编写 HAProxy 健康检查脚本(haproxy01)
1# 1. 创建脚本文件 2[root@haproxy01 ~]# vim /etc/keepalived/check_haproxy.sh 3
脚本内容:
1#!/bin/bash 2# 检测HAProxy进程是否运行 3count=[`ps -C haproxy --no-header|wc -l`](https://xplanc.org/primers/document/zh/10.Bash/90.%E5%B8%AE%E5%8A%A9%E6%89%8B%E5%86%8C/EX.wc.md) 4if [ $count -eq 0 ]; then 5 # 尝试重启HAProxy 6 /usr/bin/systemctl start haproxy 7 sleep 1 8 # 重启失败则停止keepalived,释放VIP 9 if [ [`ps -C haproxy --no-header | wc -l`](https://xplanc.org/primers/document/zh/10.Bash/90.%E5%B8%AE%E5%8A%A9%E6%89%8B%E5%86%8C/EX.wc.md) -eq 0 ]; then 10 /usr/bin/systemctl stop keepalived 11 fi 12fi 13 14 15上面有缺陷是可能有存在僵尸进程 16优化为以下,还可以添加反馈,还可以添加log日志搜集报错,运行结果 17脚本不够完善: 18[root@haproxy01 keepalived]# ./check_haproxy.sh 19[WARN]the haproxy verification failed,and the service is being restart 2026-03-15 16:16:07 20[info]the haproxy service restarted successfully 2026-03-15 16:16:08 21 22需要手动执行脚本才能看见提示语句,建议添加一个日志文件,将提示语句输入到文件中,这样方便查看,实时了解服务的变化 23 24 25#!/bin/bash 26RED='\033[0;31m' 27GREEN='\033[0;32m' 28YELLOW='\033[1;33m' 29NC='\033[0m' 30log_info(){ 31 echo -e "${GREEN}[info]$1${NC} $(date +'%F %T')" 32} 33log_warn(){ 34 echo -e "${YELLOW}[WARN]$1${NC} $(date +'%F %T')" 35} 36log_error(){ 37 echo -e "${RED}[ERROR]$1${NC} $(date +'%F %T')" 38} 39answer=`systemctl is-active haproxy` 40if [ $answer != "active" ]; then 41 log_warn "the haproxy verification failed,and the service is being restart" 42 /usr/bin/systemctl start haproxy 43 sleep 1 44 answer_after=$(systemctl is-active haproxy) 45 if [ $answer_after != "active" ]; then 46 /usr/bin/systemctl stop keepalived 47 else 48 log_info "the haproxy service restarted successfully" 49 fi 50else 51 log_info "haproxy is up and running" 52fi 53
1# 2. 赋予脚本执行权限 2[root@haproxy01 ~]# chmod +x /etc/keepalived/check_haproxy.sh 3 4# 3. 启动keepalived并设置开机自启 5[root@haproxy01 ~]# systemctl enable --now keepalived 6 7# 4. 验证VIP已绑定 8[root@haproxy01 ~]# ip a show ens160 9# 输出中包含 192.168.72.200/32 表示VIP绑定成功 10
3.4.3 在 haproxy02(备节点)安装配置 keepalived
1# 1. 安装keepalived 2[root@haproxy02 ~]# dnf install keepalived -y 3 4# 2. 复制haproxy01的配置和脚本(简化配置) 5[root@haproxy02 ~]# scp -p 192.168.72.100:/etc/keepalived/* /etc/keepalived/ 6# 输入haproxy01的root密码完成复制 7 8# 3. 修改keepalived配置(BACKUP节点) 9[root@haproxy02 ~]# vim /etc/keepalived/keepalived.conf 10
修改后的配置:
1global_defs { 2 router_id LVS_backup # 备节点标识 3} 4 5vrrp_script chk_haproxy { 6 script "/etc/keepalived/check_haproxy.sh" 7 interval 2 8 rise 2 9 fall 3 10 weight -20 11} 12 13vrrp_instance VI_1 { 14 state BACKUP # 节点角色(备) 15 interface ens160 16 virtual_router_id 51 # 与主节点一致 17 priority 90 # 优先级低于主节点(100) 18 advert_int 1 19 authentication { 20 auth_type PASS 21 auth_pass 1111 # 与主节点一致 22 } 23 virtual_ipaddress { 24 192.168.72.200/24 # 与主节点共享VIP 25 } 26 track_script { 27 chk_haproxy 28 } 29} 30
1# 4. 赋予脚本执行权限 这一步上面scp -p 将权限也原封不动的复制过来,也可以不用这一步 2[root@haproxy02 ~]# chmod +x /etc/keepalived/check_haproxy.sh 3# 5. 启动keepalived并设置开机自启 4[root@haproxy02 ~]# systemctl enable --now keepalived 5
3.5 高可用验证测试
3.5.1 基础访问测试(VIP 访问)
1# 在任意节点访问VIP,验证负载均衡生效 2[root@localhost ~]# curl 192.168.72.200 3nfs 192.168.72.30 4[root@localhost ~]# curl www.chengke.com # DNS已解析到VIP/HAProxy IP 5nfs 192.168.72.30 6
3.5.2 故障切换测试(主节点 HAProxy 故障)
因为脚本写了重启该服务,所以不会出现关闭的情况,除非关闭后修改其服务的配置文件使其无法启动
1# 1. 在haproxy01停止HAProxy 2[root@haproxy01 ~]# systemctl stop haproxy 3 4# 2. 验证haproxy01的keepalived是否停止(释放VIP) 5[root@haproxy01 ~]# systemctl status keepalived # 状态为stopped 6[root@haproxy01 ~]# ip a show ens160 # VIP 192.168.72.200已消失 7 8# 3. 验证haproxy02已绑定VIP 9[root@haproxy02 ~]# ip a show ens160 # 输出包含192.168.72.200/32 10 11# 4. 访问VIP验证服务不中断 12[root@localhost ~]# curl 192.168.72.200 13nfs 192.168.72.30 14 15# 5. 恢复haproxy01的HAProxy和keepalived 16[root@haproxy01 ~]# systemctl start haproxy 17[root@haproxy01 ~]# systemctl start keepalived 18# 验证VIP切回haproxy01(主节点优先级更高) 19[root@haproxy01 ~]# ip a show ens160 # VIP重新绑定 20
3.5.3 节点宕机测试(主节点关机)
1# 1. 关闭haproxy01虚拟机 2[root@haproxy01 ~]# poweroff 3 4# 2. 验证haproxy02自动接管VIP 5[root@haproxy02 ~]# ip a show ens160 # 包含VIP 192.168.72.200 6 7# 3. 访问VIP验证服务正常 8[root@localhost ~]# curl 192.168.72.200 9nfs 192.168.72.30 10 11# 4. 重启haproxy01,验证VIP切回主节点 12[root@haproxy01 ~]# systemctl start keepalived 13[root@haproxy01 ~]# ip a show ens160 # VIP重新绑定 14
1以上测试可直接进行,但是如果要测试www.chengke.com,需要将dns服务器上的区域文件做相对应的修改,并且重启named服务 2 3[root named]# cat chengke.com.zone 4$TTL 1D 5@ IN SOA ns1.chengke.com. root.chengke.com. ( 6 2026012202 ; serial(必须递增,10位) 7 86400 ; refresh (1D,用秒更规范) 8 3600 ; retry (1H) 9 604800 ; expire (1W) 10 10800 ) ; minimum (3H) 11 IN NS ns1.chengke.com. 12ns1.chengke.com. IN A 192.168.72.40 13www.chengke.com. IN A 192.168.72.200 14[root named]# systemctl restart named 15 16 17[root keepalived]# curl www.chengke.com 18nfs 192.168.72.30 19
3.6 核心流程升级总结
- NFS 提供统一 Web 文件共享,所有 Nginx 节点挂载后内容一致;
- Nginx 作为 Web 服务,接收 HAProxy 分发的请求;
- 双 HAProxy 节点通过 keepalived 实现高可用:
- 主节点(haproxy01)绑定 VIP,承担负载均衡;
- 备节点(haproxy02)实时监控主节点状态,故障时自动接管 VIP;
- 健康检查脚本确保 HAProxy 进程异常时自动重启或切换 VIP;
- DNS 将域名(www.chengke.com)解析到 VIP(192.168.72.200),实现域名访问的高可用。
3.7 注意事项
- keepalived 主备节点的
virtual_router_id和auth_pass必须一致; - 优先级(priority)主节点需高于备节点,确保主节点恢复后重新接管 VIP;
- 健康检查脚本需在主备节点都配置,避免单节点脚本缺失导致切换异常;
- 所有节点的防火墙需放行 VRRP 协议(默认已关闭防火墙,若开启需配置:
firewall-cmd --permanent --add-protocol=vrrp && firewall-cmd --reload)。
三、核心流程总结
- NFS 提供统一的 Web 文件共享,所有 Nginx 节点挂载后内容一致;
- Nginx 作为 Web 服务,接收 HAProxy 分发的请求;
- HAProxy 通过轮询算法将请求分发到 nginx1/nginx2,实现负载均衡;
- DNS 将域名(www.chengke.com)解析到 HAProxy 的 IP,实现域名访问。
《haproxy案例项目(haproxy+dns+nginx+nfs+keepalived)》 是转载文章,点击查看原文。