从代码 Push 到 K8s 滚动更新 —— 前端 CI/CD 全链路拆解
2026/6/30 10:55:53 网站建设 项目流程

一、引子:前端部署为什么链路这么长?

很多开发者在初次接触前端部署时,看到 Jenkins 日志里冒出一堆docker buildhelm upgradekubectl rollout,难免一头雾水。明明后端部署就是打个 jar 包扔上去java -jar就完事了,前端怎么拐了这么多弯?

其实前后端在 K8s 这套体系下跑的是完全相同的流水线逻辑,只是"集装箱"里装的东西不一样。本文以前端项目的真实 Jenkins 日志为线索,把每一步拆开讲清楚。

二、完整链路一览

Git 代码 Push │ ▼ [GitLab Runner] npm install → npm run build → 产出 dist.zip │ ▼ [Jenkins] 下载 zip → 解压 → docker build → docker push 到 Harbor │ ▼ [Jenkins] 调 Helm 通知 K8s:"用新镜像升级" │ ▼ [K8s] 拉新镜像 → 启动新 Pod → 健康检查通过 → 旧 Pod 下线 → 完成

下面逐步展开。

三、GitLab Runner 构建产物

代码 push 到 GitLab 后,第一棒是 GitLab Runner。它做的是纯粹的"体力活"——拉代码、装依赖、跑构建:

gitclone<仓库>npminstallnpmrun build# 产出 dist/ 文件夹zip-rdist.zip dist/# 压缩# 上传至文件服务器,生成下载链接

最终产出是一个 zip 文件和它的下载地址。为什么不是 Jenkins 来构建?因为 Jenkins 的 Agent 节点是通用机器,不一定装了 Node 环境。让 GitLab Runner 来构建,环境与代码仓库绑定,职责更清晰——这就是关注点分离。Jenkins 只管编排,不干具体的构建活儿。

四、Jenkins 打包 Docker 镜像

Jenkins 拿到 zip 下载链接后:

wget-Odist.zip"https://s.longhu.net/.../purchse-evaluate-web-UAT.zip"unzipdist.zip-d./distdockerbuild-tpurchse-evaluate-web-uat:263526-f./h5/dockerfile ./

实际 Dockerfile 长这样:

FROM nginx:latest # 基础镜像:自带 nginx COPY ./h5/nginx.conf /etc/nginx/nginx.conf # 换 nginx 配置 COPY ./dist /usr/share/nginx/dist # 把前端静态文件塞进去 EXPOSE 80

这个镜像本质上就是“nginx 程序 + 前端静态文件”打包成的一个标准单元。K8s 只认镜像,不认裸文件——没有镜像,它根本不知道该怎么"启动你"。

五、推送到 Harbor 镜像仓库

dockerpush harbor.longfor.com/longhu-devops-k8s-sit/purchse-evaluate-web-uat:263526

镜像仓库是必需品。Jenkins 构建镜像的机器和 K8s 集群的机器不是同一台,镜像必须上传到 Harbor(企业级 Docker Registry),K8s 各节点才能通过docker pull拉下来运行。

类比:GitLab Runner 产出 zip(原材料),Jenkins 把它装进"保温箱"(Docker 镜像),Harbor 就是中央仓库货架,K8s 各节点按需取货。

六、Helm 通知 K8s 升级

helm upgrade--setimage.tag=263526purchse-evaluate-web-uat-39856 /Docker/helm/h5

Helm 是 K8s 的包管理器(类似 yum / npm)。它用 chart 模板把部署配置(镜像名、副本数、域名、端口)打包,一条命令完成升级。

这条命令翻译成人话:“用第 263526 号版本的新镜像,替换掉现在跑着的旧版本的 purchse-evaluate-web-uat 这个服务”

七、K8s 滚动更新机制

这是整个链路最精华的部分。Helm 下发指令后,K8s 执行滚动更新(Rolling Update):

时间线 ────────────────────────────────────────→ 阶段 1:旧 Pod 正常运行 ┌──────────┐ │ 旧版本 │ ← 正在接收用户请求 └──────────┘ 阶段 2:K8s 拉新镜像,启动新 Pod ┌──────────┐ │ 旧版本 │ ← 仍在接请求(用户流量没断) └──────────┘ ┌──────────┐ │ 新版本 │ ← 启动中…拉镜像 → nginx 进程跑起来 └──────────┘ 阶段 3:健康检查(Readiness Probe) K8s 访问 http://新Pod:80/ → 返回 200 → ✅ Ready 阶段 4:切换流量,淘汰旧 Pod 旧 Pod 收到 SIGTERM → 不再接收新请求 → 处理完手头连接 → 退出 ┌──────────┐ │ 新版本 │ ← 所有流量切过来了 └──────────┘ 阶段 5:旧 Pod 删除,滚动更新完成 ✅

核心原则:整个过程中用户请求不中断。K8s 保证至少有一个 Pod 在接客,这就是"零停机部署"。

八、常见问题:部署超时

真实场景中的典型错误日志:

Waiting for deployment rollout to finish: 1 old replicas are pending termination... timeout has been exceeded: ABORTED

这不是代码问题,而是 K8s 集群层面的问题,常见原因有三个:

  • 新 Pod 没 Ready。健康检查一直不过(比如 nginx 配置错了、镜像拉不下来),K8s 不敢关旧的——关了服务就断了。
  • 旧 Pod 僵死。SIGTERM 发过去但进程不响应,一直卡在 Terminating 状态。
  • 节点资源不足。集群没有余力拉新镜像或启动新容器。

排查方式:

kubectl-ndevops get pods|greppurchse-evaluate-web-uat kubectl-ndevops describe pod<pod名># 重点看 Events 字段

大多数情况下,部署最终是成功的,只是 Jenkins 的 3 分钟超时等不及了。

九、前后端流程对比

把前后端放在同一个框架下看,逻辑完全一致:

步骤后端 jar前端
拉代码构建Maven/Gradle compilenpm run build
产出物app.jardist.zip
打包Dockerfile + java 基础镜像Dockerfile + nginx 基础镜像
部署Helm → K8sHelm → K8s
运行时JVM 启动 Spring Bootnginx 提供静态文件

唯一的区别是"集装箱里谁当服务员"——后端自带 Tomcat,前端得配 nginx。这一点在第二篇详细展开。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询