基于 CentOS7 搭建 5 节点三层高可用 Web 集群(Nginx+Keepalived+Tomcat+MySQL 主从)
本文记录了本人从零规划、搭建一套 5 节点 CentOS7 高可用 Web 业务集群的完整实操全过程,采用经典三层架构:前端通过 Nginx+Keepalived 基于 VRRP 协议实现负载均衡与虚拟 IP 故障自动漂移,消除网关单点故障;中间层部署两台 Tomcat 服务器承载 Web 应用,分担访问压力;底层使用 MySQL 5.7 搭建一主一从二进制日志复制架构,实现数据实时热备份。 整套环境依托 VMware 虚拟机模板批量克隆部署,搭建过程中踩坑并解决了网段不匹配、端口不通、数据库同步异常、权限策略报错等大量运维常见问题,同时完成主节点宕机故障模拟演练,验证集群业务连续性。
1.模板机初始化 + 5 台虚拟机批量克隆与网络规划
用户访问VIP192.168.2.100 → Keepalived自动把流量切到主Nginx,Nginx做负载均衡转发给Tomcat应用,Tomcat读写MySQL主从数据库。
| 虚拟机名称 | 集群角色 | 分配静态 IP | 预装软件 |
|---|---|---|---|
| centos-master | Nginx 主节点 | 192.168.2.10 | Nginx、Keepalived |
| centos-backup | Nginx 备节点 | 192.168.2.11 | Nginx、Keepalived |
| centos-app | Tomcat 应用服务器 | 192.168.2.12 | JDK1.8、Tomcat8 |
| centos-mysql1 | MySQL 主库 | 192.168.2.14 | MySQL5.7 |
| centos-mysql2 | MySQL 从库 | 192.168.2.15 | MySQL5.7 |
统一对外 VIP:192.168.2.100
准备
先对模板机进行初始化:
切换root模式,全程用root操作
关闭防火墙&设置开机不自启
systemctl stop firewild systemctl disable firewalld
关闭SElinux(永久关闭)
安装必备基础依赖包
作用:• net-tools:提供ifconfig查看网卡IP
• wget:下载安装包
• vim:编辑器
• openssl/pcre:后面编译Nginx必备依赖
执行备份原yum源的命令(把系统默认文件做备份,避免后续出现问题无法回滚)
下载阿里云Centos7源文件
若提示wget找不到,可用curl版本
刷新yum缓存(换源必做!)
查看源文件是否替换成功
安装epel扩展源(后面装keepalived,nginx需要用)
设置主机名(模板机临时名字,克隆后每台再单独改)
优化SSH连接(可选)
系统时间同步(集群时间须统一)
注:模板机保持DHCP自动获取即可
以上执行完成后,关机halt
克隆
卡隆方式要选择 完整克隆!!!依次克隆出五台机器并分别命名
以第一台Nginx主节点master为例:
修改主机名
修改网卡配置为静态IP
清空原有的内容,只修改IPADDR对应的地址
BOOTPROTO=static
ONBOOT=yes
IPADDR=192.168.2.10 # 每台替换成表格里的对应IP
NETMASK=255.255.255.0
GATEWAY=192.168.2.2
DNS1=8.8.8.8
DNS2=114.114.114.114
重启网卡服务生效
验证本机IP:ifconfig
连通性测试:在任意一台机器ping其他所有ip,能通代表网络环境已经搭建完成!
2.Nginx+Keepalived 主备负载均衡部署与漂移测试
目的:实现负载均衡+故障自动切换VIP,后端转发到Tomcat
——两台机器都安装Nginx+Keepalived(192.168.2.10,192.168.2.11)
yum install -y nginx keepalived # 设置开机自启
systemctl enable nginx keepalived
systemctl start nginx
——编辑配置文件(两台配置一样)
vim /etc/nginx/nginx.conf
删掉全部原有内容,写入如下配置:
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
keepalive_timeout 65;
# 后端Tomcat服务器集群
upstream tomcat_pool {
server 192.168.2.12:8080;
}
server {
listen 80;
server_name _;
location / {
proxy_pass http://tomcat_pool;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
}
检查配置:
nginx -t
systemctl restart nginx
配置Keepalived虚拟IP漂移
1.主节点master192.168.2.10:
vim /etc/keepalived/keepalived.conf
完整配置:
global_defs {
router_id NGINX_MASTER
}
vrrp_instance VI_1 {
state MASTER
interface ens33
virtual_router_id 51
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.2.100/24
}
}
2.备节点backup192.168.2.11:
vim /etc/keepalived/keepalived.conf
完整配置:
global_defs {
router_id NGINX_BACKUP
}
vrrp_instance VI_1 {
state BACKUP
interface ens33
virtual_router_id 51
priority 90
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.2.100/24
}
}
两台启动Keepalived!
systemctl start keepalived
在主节点查看是否生成VIP:
ip addr
此时192.168.2.100在主节点上,在主节点上执行systemctl stop keepalived,然后去backup执行
ip addr,会发现VIP已经自动切换回来,代表双击热备成功!
3.Tomcat 集群部署 + Nginx 反向代理配置
登录192.168.2.12 centos-app,安装JDK8
yum install -y java-1.8.0-openjdk-devel
验证是否安装成功:
java -version
javac -version
下载并解压Tomcat8.5:
# 下载安装包
wget https://archive.apache.org/dist/tomcat/tomcat-8/v8.5.98/bin/apache-tomcat-8.5.98.tar.gz
# 解压到 /usr/local 目录
tar -zxvf apache-tomcat-8.5.98.tar.gz -C /usr/local/
编写测试页面,验证Nginx转发
vim /usr/local/tomcat8/webapps/ROOT/index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<body>
<h2>Server Node: 192.168.2.12 Tomcat</h2>
<p>Access VIP: 192.168.2.100</p>
</body>
</html>
EOF
启动Tomcat
/usr/local/tomcat8/bin/startup.sh
避坑:
为避免系统里不存在这个文件夹路径等,可先查找本机真正的网络根目录,
执行find / -name webapps,正常会输出类似:/usr/share/tomcat/webapps 这才是真实路径
然后再用正确路径创建测试页面:
cat > /usr/share/tomcat/webapps/ROOT/index.jsp <<EOF
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<body>
<h2>Server Node: 192.168.2.12 Tomcat</h2>
<p>Access VIP: 192.168.2.100</p>
</body>
</html>
验证是否创建成功:ls /usr/share/tomcat/webapps/ROOT/ (出现index.jsp即为成功)
放行端口并重启服务:
firewall-cmd --add-port=8080/tcp --permanent
firewall-cmd --reload
浏览器验证:
避坑:
1. 只去连VIP 192.168.2.100,主备节点没启动Keepalived,VIP不存在,必然失败;
2. 桥接没绑定正确物理网卡,虚拟机拿到别的网段IP,局域网不通;
3. 重启后防火墙自动开启,之前临时关闭的设置失效;
高可用故障漂移测试:
1. 关闭当前承载VIP的主Nginx主机
2. 持续刷新网页,只会短暂卡顿一下,页面立刻恢复访问
3. 查看备用机,VIP已经自动漂移过来,实现故障自动切换
4.MySQL 一主一从搭建
主机:centos-mysql1 192.168.2.14(主库 Master)
从机:centos-mysql2 192.168.2.15(从库 Slave)
两台机器执行前置操作:
# 关闭防火墙
systemctl stop firewalld
systemctl disable firewalld
setenforce 0
两台机器安装MySQL5.7:
安装yum源
rpm -ivh https://dev.mysql.com/get/mysql57-community-release-el7-11.noarch.rpm
安装服务
yum install -y mysql-community-server
systemctl start mysqld
systemctl enable mysqld
获取初始临时密码
grep 'temporary password' /var/log/mysqld.log
登录并修改密码
mysql -uroot -p
ALTER USER 'root'@'localhost' IDENTIFIED BY 'Root@123456';
exit;
配置Master主库(192.168.2.14)
编辑配置文件:
vi /etc/my.cnf
写入:
[mysqld]
server-id=1
log-bin=mysql-bin
binlog-format=ROW
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
保存退出,重启MySQL:systemctl restart mysqld
登录MySQL,创建账号:mysql -uroot -pRoot@123456
执行:
CREATE USER 'repl'@'%' IDENTIFIED BY 'Repl@123456';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%';
FLUSH PRIVILEGES;
-- 锁定库,防止配置期间数据变动
FLUSH TABLES WITH READ LOCK;
查看主库状态,记录File和Position: SHOW MASTER STATUS;
配置Slave主库(192.168.2.15)
编辑配置文件:
vi /etc/my.cnf
写入:
[mysqld]
server-id=2
log-bin=mysql-bin
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
保存退出,重启MySQL:systemctl restart mysqld
登录MySQL,绑定主库:mysql -uroot -pRoot@123456
把下面对应参数换成刚才SHOW MASTER STATUS查询出来的值:
STOP SLAVE;
CHANGE MASTER TO
MASTER_HOST='192.168.2.14',
MASTER_USER='repl',
MASTER_PASSWORD='Repl@123456',
MASTER_LOG_FILE='mysql-bin.000002',#填查到的file名称
MASTER_LOG_POS=747;#填查到的Position数字
启动同步:
START SLAVE;
检查同步状态:
SHOW SLAVE STATUS\G
必须同时满足两个Yes才算成功:
• Slave_IO_Running: Yes
• Slave_SQL_Running: Yes
验证同步效果:
切回主库MySQL窗口,解锁表:
UNLOCK TABLES;
主库新建库,插入测试数据:
CREATE DATABASE test_db;
USE test_db;
CREATE TABLE t(id INT);
INSERT INTO t VALUES(100);
若能从从库查询到这条数据,代表主从搭建完成!
项目总结与后续规划
本次搭建的三层高可用集群,是传统企业机房非常经典的部署方案,完美结合了 TCP/IP 网络原理、VRRP 冗余协议、Linux 系统运维、Web 服务与数据库冗余设计等理论知识。通过亲手完成环境规划、配置部署、错误排查、故障验证,彻底理解了单点故障带来的业务风险,以及负载均衡、主备切换、数据备份的设计意义。
访问链路:
浏览器 → 192.168.2.100(Nginx虚拟VIP)→ 两台Nginx负载均衡 → Tomcat应用节点 → MySQL主库写入、从库同步备份。
现阶段整套集群已经可以稳定运行,为了进一步提升项目深度,后续计划分步完成升级:
- 编写 Shell 批量运维脚本,替代重复手动命令,提升部署效率;
- 接入 Prometheus+Grafana 监控体系,实现服务器、服务、数据库状态实时监测与异常告警;
- 完成 MySQL 读写分离改造,搭配 Redis 缓存优化数据库访问压力;
- 使用 Docker 完成服务容器化部署,进一步可向 K8s 编排方向延伸;
- 将整套架构迁移至公有云服务器,适配线上生产环境部署逻辑。
本文仅作为个人原创项目实训笔记,可供参考学习,禁止商用二次转载。