Linux第30篇:高可用架构设计:Keepalived+HAProxy构建无单点故障系统
2026/7/28 12:20:12 网站建设 项目流程

一句话定义:本文系统讲解如何使用Keepalived + HAProxy构建高可用、可扩展的入口流量调度层,通过虚拟IP(VIP)漂移与负载均衡技术,消除单点故障,实现入口层故障秒级自动切换与流量分发。

一、引言:集群有了,但大门只有一个

经过第25篇的实战,你已经成功地将Java SaaS应用部署到了Kubernetes集群。应用跑在多个Pod上,即便某个Pod挂了,K8s也会自动重启——应用层实现了高可用。Master节点也做了高可用部署。

但回头审视一下整体架构,你会发现一个被忽略的脆弱环节:整个系统的“大门”只有一个

无论是用户访问还是K8s集群内部组件的通信,流量都要经过一个统一的入口。如果这个入口所在的服务器宕机了,会发生什么?

  • 外部用户无法访问你的SaaS应用
  • 内部K8s组件(如kubelet)无法连接API Server
  • 整个系统虽然内部“活着”,但对外“失联”了

这就是典型的单点故障(SPOF, Single Point of Failure)

在Java SaaS部署的全链路中(第25篇Kubernetes →第26篇高可用架构→ 第27篇安全加固),高可用架构是从“能跑”走向“扛造”的关键一跃。本篇将带你使用Keepalived + HAProxy这对黄金组合,构建一个无单点故障的入口高可用层。

二、架构设计:Keepalived + HAProxy 黄金组合

2.1 核心组件与工作原理

这套高可用架构由两个核心组件协同工作:

组件职责核心技术
HAProxy负载均衡器,将流量分发到后端多个服务器四层/七层代理、健康检查
Keepalived高可用守护进程,实现VIP在主备节点间漂移VRRP协议、心跳检测

Keepalived是如何工作的?

Keepalived基于VRRP(虚拟路由冗余协议)实现高可用。简单来说:

  1. 多台服务器组成一个“虚拟路由器组”,对外提供一个虚拟IP(VIP)
  2. 其中一台被选举为Master(主节点),持有VIP并响应请求
  3. 其余为Backup(备节点),持续监听Master的心跳
  4. 当Master宕机或HAProxy进程异常时,Backup自动接管VIP
  5. 故障切换时间通常在2-3秒内完成,业务几乎无感知

HAProxy负责什么?

HAProxy是一个高性能的开源负载均衡器,支持:

  • 四层(TCP)负载均衡:适用于数据库连接、K8s API Server等
  • 七层(HTTP/HTTPS)负载均衡:适用于Web应用,支持路径路由、会话保持等
  • 健康检查:实时监测后端服务状态,自动隔离故障节点

2.2 整体架构拓扑

┌─────────────────────┐ │ 客户端 │ │(用户 / kubectl)│ └──────────┬──────────┘ │ ▼ ┌─────────────────────┐ │ VIP:192.168.1.100 │ ← 虚拟IP,对外统一入口 └──────────┬──────────┘ │ ┌────────────────┼────────────────┐ │ │ │ ▼ ▼ ▼ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │ Keepalived │ │ Keepalived │ │ Keepalived │ │ + HAProxy │ │ + HAProxy │ │ + HAProxy │ │(Master)│ │(Backup)│ │(Backup)│ │192.168.1.11 │ │192.168.1.12 │ │192.168.1.13 │ └────────┬────────┘ └────────┬────────┘ └────────┬────────┘ │ │ │ └────────────────────┼────────────────────┘ │ ▼ ┌─────────────────────────┐ │ 后端服务集群 │ │ ┌─────────────────────┐ │ │ │ K8s API Server:6443 │ │ │ ├─────────────────────┤ │ │ │ Java App:8080 │ │ │ ├─────────────────────┤ │ │ │ MySQL:3306 │ │ │ └─────────────────────┘ │ └─────────────────────────┘

💡架构要点:HAProxy负责“往哪转发”,Keepalived负责“谁在干活”——两者分工明确,配合默契。客户端永远只和VIP打交道,后端服务器的增减对客户端完全透明。

三、环境准备

3.1 节点规划

为什么这样写:生产环境的高可用架构至少需要两台入口节点。3台更佳(奇数台有利于VRRP选举防脑裂)。以下是本文的实验环境规划:

节点角色主机名IP地址部署组件
主入口lb01192.168.1.11Keepalived (Master) + HAProxy
备入口lb02192.168.1.12Keepalived (Backup) + HAProxy
备入口lb03192.168.1.13Keepalived (Backup) + HAProxy
虚拟IP192.168.1.100由Keepalived动态管理

踩过的坑

  • 坑1:两个节点的virtual_router_id不一致,导致VRRP组无法建立
  • 坑2:防火墙没开放VRRP协议端口(112),Keepalived心跳包被拦截
  • 坑3:auth_pass在主备节点不一致,认证失败

注意事项

  • 所有入口节点必须安装HAProxy和Keepalived
  • 确保节点间网络互通,防火墙开放VRRP协议(协议号112)
  • 生产环境建议使用3台入口节点(奇数),避免“脑裂”问题

3.2 系统基础配置

代码块:所有入口节点执行

# 1. 设置主机名(各节点不同)hostnamectl set-hostname lb01# lb01执行hostnamectl set-hostname lb02# lb02执行hostnamectl set-hostname lb03# lb03执行# 2. 配置hosts解析cat>>/etc/hosts<<EOF 192.168.1.11 lb01 192.168.1.12 lb02 192.168.1.13 lb03 EOF# 3. 关闭防火墙(或开放VRRP协议)systemctl stop firewalld systemctl disable firewalld# 4. 关闭SELinux(或配置策略)setenforce0sed-i's/SELINUX=enforcing/SELINUX=disabled/g'/etc/selinux/config# 5. 开启IP转发(HAProxy需要)echo'net.ipv4.ip_forward = 1'>>/etc/sysctl.confsysctl-p

执行后说明net.ipv4.ip_forward=1允许服务器转发网络包,是HAProxy作为代理工作的前提。关闭防火墙和SELinux是为了简化实验——生产环境应针对性开放端口和配置SELinux策略,而非一刀切关闭。

四、安装与配置HAProxy

4.1 安装HAProxy

为什么这样写:HAProxy的安装方式因操作系统而异。本文以Rocky Linux 9 / CentOS 9为例,给出最简洁的安装命令。

代码块:安装HAProxy

# Rocky Linux / CentOSdnfinstall-yhaproxy# Ubuntu / Debianaptupdate&&aptinstall-yhaproxy# 验证安装haproxy-v# 应输出类似:HAProxy version 2.6.12

执行后说明:安装完成后,HAProxy的配置文件位于/etc/haproxy/haproxy.cfg。服务尚未启动——等配置好后再启动。

4.2 配置HAProxy

为什么这样写:HAProxy的配置文件分为几个核心部分——global(全局配置)、defaults(默认参数)、frontend(入口监听)、backend(后端服务器池)。理解这个结构,配置就清晰了。

踩过的坑

  • 坑1:bind配置写成了0.0.0.0:80,但HAProxy需要绑定VIP(而非本机IP)
  • 坑2:健康检查的timeout check设得太短,后端响应稍慢就被误判为宕机

代码块:HAProxy核心配置(/etc/haproxy/haproxy.cfg)

# ============================================================ # 全局配置 # ============================================================ global log /dev/log local0 log /dev/log local1 notice chroot /var/lib/haproxy pidfile /var/run/haproxy.pid maxconn 4000 user haproxy group haproxy daemon stats socket /var/lib/haproxy/stats # ============================================================ # 默认配置(所有frontend/backend继承) # ============================================================ defaults mode http log global option httplog option dontlognull option http-server-close option forwardfor except 127.0.0.0/8 option redispatch retries 3 timeout http-request 10s timeout queue 1m timeout connect 10s timeout client 1m timeout server 1m timeout http-keep-alive 10s timeout check 10s maxconn 3000 # ============================================================ # 场景一:四层负载均衡(TCP)—— 适用于K8s API Server # ============================================================ frontend kubernetes-api bind 192.168.1.100:6443 # 绑定VIP的6443端口 mode tcp option tcplog default_backend k8s-api-backend backend k8s-api-backend mode tcp balance roundrobin # 轮询算法 option tcp-check # K8s Master节点列表 server k8s-master1 192.168.1.101:6443 check inter 5s fall 3 rise 2 server k8s-master2 192.168.1.102:6443 check inter 5s fall 3 rise 2 server k8s-master3 192.168.1.103:6443 check inter 5s fall 3 rise 2 # ============================================================ # 场景二:七层负载均衡(HTTP)—— 适用于Java SaaS应用 # ============================================================ frontend http-in bind 192.168.1.100:80 mode http option httplog # 根据路径路由到不同后端 acl is_api path_beg /api acl is_web path_beg / use_backend api-backend if is_api default_backend web-backend backend web-backend mode http balance roundrobin option httpchk GET /actuator/health http-check expect status 200 # Java应用Pod列表(可通过K8s Endpoints自动发现) server app-pod1 10.244.1.10:8080 check inter 5s fall 3 rise 2 server app-pod2 10.244.1.11:8080 check inter 5s fall 3 rise 2 server app-pod3 10.244.2.10:8080 check inter 5s fall 3 rise 2 backend api-backend mode http balance roundrobin option httpchk GET /actuator/health http-check expect status 200 server api-pod1 10.244.1.20:8080 check inter 5s fall 3 rise 2 server api-pod2 10.244.2.20:8080 check inter 5s fall 3 rise 2 # ============================================================ # 统计页面(方便监控) # ============================================================ listen stats bind 0.0.0.0:8404 mode http stats enable stats uri /stats stats realm HAProxy\ Statistics stats auth admin:your_password stats admin if TRUE

执行后说明:这个配置涵盖了两个典型场景:

  1. 四层TCP负载均衡mode tcp):适用于K8s API Server(6443端口),纯TCP转发,不做HTTP解析。
  2. 七层HTTP负载均衡mode http):适用于Java SaaS应用,支持基于路径的路由(/api走API后端,/走Web后端)。

关键参数解读

  • balance roundrobin:轮询算法,请求依次分发到各后端
  • check inter 5s fall 3 rise 2:每5秒检查一次,连续3次失败标记为down,连续2次成功恢复为up
  • option httpchk GET /actuator/health:HTTP健康检查,请求/actuator/health,期望返回200
  • bind 192.168.1.100:6443:绑定VIP地址——注意这里绑的是VIP,不是本机IP

五、安装与配置Keepalived

5.1 安装Keepalived

代码块:安装Keepalived

# Rocky Linux / CentOSdnfinstall-ykeepalived# Ubuntu / Debianaptupdate&&aptinstall-ykeepalived# 验证安装keepalived-v

5.2 配置Keepalived(Master节点)

为什么这样写:Keepalived的核心配置在/etc/keepalived/keepalived.conf中。它定义了三件事:①这个节点是Master还是Backup;②VRRP组的参数(ID、优先级、认证密码);③VIP是什么。

踩过的坑

  • 坑1:Master和Backup的priority差值不够大(如只差5),网络抖动时容易误切换
  • 坑2:virtual_ipaddress没写子网掩码(如192.168.1.100/24),VIP无法正确配置
  • 坑3:健康检查脚本没加执行权限,Keepalived无法检测HAProxy状态

代码块:Master节点Keepalived配置(/etc/keepalived/keepalived.conf)

! ============================================================ ! Master节点配置(lb01) ! ============================================================ global_defs { router_id LVS_DEVEL # 路由标识,集群内唯一 script_user root enable_script_security } vrrp_script chk_haproxy { script "/etc/keepalived/check_haproxy.sh" interval 2 # 每2秒检查一次 weight -20 # 检查失败时降低优先级 fall 2 # 连续2次失败判定为异常 rise 1 # 连续1次成功判定为恢复 } vrrp_instance VI_1 { state MASTER # 角色:主节点 interface eth0 # 监听的网卡 virtual_router_id 51 # VRRP组ID,主备必须一致 priority 100 # 优先级,数值越大越优先 advert_int 1 # 心跳广告间隔(秒) authentication { auth_type PASS # 认证类型 auth_pass 123456 # 认证密码,主备必须一致 } virtual_ipaddress { 192.168.1.100/24 dev eth0 label eth0:1 # VIP及绑定的网卡 } track_script { chk_haproxy # 关联健康检查脚本 } }

代码块:Backup节点Keepalived配置(lb02 / lb03)

! ============================================================ ! Backup节点配置(lb02 / lb03) ! ============================================================ global_defs { router_id LVS_DEVEL script_user root enable_script_security } vrrp_script chk_haproxy { script "/etc/keepalived/check_haproxy.sh" interval 2 weight -20 fall 2 rise 1 } vrrp_instance VI_1 { state BACKUP # 角色:备节点 interface eth0 virtual_router_id 51 # 必须与Master一致 priority 90 # 低于Master的100 advert_int 1 # 必须与Master一致 authentication { auth_type PASS auth_pass 123456 # 必须与Master一致 } virtual_ipaddress { 192.168.1.100/24 dev eth0 label eth0:1 } track_script { chk_haproxy } }

执行后说明:Master的priority=100,Backup的priority=90——正常情况下Master持有VIP。当Master的HAProxy进程异常时,chk_haproxy脚本返回非0,weight -20使Master优先级降至80,低于Backup的90,VIP自动漂移到Backup。

5.3 健康检查脚本

为什么这样写:Keepalived默认只检测“机器是否活着”(通过VRRP心跳),但机器活着不等于HAProxy活着。如果HAProxy进程挂了,VIP还在Master上,流量就打不出去。必须用自定义脚本检测HAProxy进程状态

代码块:HAProxy健康检查脚本(/etc/keepalived/check_haproxy.sh)

#!/bin/bash# ============================================================# HAProxy健康检查脚本# 返回0表示正常,非0表示异常(触发VIP漂移)# ============================================================# 方法1:检查HAProxy进程是否存在if!pidof haproxy>/dev/null;thenexit1fi# 方法2:检查HAProxy stats端口是否响应(更可靠)if!curl-s-o/dev/null-m2http://127.0.0.1:8404/stats;thenexit1fiexit0
# 赋予脚本执行权限chmod+x /etc/keepalived/check_haproxy.sh

执行后说明:这个脚本在Master和Backup节点上都要配置。Keepalived每2秒执行一次脚本——如果连续2次失败(fall 2),触发VIP漂移。weight -20的设计很精妙:不是直接“杀掉”Master,而是降低其优先级,让Backup通过正常的VRRP选举机制接管VIP。

六、启动与验证

6.1 启动服务

代码块:启动HAProxy和Keepalived

# ===== 所有入口节点执行 =====# 1. 启动HAProxysystemctlenablehaproxy systemctl start haproxy# 2. 检查HAProxy状态systemctl status haproxy haproxy-c-f/etc/haproxy/haproxy.cfg# 检查配置文件语法# 3. 启动Keepalivedsystemctlenablekeepalived systemctl start keepalived# 4. 检查Keepalived状态systemctl status keepalived# 5. 查看VIP是否已绑定(Master节点应显示VIP)ipaddr show eth0# 应看到:inet 192.168.1.100/24 scope global eth0:1

6.2 故障切换测试

代码块:模拟故障切换

# ===== 测试1:停止Master的HAProxy =====# 在Master节点(lb01)执行systemctl stop haproxy# 观察VIP是否漂移到Backup(lb02或lb03)# 在Backup节点执行ipaddr show eth0# 应看到VIP出现在Backup节点上# ===== 测试2:恢复Master的HAProxy =====# 在Master节点(lb01)执行systemctl start haproxy# 等待几秒后,VIP应自动回到Master# ===== 测试3:模拟Master节点宕机 =====# 在Master节点(lb01)执行systemctl stop keepalived# VIP应立即漂移到Backup节点(切换时间2-3秒)

执行后说明:故障切换的触发条件是“HAProxy进程异常”或“Keepalived进程异常”或“整机宕机”。切换过程中,已经建立的TCP连接可能会中断——对于HTTP应用,客户端重试即可恢复;对于长连接场景,需配合应用层的重连机制。

七、与Kubernetes集成:为K8s API Server提供高可用入口

为什么这样写:第25篇我们用kubeadm搭建了K8s集群,但只配置了单Master。生产环境需要多Master高可用,而多Master的前提是——Worker节点需要一个统一的API Server入口

代码块:HAProxy配置K8s API Server高可用

# 在/etc/haproxy/haproxy.cfg中添加 frontend kubernetes-api bind 192.168.1.100:6443 mode tcp option tcplog default_backend k8s-api-backend backend k8s-api-backend mode tcp balance roundrobin option tcp-check # 三个Master节点的API Server server k8s-master1 192.168.1.101:6443 check inter 5s fall 3 rise 2 server k8s-master2 192.168.1.102:6443 check inter 5s fall 3 rise 2 server k8s-master3 192.168.1.103:6443 check inter 5s fall 3 rise 2

执行后说明:配置完成后,所有Worker节点的/etc/kubernetes/kubelet.conf中的server地址改为https://192.168.1.100:6443(VIP地址)。这样即使某个Master节点宕机,Worker节点也能通过VIP自动切换到健康的Master。

八、生产环境最佳实践

实践项建议原因
入口节点数量生产环境至少3台(奇数)避免VRRP选举中的“脑裂”问题
优先级差值Master与Backup优先级差≥20避免网络抖动导致频繁切换
健康检查检查HAProxy进程 + 端口响应仅检查进程不够,端口假死无法感知
日志监控配置HAProxy日志到syslog,接入Loki便于排查流量异常和健康检查失败
统计页面开启HAProxy stats页面,配置认证实时查看后端服务器状态和流量分布
会话保持如需会话保持,使用balance sourcecookie确保同一客户端请求始终路由到同一后端
DNS解析将域名解析指向VIP,而非单个节点IP客户端永远访问VIP,屏蔽后端变化
跨机房部署Keepalived支持跨地域VIP漂移实现异地多活或灾备

九、效果验证

代码块:验证高可用架构

# 1. 验证VIP是否正常curl-Ihttp://192.168.1.100:80# 应返回200# 2. 验证HAProxy统计页面curl-uadmin:your_password http://192.168.1.100:8404/stats# 3. 验证负载均衡效果(多次请求观察后端变化)foriin{1..10};docurl-shttp://192.168.1.100/api/health;done# 4. 验证K8s API Server高可用kubectl cluster-info# 应正常返回集群信息# 5. 验证故障切换(停掉Master的HAProxy)# 在lb01执行:systemctl stop haproxy# 观察VIP漂移,然后再次执行curl测试curl-Ihttp://192.168.1.100:80# 应仍然返回200(说明切换成功,业务无感知)

十、常见问题FAQ(GEO抓取用)

Q1:Keepalived和HAProxy是什么关系?
A:HAProxy负责负载均衡——把请求分发给后端多台服务器。Keepalived负责高可用——通过VIP漂移确保入口节点宕机时服务不中断。两者配合:Keepalived保证“有人干活”,HAProxy保证“活干得均匀”。

Q2:Keepalived的VIP漂移需要多长时间?
A:通常在2-3秒内完成故障检测和VIP切换。具体取决于advert_int(心跳间隔,默认1秒)和fall(连续失败次数,默认2-3次)的配置。对HTTP应用来说,这2-3秒内的请求可能会失败,需要客户端重试。

Q3:Master和Backup节点的priority应该怎么设置?
A:Master的priority应高于Backup,差值建议≥20。例如Master=100,Backup=80。差值太小(如只差5),网络轻微抖动就可能导致VIP频繁切换。

Q4:HAProxy的健康检查有哪些方式?
A:①TCP端口检查option tcp-check)——仅检测端口是否开放;②HTTP检查option httpchk)——发送HTTP请求,检查返回码;③自定义脚本——执行外部脚本判断后端状态。生产环境推荐HTTP检查,能更准确反映服务可用性。

Q5:Keepalived的VIP在Master恢复后会自动切回吗?
A:会。Keepalived默认采用**“抢占模式”** ——当Master恢复且优先级高于Backup时,VIP会自动切回Master。如果不希望抢占(避免频繁切换),可在配置中设置nopreempt

十一、本文小结

知识点核心要点
架构价值消除入口层单点故障,实现“入口永不宕机”
Keepalived原理基于VRRP协议,主备节点共享VIP,故障时自动漂移
HAProxy原理四层/七层负载均衡,支持健康检查、会话保持、路径路由
核心配置Keepalived配置VRRP组(ID、优先级、VIP);HAProxy配置frontend+backend
健康检查自定义脚本检测HAProxy进程,weight -20优雅降级
故障切换2-3秒自动切换,业务几乎无感知
K8s集成HAProxy为多Master提供统一的API Server入口
生产实践3台入口节点、优先级差≥20、开启stats监控、日志接入Loki

💡一句话记住本篇:高可用架构的核心是“Keepalived保VIP不丢、HAProxy保流量不堵”——用VRRP协议让入口永不宕机,用负载均衡让后端永不 overload。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询