從原理到實(shí)操:基于 Keepalived 的 Nginx/HAProxy 高可用部署指南
前言
在互聯(lián)網(wǎng)架構(gòu)中,負(fù)載均衡器(如 Nginx、HAProxy)是流量入口的核心組件,一旦單點(diǎn)故障將導(dǎo)致整個(gè)服務(wù)不可用。Keepalived基于VRRP(虛擬路由冗余協(xié)議)實(shí)現(xiàn)節(jié)點(diǎn)高可用,可與Nginx/HAProxy結(jié)合,構(gòu)建負(fù)載均衡 + 故障自動(dòng)切換的高可用架構(gòu)。
核心概念
組件 | 核心作用 |
Keepalived | 基于 VRRP 協(xié)議,實(shí)現(xiàn)主備節(jié)點(diǎn)的 “虛擬 IP(VIP)” 漂移,完成故障自動(dòng)切換 |
Nginx | 七層(HTTP/HTTPS)負(fù)載均衡器,支持反向代理、靜態(tài)資源緩存、SSL 終止等功能 |
HAProxy | 四層(TCP)/ 七層負(fù)載均衡器,支持會(huì)話保持、健康檢查、高并發(fā)場景,性能更優(yōu) |
VIP(虛擬 IP) | 對(duì)外提供服務(wù)的統(tǒng)一 IP 地址,主節(jié)點(diǎn)故障時(shí)自動(dòng)切換到備節(jié)點(diǎn),對(duì)業(yè)務(wù)無感知 |
VRRP 協(xié)議工作原理
圖片
VRRP 協(xié)議通過主備節(jié)點(diǎn)選舉實(shí)現(xiàn)IP冗余:
- 主節(jié)點(diǎn)(
Master):正常情況下持有VIP,對(duì)外提供服務(wù),并定期向備節(jié)點(diǎn)發(fā)送VRRP通告報(bào)文(默認(rèn)每1秒一次),告知自身狀態(tài); - 備節(jié)點(diǎn)(
Backup):監(jiān)聽主節(jié)點(diǎn)的通告報(bào)文,若超時(shí)(默認(rèn)3秒)未收到,則認(rèn)為主節(jié)點(diǎn)故障,自動(dòng)升級(jí)為新主節(jié)點(diǎn),搶占VIP; - 故障恢復(fù):原主節(jié)點(diǎn)恢復(fù)后,根據(jù)優(yōu)先級(jí)(默認(rèn)主節(jié)點(diǎn)優(yōu)先級(jí)更高)重新?lián)屨?/span>
VIP,恢復(fù)主節(jié)點(diǎn)身份(可配置非搶占模式避免頻繁切換)。
部署配置
以一主一備架構(gòu)為例(生產(chǎn)環(huán)境推薦2節(jié)點(diǎn)以上),拓?fù)淙缦拢?/span>
[客戶端] → [VIP: 192.168.1.100]
↓(自動(dòng)切換)
┌──────────────┐ ┌──────────────┐
│ 主節(jié)點(diǎn)(Master) │ │ 備節(jié)點(diǎn)(Backup) │
│ IP: 192.168.1.11 │ │ IP: 192.168.1.12 │
│ Keepalived + Nginx/HAProxy │ │ Keepalived + Nginx/HAProxy │
└──────────────┘ └──────────────┘
↓(負(fù)載均衡)
┌──────────────┐ ┌──────────────┐
│ 后端 Web 節(jié)點(diǎn)1 │ │ 后端 Web 節(jié)點(diǎn)2 │
│ IP: 192.168.1.21 │ │ IP: 192.168.1.22 │
└──────────────┘ └──────────────┘- 正常狀態(tài):主節(jié)點(diǎn)持有
VIP,客戶端流量通過VIP進(jìn)入主節(jié)點(diǎn)的Nginx/HAProxy,再轉(zhuǎn)發(fā)到后端Web節(jié)點(diǎn); - 故障狀態(tài):主節(jié)點(diǎn)宕機(jī)或負(fù)載均衡服務(wù)異常,備節(jié)點(diǎn)搶占
VIP,流量自動(dòng)切換到備節(jié)點(diǎn),業(yè)務(wù)無感知。
準(zhǔn)備與規(guī)劃
節(jié)點(diǎn)角色 | IP 地址 | 安裝軟件 |
主節(jié)點(diǎn)(Master) | 192.168.1.11 | Keepalived + Nginx/HAProxy |
備節(jié)點(diǎn)(Backup) | 192.168.1.12 | Keepalived + Nginx/HAProxy |
虛擬 IP(VIP) | 192.168.1.100 | |
后端 Web 節(jié)點(diǎn) 1 | 192.168.1.21 | Nginx/Apache |
后端 Web 節(jié)點(diǎn) 2 | 192.168.1.22 | Nginx/Apache |
前置操作(所有節(jié)點(diǎn))
# 關(guān)閉防火墻(CentOS 7)
systemctl stop firewalld && systemctl disable firewalld
# 關(guān)閉 SELINUX
setenforce 0 && sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/configKeepalived +Nginx/HAProxy安裝過程略,下面只進(jìn)行配置講解
配置主節(jié)點(diǎn)(Master)Keepalived
! Configuration File for keepalived
global_defs {
router_id LVS_MASTER # 節(jié)點(diǎn)標(biāo)識(shí),主備需不同(如備節(jié)點(diǎn)設(shè)為 LVS_BACKUP)
}
# 健康檢查腳本:檢測 Nginx/HAProxy 是否存活,若服務(wù)停則觸發(fā)切換
vrrp_script check_lb {
script "/etc/keepalived/check_lb.sh"# 健康檢查腳本路徑
interval 2 # 檢查間隔(秒)
weight -20 # 若腳本返回失敗,節(jié)點(diǎn)優(yōu)先級(jí)降低 20(確保備節(jié)點(diǎn)搶占)
}
vrrp_instance VI_1 {
state MASTER # 節(jié)點(diǎn)角色:MASTER(主)/BACKUP(備)
interface eth0 # 綁定 VIP 的網(wǎng)卡(需與實(shí)際網(wǎng)卡一致,用 ip addr 查看)
virtual_router_id 51 # 虛擬路由 ID,主備必須相同(0-255)
priority 100 # 優(yōu)先級(jí):主節(jié)點(diǎn) > 備節(jié)點(diǎn)(如備節(jié)點(diǎn)設(shè)為 90)
advert_int 1 # VRRP 通告間隔(秒),主備需一致
# 認(rèn)證配置:主備必須相同,防止非法節(jié)點(diǎn)接入
authentication {
auth_type PASS
auth_pass 1111 # 密碼(1-8 位)
}
# 虛擬 IP(VIP):可配置多個(gè),用空格分隔
virtual_ipaddress {
192.168.1.100/24 dev eth0 label eth0:0 # 網(wǎng)卡別名,便于識(shí)別
}
# 調(diào)用健康檢查腳本
track_script {
check_lb
}
}配置備節(jié)點(diǎn)(Backup)Keepalived
備節(jié)點(diǎn)配置與主節(jié)點(diǎn)類似,僅需修改3處參數(shù):
global_defs {
router_id LVS_BACKUP # 與主節(jié)點(diǎn)不同
}
vrrp_instance VI_1 {
state BACKUP # 角色為備節(jié)點(diǎn)
priority 90 # 優(yōu)先級(jí)低于主節(jié)點(diǎn)(100)
# 其他參數(shù)(virtual_router_id、auth_pass、VIP 等)與主節(jié)點(diǎn)完全一致
}編寫健康檢查腳本
檢測負(fù)載均衡服務(wù)(以Nginx為例,HAProxy只需替換服務(wù)名):
#!/bin/bash
# 檢查 Nginx 進(jìn)程是否存在
if ! ps aux | grep nginx | grep -v grep > /dev/null; then
# 嘗試重啟 Nginx(若重啟失敗則觸發(fā)切換)
systemctl start nginx
sleep 2
# 再次檢查,若仍失敗則停止 Keepalived(釋放 VIP)
if ! ps aux | grep nginx | grep -v grep > /dev/null; then
systemctl stop keepalived
fi
fi配置 Nginx 反向代理
# 定義后端 Web 節(jié)點(diǎn)池(weight 為權(quán)重,值越大分配到的流量越多)
upstream web_servers {
server 192.168.1.21:80 weight=1;
server 192.168.1.22:80 weight=1;
# 可選配置:故障重試、超時(shí)時(shí)間
keepalive 32; # 長連接數(shù)
proxy_next_upstream error timeout invalid_header;
}
# 配置反向代理
server {
listen 80;
server_name localhost; # 若有域名,可替換為實(shí)際域名(如 www.example.com)
location / {
proxy_pass http://web_servers; # 轉(zhuǎn)發(fā)到后端節(jié)點(diǎn)池
# 傳遞客戶端真實(shí) IP 及請(qǐng)求頭
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}配置 HAProxy 四層負(fù)載均衡(以 TCP 為例)
global
log 127.0.0.1 local2 # 日志配置
chroot /var/lib/haproxy
pidfile /var/run/haproxy.pid
maxconn 4000 # 最大并發(fā)連接數(shù)
user haproxy
group haproxy
daemon # 后臺(tái)運(yùn)行
defaults
mode tcp # 模式:tcp(四層)/http(七層)
log global
option tcplog
option dontlognull
retries 3 # 故障重試次數(shù)
timeout connect 5000ms # 連接超時(shí)
timeout client 50000ms # 客戶端超時(shí)
timeout server 50000ms # 服務(wù)端超時(shí)
# 前端監(jiān)聽配置(監(jiān)聽 VIP 的 80 端口)
frontend http_front
bind *:80
default_backend http_back # 轉(zhuǎn)發(fā)到后端節(jié)點(diǎn)池
# 后端節(jié)點(diǎn)池配置
backend http_back
balance roundrobin # 負(fù)載均衡算法:輪詢(roundrobin)/權(quán)重(static-rr)
server web1 192.168.1.21:80 check inter 2000 rise 2 fall 3 # check 啟用健康檢查
server web2 192.168.1.22:80 check inter 2000 rise 2 fall 3主節(jié)點(diǎn)故障切換測試
- 模擬主節(jié)點(diǎn)服務(wù)故障:在主節(jié)點(diǎn)(
192.168.1.11)停止Nginx/HAProxy服務(wù) - 觀察
VIP漂移:在備節(jié)點(diǎn)(192.168.1.12)執(zhí)行ip addr show eth0,若出現(xiàn)192.168.1.100(VIP),說明漂移成功; - 驗(yàn)證業(yè)務(wù)連續(xù)性:客戶端再次訪問
192.168.1.100,若仍能正常訪問,說明故障切換生效(業(yè)務(wù)無感知)。
補(bǔ)充說明
virtual_server
virtual_server是Keepalived中LVS模塊的核心配置項(xiàng),它的作用是:
- 在
Keepalived節(jié)點(diǎn)上直接實(shí)現(xiàn) 四層(TCP/UDP)負(fù)載均衡,將客戶端請(qǐng)求通過VIP轉(zhuǎn)發(fā)到后端真實(shí)服務(wù)器(Real Server),無需依賴Nginx/HAProxy等第三方負(fù)載均衡軟件。
! 基于 Keepalived + LVS 的配置(無需 Nginx/HAProxy)
global_defs {
router_id LVS_MASTER
}
vrrp_instance VI_1 {
state MASTER
interface eth0
virtual_router_id 51
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.1.100/24 dev eth0 label eth0:0 # VIP
}
}
# 關(guān)鍵:配置 virtual_server(LVS 負(fù)載均衡規(guī)則)
virtual_server 192.168.1.100 80 { # VIP + 監(jiān)聽端口(80 端口)
delay_loop 6 # 健康檢查間隔(秒)
lb_algo rr # 負(fù)載均衡算法:rr(輪詢)、wrr(權(quán)重輪詢)等
lb_kind DR # LVS 模式:DR(直接路由)、NAT、TUN(隧道)
persistence_timeout 50 # 會(huì)話保持時(shí)間(秒)
# 后端真實(shí)服務(wù)器(Real Server)
real_server 192.168.1.21 80 {
weight 1 # 權(quán)重
TCP_CHECK { # 健康檢查(TCP 端口檢測)
connect_timeout 3
retry 3
delay_before_retry 3
}
}
real_server 192.168.1.22 80 {
weight 1
TCP_CHECK {
connect_timeout 3
retry 3
delay_before_retry 3
}
}
}
























