采用 Docker + Kubernetes 实现 Tomcat 9 服务器高可用稳定运行方案
系统环境:Ubuntu 22.04 LTS (jammy)
部署目标:Apache Tomcat 9.0.89 + Java 17,多副本高可用,零停机发布
================================================================================
一、背景与问题说明
================================================================================
本文以站建设平台的生产环境部署为实际案例,
介绍如何将传统单节点部署升级为 Docker + Kubernetes 高可用架构。
当前项目运行环境为 Ubuntu 22.04 LTS,使用 Java 17 + Apache Tomcat 9.0.89,
应用部署在 /opt/tomcat9 目录,通过 systemd 管理服务,JVM 最大内存配置为 1024M。
这种单节点部署方式在日常开发中足够用,但在生产环境中存在明显隐患:
一旦服务器宕机、Tomcat 进程崩溃或发布新版本时,网站即刻中断,
用户访问 网站域名时直接报错,
排查和恢复都需要人工介入,无法满足 7x24 小时稳定运行的要求。
引入 Docker 容器化 + Kubernetes(K8s)编排,是解决上述问题的主流方案。
Docker 让 Tomcat 应用打包成可移植的镜像,K8s 则负责多副本调度、
自动故障恢复和滚动发布,两者结合可以在同一套基础设施上实现高可用部署。
================================================================================
二、整体架构设计
================================================================================
整体请求链路如下:
用户请求
-> Nginx Ingress(统一入口,SSL 终止)
-> K8s Service(内部负载均衡)
-> Tomcat Pod x3(多副本,分布在不同节点)
-> 持久化存储(PVC 挂载 webapps 目录)
K8s 集群至少部署 1 个 Master 节点 + 2 个 Worker 节点,
Tomcat 应用保持 3 个副本(Replica),分散到不同 Worker 节点,
任意一个节点故障,剩余副本继续对外服务,K8s 自动在其他节点拉起新 Pod。
以 wangzhanjianshe9为例,Nginx Ingress 统一接管 HTTPS 流量,
后端 Pod 的上线与下线对终端用户完全透明,体感上网站始终处于可用状态。
================================================================================
步骤1:Docker 容器化 Tomcat 9.0.89
================================================================================
基于现有环境编写 Dockerfile,镜像与本地安装保持一致:
# 1. 新建构建目录
mkdir -p /opt/docker-tomcat9 && cd /opt/docker-tomcat9
# 2. 创建 Dockerfile 文件
sudo tee Dockerfile > /dev/null <<'EOF'
FROM eclipse-temurin:17-jdk-jammy
ENV TOMCAT_VER=9.0.89
ENV CATALINA_HOME=/opt/tomcat9
RUN groupadd -r tomcat && useradd -r -g tomcat -d $CATALINA_HOME tomcat
RUN curl -fL https://archive.apache.org/dist/tomcat/tomcat-9/v${TOMCAT_VER}/bin/apache-tomcat-${TOMCAT_VER}.tar.gz \
| tar -xz -C /opt \
&& mv /opt/apache-tomcat-${TOMCAT_VER} $CATALINA_HOME \
&& chown -R tomcat:tomcat $CATALINA_HOME
COPY setenv.sh $CATALINA_HOME/bin/setenv.sh
RUN chmod +x $CATALINA_HOME/bin/setenv.sh
USER tomcat
EXPOSE 8080
CMD ["/opt/tomcat9/bin/catalina.sh", "run"]
EOF
# 3. 创建 setenv.sh(与原机器配置一致)
sudo tee setenv.sh > /dev/null <<'EOF'
#!/bin/sh
export JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64
export CATALINA_PID=/opt/tomcat9/temp/catalina.pid
export JAVA_OPTS="-Dfile.encoding=UTF-8 -Djava.awt.headless=true -Xms512m -Xmx1024m -XX:+UseG1GC -XX:MaxGCPauseMillis=200"
EOF
# 4. 构建镜像并推送到镜像仓库
docker build -t registry.wangzhanjianshe9.com.cn/myapp/tomcat9:1.0 .
docker push registry.wangzhanjianshe9.com.cn/myapp/tomcat9:1.0
# 5. 验证镜像构建结果
docker images | grep tomcat9
注意事项:
- setenv.sh 中的 JVM 参数(-Xms512m -Xmx1024m)与原机器 /opt/tomcat9/bin/setenv.sh 保持一致
- 基础镜像 eclipse-temurin:17-jdk-jammy 对应 Java 17 + Ubuntu 22.04,与现有环境匹配
- 如无私有镜像仓库,可将镜像打 tar 包拷贝到服务器:docker save ... | gzip > tomcat9.tar.gz
================================================================================
步骤2:Kubernetes 部署配置 - Deployment(多副本 + 健康检查)
================================================================================
# 创建 Deployment 配置文件
sudo tee /opt/k8s/tomcat9-deploy.yaml > /dev/null <<'EOF'
apiVersion: apps/v1
kind: Deployment
metadata:
name: tomcat9-deploy
spec:
replicas: 3
selector:
matchLabels:
app: tomcat9
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
maxSurge: 1
template:
metadata:
labels:
app: tomcat9
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchLabels:
app: tomcat9
topologyKey: kubernetes.io/hostname
containers:
- name: tomcat9
image: registry.wangzhanjianshe9.com.cn/myapp/tomcat9:1.0
ports:
- containerPort: 8080
resources:
requests:
memory: "512Mi"
cpu: "250m"
limits:
memory: "1024Mi"
cpu: "1000m"
livenessProbe:
httpGet:
path: /
port: 8080
initialDelaySeconds: 30
periodSeconds: 15
readinessProbe:
httpGet:
path: /
port: 8080
initialDelaySeconds: 20
periodSeconds: 10
EOF
# 应用 Deployment 配置
kubectl apply -f /opt/k8s/tomcat9-deploy.yaml
# 验证 Pod 运行状态(等待约 30 秒)
kubectl get pods -l app=tomcat9
# 输出应显示 3 个 Pod 状态为 Running
注意事项:
- replicas: 3 表示启动 3 个副本,任意 1 个故障不影响服务
- podAntiAffinity 确保 3 个副本分散到不同物理节点,避免单点集中
- livenessProbe 存活检测失败时 K8s 自动重启容器
- readinessProbe 就绪检测通过后才允许接收流量,确保新 Pod 启动完成再上线
- memory limits 1024Mi 与 setenv.sh 中的 -Xmx1024m 对应,防止 OOM
================================================================================
步骤3:Kubernetes 部署配置 - Service(集群内负载均衡)
================================================================================
# 创建 Service 配置文件
sudo tee /opt/k8s/tomcat9-svc.yaml > /dev/null <<'EOF'
apiVersion: v1
kind: Service
metadata:
name: tomcat9-svc
spec:
selector:
app: tomcat9
ports:
- port: 80
targetPort: 8080
type: ClusterIP
EOF
# 应用 Service 配置
kubectl apply -f /opt/k8s/tomcat9-svc.yaml
# 验证 Service 创建结果
kubectl get svc tomcat9-svc
================================================================================
步骤4:Kubernetes 部署配置 - Ingress(域名路由 + HTTPS 终止)
================================================================================
Service 只负责集群内通信,对外暴露域名需要配置 Ingress。
以下示例将 wangzhanjianshe9 的 HTTPS 请求统一路由到 tomcat9-svc。
# 创建 Ingress 配置文件
sudo tee /opt/k8s/tomcat9-ingress.yaml > /dev/null <<'EOF'
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: tomcat9-ingress
annotations:
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/proxy-connect-timeout: "60"
nginx.ingress.kubernetes.io/proxy-read-timeout: "60"
spec:
ingressClassName: nginx
tls:
- hosts:
- www.wangzhanjianshe9.com.cn
secretName: wangzhanjianshe9-tls
rules:
- host: www.wangzhanjianshe9.com.cn
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: tomcat9-svc
port:
number: 80
EOF
# 应用 Ingress 配置
kubectl apply -f /opt/k8s/tomcat9-ingress.yaml
# 验证 Ingress 状态
kubectl get ingress tomcat9-ingress
注意事项:
- secretName: wangzhanjianshe9-tls 需要提前将 SSL 证书导入 K8s Secret
- Ingress 控制器接到请求后自动完成 SSL 解密并转发给后端 Pod
- 证书更新只需替换 Secret,无需重启 Tomcat 或 Pod
================================================================================
步骤5:Kubernetes 部署配置 - HPA(水平自动扩缩容)
================================================================================
# 创建 HPA 配置文件
sudo tee /opt/k8s/tomcat9-hpa.yaml > /dev/null <<'EOF'
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: tomcat9-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: tomcat9-deploy
minReplicas: 3
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
EOF
# 应用 HPA 配置
kubectl apply -f /opt/k8s/tomcat9-hpa.yaml
# 验证 HPA 状态
kubectl get hpa tomcat9-hpa
当访问量突增时,HPA 自动将 Pod 从 3 个扩展至最多 10 个;
流量回落后再自动缩减,节省服务器资源。
================================================================================
步骤6:滚动发布与版本更新
================================================================================
K8s Deployment 默认采用 RollingUpdate 滚动发布策略,发布新版本时逐个替换旧 Pod,
始终保持至少 2 个 Pod 在线接收流量,整个过程对用户无感知。
# 发布新版本镜像
kubectl set image deployment/tomcat9-deploy tomcat9=registry.wangzhanjianshe9.com.cn/myapp/tomcat9:1.1
# 查看发布进度
kubectl rollout status deployment/tomcat9-deploy
# 输出:Waiting for deployment ... -> Deployment "tomcat9-deploy" successfully rolled out
# 如果新版本有问题,一键回滚到上一版本
kubectl rollout undo deployment/tomcat9-deploy
# 查看历史版本记录
kubectl rollout history deployment/tomcat9-deploy
注意事项:
- 滚动发布期间 maxUnavailable: 1 确保最多 1 个 Pod 不可用
- readinessProbe 通过后新 Pod 才接入流量,上线前不影响现有用户
- 回滚操作即时生效,无需重新构建镜像
================================================================================
高可用效果对比
================================================================================
节点宕机:
原 systemd 单节点方案 -> 服务中断,人工登录恢复,耗时分钟级
Docker + K8s 方案 -> 自动调度到其他节点,30 秒内恢复
Tomcat 进程崩溃:
原 systemd 单节点方案 -> 依赖 Restart=on-failure,单机重启
Docker + K8s 方案 -> liveness 探针触发自动重启,其他副本同时在线
流量突增:
原 systemd 单节点方案 -> 手动调整 JVM 参数或新增机器,响应慢
Docker + K8s 方案 -> HPA 自动水平扩容,CPU 超 70% 即触发
版本发布:
原 systemd 单节点方案 -> 停服重启,用户访问中断
Docker + K8s 方案 -> 滚动发布,零停机
多版本灰度:
原 systemd 单节点方案 -> 不支持
Docker + K8s 方案 -> 支持金丝雀发布,按比例分流
================================================================================
安装完成清单
================================================================================
✓ Docker 镜像:registry.wangzhanjianshe9.com.cn/myapp/tomcat9:1.0
✓ Tomcat 版本:9.0.89,Java 17,JVM -Xms512m -Xmx1024m
✓ 副本数量:3 个,分散在不同节点
✓ 健康检查:liveness + readiness 探针已配置
✓ 域名路由:www.wangzhanjianshe9.com.cn 已配置 Ingress + HTTPS
✓ 自动扩容:HPA 已启用,最小 3 个,最多 10 个 Pod
✓ 滚动发布:已启用,支持一键回滚
================================================================================
总结
================================================================================
通过 Docker + Kubernetes 方案,在原有 Ubuntu 22.04 + Java 17 + Tomcat 9.0.89
技术栈不变的前提下,将单点部署升级为多副本高可用架构,
显著提升了系统的稳定性、弹性和可维护性,是中小型 Java Web 项目迈向生产级部署的推荐路径。
以wangzhanjianshe9网站建设平台的实际运行为验证,
采用本方案后节点故障恢复时间从分钟级缩短至 30 秒以内,
版本发布期间用户零感知,流量高峰期 HPA 自动扩容有效规避了服务过载风险。
================================================================================
下一步建议
================================================================================
高可用部署完成后,可以继续完善:
1. 配置 Prometheus + Grafana 监控 Pod 资源使用情况
2. 配置 EFK(Elasticsearch + Fluentd + Kibana)集中收集 Tomcat 日志
3. 配置 PodDisruptionBudget 防止维护操作导致副本数不足
4. 配置数据库连接池(连接 MariaDB 11.4)提升并发处理能力
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。