前言

最近在学习运维高可用架构,尝试用四台 Redhat 虚拟机搭建一套 Keepalived + Nginx + Tomcat 的集群环境。目标很简单:入口 IP(VIP)高可用,Nginx 做反向代理转发给后端两台 Tomcat,任意一台服务器宕机都不影响服务。

看似常规的架构,实际动手却踩了无数坑:404 下载失败、权限不足、启动脚本缺失、防火墙拦截、SELinux 捣乱……本文完整记录搭建过程和错误解决思路,希望能帮到同样在摸索的同学。


一、环境规划

角色 主机名 IP 地址 安装服务 Nginx 主 + Keepalived 主 master 192.168.211.134 nginx, keepalived Nginx 备 + Keepalived 备 backup 192.168.211.135 nginx, keepalived Tomcat 节点1 tomcat1 192.168.211.128 tomcat, jdk Tomcat 节点2 tomcat2 192.168.211.133 tomcat, jdk 虚拟 IP(VIP) - 192.168.211.100 -

所有主机均为 Redhat 8/9 系统,关闭防火墙或放行必要端口,SELinux 先临时关闭以便测试。


二、搭建过程与踩坑记录

1、安装 JDK 并配置环境变量

每台 Tomcat 节点都需要 Java 环境。下载 JDK 21,解压到 /usr/local/jdk-21.0.6/,然后配置环境变量:

vim /etc/profile

添加:

export JAVA_HOME=/usr/local/jdk-21.0.6/
export PATH=$PATH:$JAVA_HOME/bin

使生效:

source /etc/profile

验证:

java -version

2、下载 Tomcat——第一个大坑

在 Tomcat 节点上下载 Tomcat 11,我最初执行的命令是:

wget https://dlcdn.apache.org/tomcat/tomcat-11/v11.0.18/apache-tomcat-11.0.18.tar.gz

结果报错 404 Not Found。 排查:去官网查看,发现 Tomcat 11 的最新版确实是 11.0.18,但链接不对。后来才明白,二进制包的路径中必须包含 /bin/,我复制的链接其实是源码包的地址(少了 /bin/ 段)。

正确链接:

wget https://dlcdn.apache.org/tomcat/tomcat-11/v11.0.18/bin/apache-tomcat-11.0.18.tar.gz

如果还是 404,可以去官网下载页手动复制链接,或者换用 Tomcat 10 的稳定版(不影响后续测试)。


3、解压并尝试启动——权限与脚本缺失

解压后进入 bin 目录,执行 ./startup.sh 遇到一堆问题:

错误1:bash: ./startup.sh: 权限不够

解决:

chmod +x *.sh

给所有脚本加上执行权限。

错误2:Cannot find ./catalina.sh

原因:下载的 tar 包是源码包而不是二进制包,bin 目录下只有配置文件,没有 catalina.sh、startup.sh 等核心脚本。 解决:删除错误的目录,重新下载二进制包(注意链接里一定要有 /bin/ 路径)。

错误3:再次尝试启动,依然报错找不到 catalina.sh,但这次 ls bin 下确实有脚本文件

排查:检查文件权限,发现 catalina.sh 没有执行权限。 解决:

chmod +x catalina.sh startup.sh shutdown.sh

再次 ./startup.sh 终于看到 Tomcat started.


4、防火墙与 SELinux 的干扰

Tomcat 默认端口 8080,在另一台机器上访问 http://192.168.211.128:8080 无法打开。 排查:先检查 Tomcat 是否真的在监听:

netstat -tlnp | grep 8080

确认监听后,尝试关闭防火墙:

systemctl stop firewalld

再次访问成功。为了安全,也可以只放行端口:

firewall-cmd --add-port=8080/tcp --permanent
firewall-cmd --reload

SELinux 也可能会阻止,临时关闭:

setenforce 0

测试通过后,可以配置正确的 SELinux 策略,此处为快速实验先关闭。


5、配置 Nginx 反向代理

在两台 Nginx 节点上安装 nginx,修改配置文件 /etc/nginx/nginx.conf,添加 upstream 指向两台 Tomcat:

upstream tomcat_cluster {
    server 192.168.211.128:8080;
    server 192.168.211.133:8080;
}
server {
    listen 80;
    server_name 192.168.211.100;  # 这里就是最后提到的坑:server_name 要设为 VIP,不然一直显示nginx页面
    location / {
        proxy_pass http://tomcat_cluster;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

注意:server_name 如果设置成具体 IP 或域名,访问 VIP 时可能匹配不上,导致 404。所以必须改成 VIP 地址,或者用下划线 _ 匹配所有。

启动 Nginx:

systemctl start nginx

6、Keepalived 配置及 Nginx 监控脚本

在两台 Nginx 节点安装 keepalived,主节点配置如下(/etc/keepalived/keepalived.conf):

global_defs {
   router_id master
}
vrrp_script chk_nginx {
    script "/etc/keepalived/check_nginx.sh"
    interval 2
    weight -20
}
vrrp_instance VI_1 {
    state MASTER
    interface ens160
    virtual_router_id 51
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    track_script {
        chk_nginx
    }
    virtual_ipaddress {
        192.168.211.100
    }
}

备节点只需修改 state BACKUP、priority 90 和 router_id。

监控脚本 /etc/keepalived/check_nginx.sh:

#!/bin/bash
if ! ps -C nginx &>/dev/null; then
    systemctl start nginx
    sleep 2
    if ! ps -C nginx &>/dev/null; then
        systemctl stop keepalived
    fi
fi

赋予执行权限:

chmod +x /etc/keepalived/check_nginx.sh

启动 keepalived:

systemctl start keepalived

7、最后的隐藏问题:server_name 未改为 VIP

所有服务启动后,访问 http://192.168.211.100 却得到 Nginx 的默认欢迎页,而不是 Tomcat 的应用页面。 排查:检查 Nginx 配置,发现 server_name 写的是原来的 IP 地址,没有改为 VIP。导致通过 VIP 访问时,Nginx 匹配不到对应的 server 块,走了默认的 default_server(通常是欢迎页)。

解决:将 server_name 修改为 192.168.211.100 或直接用 _ 匹配所有,重启 Nginx 后问题解决。


三、最终验证

  1. 浏览器访问 http://192.168.211.100,正常显示 Tomcat 欢迎页。

  2. 手动停止主节点的 Nginx:

    systemctl stop nginx

    观察脚本会尝试重启,失败后 keepalived 自动停止,VIP 漂移到备节点,页面访问依然正常。

  3. 停止一台 Tomcat,再次刷新页面,请求自动转发到另一台 Tomcat,服务不中断。


四、项目总结与收获

通过这次完整的搭建,我不仅掌握了 Keepalived、Nginx、Tomcat 的基本配置,更重要的收获是:

· 版本和下载源一定要仔细核对,避免下载到源码包。 · 权限问题(chmod +x) 是 Linux 新手常见坑,养成检查权限的习惯。 · 防火墙和 SELinux 会拦截服务,测试时可临时关闭,生产环境要正确放行。 · 配置文件中的名称匹配(如 server_name)必须和访问地址一致,否则会导致路由错误。 · 遇到报错不要慌,看日志、查状态、逐步排查,这是运维的基本功。


Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐