1. 为什么我会在实验环境里折腾这套组合
先说个背景。之前帮一个业务团队做内部系统的双机改造,他们当时的架构是一台 nginx 扛所有流量,业务方最怕的不是 nginx 挂了,而是"挂了没人知道、知道了切不过去"。改 DNS 要等 TTL 生效,改完还有一堆本地缓存,等解析刷新完,用户早就投诉了。所以当时调研了一圈高可用方案,最后选定 keepalived + nginx 做实验验证,核心诉求就一个:让 IP 自己会漂移,让切换对用户无感。
很多人容易把 keepalived 当成 nginx 专属组件,其实它是独立的开源项目,本身做的是 Linux 下的高可用管理,最拿手的是基于 VRRP 协议实现虚拟 IP(VIP)漂移。它不关心你的业务是 nginx、tomcat 还是 MySQL,只要服务监听在某个端口,keepalived 就能通过健康检查感知状态,在节点故障时自动把 VIP 切到备用节点。这种解耦设计非常实用,一台 keepalived 可以同时管理多个服务的漂移策略,也可以只用它做纯粹的 IP 高可用。
这套方案到底解决了什么问题?打个比方,你家里宽带配了一个固定公网 IP,你用一台路由器拨号,路由器坏了全家断网。如果你的宽带支持两台路由器做 VRRP 热备,那任意一台坏了,另一台会立刻接手同一个 IP,终端设备根本感知不到底层发生了什么。keepalived + nginx 就是把这个思路搬到服务器上:两台 nginx 共享一个 VIP,正常情况下流量走主节点,主节点出问题时 VIP 自动漂移到备节点,客户端连接的还是同一个地址。
这篇实验笔记适合谁看?如果你正在做 Linux 运维入门、准备面试环境演练、或者要给业务上一个低成本的同城双机高可用方案,可以直接照着搭。实验本身不复杂,但涉及网络协议、系统配置、服务切换等多个层面,我会把我踩过的坑、排查的思路一起写出来,而不是只给你一份能跑通的配置文件。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 实验拓扑与前置准备
2.1 网络拓扑和角色分配
我的实验环境用的是两台 CentOS 7.9 虚拟机,示意图上没有花哨的架构,就是最经典的一主一备。主节点 hostname 设为 lb01,IP 为 192.168.80.131;备节点 lb02,IP 为 192.168.80.132。两者原本不在同一个广播域时需要先打通二层网络,这里我直接用同一台物理宿主机上的 VMware NAT 网段,天然满足 VRRP 报文传输的条件。
VIP 我规划的是 192.168.80.130,和两台节点同网段。有人会问,VIP 能不能和业务 IP 不同网段?理论上只要交换机路由可达就能生效,但实验环境里面越简单越好,同网段会让抓包、验证和排障都省很多事。
顺带把域名映射也做了,我在这套环境里配了一个实验域名 app.lab.local 指向 VIP,这样可以模拟真实场景:用户访问域名,DNS 解析到 VIP,流量进入 nginx 集群。当然域名不是必须的,直接 curl VIP 也可以,但有域名会让后续验证更接近生产。
2.2 软件版本选择和安装源
nginx 版本我选了 1.24.0 的官方稳定版,没有用操作系统自带的 1.20 老版本。原因很简单:实验的目的是贴近线上,而线上越来越多的模块要求新版本特性,比如 HTTP/2、Stream 模块增强。keepalived 用的是 2.0.20,这个版本对 VRRP v2/v3 的支持都比较成熟,状态机的日志也更清晰,排障时会友好很多。
安装源方面,nginx 我直接配了官方 yum 源:
bash复制rpm -ivh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm
keepalived 在 EPEL 源里就有,版本可能不是最新但足够稳定。装完第一件事是检查版本号,别小看这一步,很多配置写法在不同版本间有细微差异,比如 vrrp_script 的定义方式、某些参数的默认值,版本不对照着老教程写容易踩坑。
2.3 系统基础配置:关防火墙,改主机名,同步时间
实验环境我先临时关闭了 firewalld 和 selinux。生产环境我不会建议直接关防火墙,而是放行 VRRP 协议(协议号 112)和 80 端口。但实验阶段关掉能减少一个变量,等你把整个链路跑通以后,再逐步把防火墙规则加回来验证,这样排障范围更可控。
bash复制systemctl stop firewalld && systemctl disable firewalld
sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config
setenforce 0
然后就是时间同步。keepalived 的日志里会带时间戳,如果两台机器时间偏差太大,分析主备切换时序时会非常痛苦。我用 ntpdate 手动同步到阿里云 NTP 服务器:
bash复制yum install -y ntpdate
ntpdate ntp.aliyun.com
主机名和 hosts 也顺手配好:
bash复制hostnamectl set-hostname lb01
echo "192.168.80.131 lb01" >> /etc/hosts
echo "192.168.80.132 lb02" >> /etc/hosts
准备工作到这里已经花掉大约 20 分钟,但它帮我省掉了很多后面排查的时间。我见过有人跳过这些"无关紧要"的配置直接跑 keepalived,最后日志里全是莫名其妙的切换记录,查了半天才发现是系统时间差了 10 分钟加上主机名解析失败导致的。
3. 两台机器上的 nginx 基础部署
3.1 安装与配置文件结构说明
在两台机器上执行同样的 nginx 安装步骤:
bash复制yum install -y nginx
systemctl enable nginx
装完之后,nginx 的主配置文件在 /etc/nginx/nginx.conf,默认通过 include 方式加载 /etc/nginx/conf.d/*.conf 下的所有子配置。这种按目录拆分配置的做法我很推荐,实验里我把站点配置独立成 /etc/nginx/conf.d/app.conf,而不是全部堆在主配置文件里,这样切换、修改、备份都清晰。
关于配置文件结构,我多说几句。新手最容易犯的错是改完主配置文件就四处找"重启"命令,但 nginx 推荐的是 nginx -t 先校验语法,然后用 systemctl reload nginx 平滑重载配置。如果直接 restart,建立过的连接全部断开,生产上会有一瞬间的抖动;reload 则是 master 进程不退出,重新加载配置后 worker 平滑替换,对用户的影响小很多。实验环境虽然没有那么讲究,但从一开始就养成正确习惯,后面上生产会少踩很多坑。
3.2 区分主备节点的标志页面
为了让故障切换的验证结果一目了然,我在两台机器的默认站点配置里放了不同的标识内容。lb01 返回的页面标题是 "APP Server - LB01",lb02 返回 "APP Server - LB02",正文里再附带各自的 hostname 和 IP 信息。
nginx复制server {
listen 80 default_server;
server_name _;
root /usr/share/nginx/html
