可行但生产环境必须补service、健康探针和资源限制,否则易出现503、反复重启、端口不可达或调度失败;本地测试可用kubectl create deployment快速验证镜像拉取与基础调度。

直接用 kubectl create deployment 命令快速启动一个 Tomcat Pod 是可行的,但生产环境必须补上 Service、健康探针和资源限制,否则容易出现 503、反复重启、端口无法访问或调度失败等问题。
用命令行快速验证是否能拉起 Tomcat
适合本地开发或测试集群快速验证网络、镜像拉取和基础调度能力:
-
kubectl create namespace tomcat-test—— 先隔离命名空间,避免污染默认环境 -
kubectl create deployment tomcat-test --image=tomcat:9.0-jdk11 -n tomcat-test—— 注意指定明确版本,latest在不同节点行为不一致 -
kubectl get pods -n tomcat-test -o wide查看状态;如果卡在ContainerCreating,大概率是镜像拉取失败(检查kubectl describe pod中的Events字段,常见错误如ImagePullBackOff或ErrImagePull) - Tomcat 默认监听
8080,但此时 Pod 还没暴露,kubectl port-forward是最安全的临时调试方式:kubectl port-forward -n tomcat-test pod/<pod-name> 8080:8080</pod-name>
必须补上的 Service 才能对外访问
只靠 Deployment 无法从集群外访问,Service 是必选项。NodePort 最常用,但要注意端口范围和防火墙:
针对 Kubernetes 仪表板和 Web UI 的浏览器自动化。适用于与 Kubernetes Dashboard、Grafana、ArgoCD UI 或其他 Web 界面交互。需要设置 MCP_BROWSER_ENABLED=true。
- NodePort 默认端口范围是
30000–32767,手动指定需在此区间内,例如nodePort: 30080 -
type: NodePort会让每个工作节点都监听该端口,但前提是节点防火墙放行(比如firewall-cmd --add-port=30080/tcp --permanent) - Service 的
selector必须和 Deployment 中的pod template metadata.labels完全一致,否则Endpoints为空,kubectl get endpoints -n tomcat-test可验证 - 不要用
ClusterIP类型直接对外访问——它只在集群内生效,浏览器打不开
不加 livenessProbe 和 readinessProbe 的后果
Tomcat 启动慢(尤其带应用 WAR 包时),K8s 默认 30 秒无响应就杀容器,导致无限重启循环:
-
livenessProbe缺失:容器假死(Java OOM 后线程卡住但进程未退出)不会被自动重建 -
readinessProbe缺失:Pod 启动后立刻被加入 Service 的 Endpoints,但此时 Tomcat 还没完成初始化,流量进来直接 404 或 503 - 建议起步配置:
initialDelaySeconds: 60(给 Tomcat 足够启动时间),periodSeconds: 10,路径用httpGet.path: /或更轻量的/manager/status(需配 manager 用户) - 注意:路径必须返回 HTTP 200,Tomcat 默认根路径
/返回 302 跳转到/index.jsp,某些 probe 实现不跟随跳转,会误判失败
挂载自定义应用和防止空 ROOT 目录重启
官方 tomcat:* 镜像默认 webapps 下只有 ROOT 目录结构,但内容为空。K8s 探针访问 / 时 Tomcat 会返回 404,触发 readiness 失败,进而导致反复重建 Pod:
- 最简方案:在容器启动后自动复制
webapps.dist到webapps,用lifecycle.postStart:
lifecycle:
postStart:
exec:
command: ["/bin/sh", "-c", "cp -r /usr/local/tomcat/webapps.dist/* /usr/local/tomcat/webapps/"]
ConfigMap 挂载 webapps/ROOT 目录(注意 ConfigMap 不支持二进制文件,WAR 包得用 initContainer + emptyDir 中转)accessModes 是 ReadWriteOnce,且 StorageClass 支持所选节点类型(比如 hostPath 只能在单节点用)真正卡住人的往往不是部署动作本身,而是探针路径语义、镜像启动逻辑与 K8s 生命周期钩子之间的隐式耦合——比如 Tomcat 的 302 跳转、空 ROOT 目录、JVM 初始化延迟,这些都不会报错,但会让服务看起来“部署成功却无法访问”。










