部署工具的一些思考:一个转行程序员的血泪踩坑日记
去年秋天,我正式告别了干了八年的传统制造业,带着一肚子对“写代码改变世界”的憧憬,入职了一家做 SaaS 产品的中型互联网公司。没错,就是那种每天被产品经理追着问“这个需求能不能下周上线”、被测试小姐姐翻白眼说“又冒烟失败了”、被运维老哥冷笑着甩一句“你这部署脚本连生产环境都进不去”的地方。
入职两个月,头发少了三成,体重轻了十斤,但收获也确实不少——至少现在听到“K8s”、“CI/CD”、“Helm Chart”这些词不会再一脸懵了。今天想和大家聊聊我最近在折腾的一件事:部署工具的选择与使用。起因?很简单:上周五晚上9点,又被拉进了一个“线上发布事故复盘会”。
事情是怎么崩的?
事情得从一个看似人畜无害的需求说起。产品同学说:“老板看了竞品,觉得我们的后台管理界面太丑了,能不能加个暗黑模式?顺便把用户头像上传功能优化一下。”听起来不难对吧?我心想:前端改点样式 + 后端加个接口,顶多两天搞定。
结果呢?后端逻辑倒是没问题,本地跑得飞起。但一到预发环境,死活传不上图片。查了半天日志,发现是 Nginx 配置里没开 client_max_body_size,而我们的部署脚本居然是手动复制粘贴上一次的 YAML 文件改几个参数……更离谱的是,这次改了前端静态资源路径,但部署脚本里硬编码了 /static/v1,新版本变成了 /static/v2,导致所有 CSS 和 JS 404。
运维老哥在群里@我:“兄弟,你这部署流程比我家老太太腌咸菜还靠手艺,下次能不能自动化点?”
我:……(内心OS:我也想啊!但我才来俩月,连 Jenkins 是啥都还没摸清)
这场事故直接让我在周一的站会上被点名:“新来的同学,部署这块你得多担起来。”
行吧,被逼上梁山了。
从“面试题挑战”到现实打脸
其实早在转行学编程那会儿,我就刷过不少“DevOps 面试题”,比如:
“谈谈你对 CI/CD 的理解?”
“Jenkins 和 GitLab CI 有什么区别?”
“如何实现零停机部署?”
当时背得头头是道,答得天花乱坠,仿佛自己已经手握百万级流量系统的发布大权。结果真到了公司,才发现:理论很丰满,现实全是补丁。
我们团队目前用的是一套“半自动”部署流程:
- 代码提交 → 触发 Jenkins 构建 Docker 镜像
- 运维手动登录服务器,执行一段 shell 脚本拉取镜像、停旧服务、启新服务
- 如果出问题,靠人工回滚(对,就是
cp backup.tar.gz . && docker-compose up -d)
这套流程在小项目上还能苟延残喘,但一旦涉及多服务、多环境(dev/staging/prod)、数据库迁移,就很容易出岔子。更别说产品部门天天喊“敏捷迭代”,运营同学动不动就要搞“双11大促活动页”,要求当天上线、当天回滚——你让运维靠手速和记忆去保证稳定性?别闹了。
我试了哪些工具?踩了哪些坑?
既然要改进,就得选工具。作为一个重度依赖 ChatGPT/Claude 的新人(别笑,真的,每天早上第一件事就是把昨天的报错贴给 Claude 问“这是啥意思”),我先列了个候选清单:
| 工具 | 优点 | 缺点 | 适合场景 |
|---|---|---|---|
| Jenkins | 插件多,老牌稳定 | 配置复杂,UI 反人类 | 已有大量 Pipeline 脚本的老项目 |
| GitLab CI | 与代码仓库深度集成 | 依赖 GitLab,资源消耗大 | 公司用 GitLab 且愿意投入 Runner 资源 |
| GitHub Actions | 免费(私有库有限额),YAML 简洁 | 国内网络不稳定,调试困难 | 开源项目或小型内部工具 |
| Argo CD | GitOps 范式,可视化强 | 学习曲线陡,需 K8s 基础 | 已全面容器化、追求声明式部署 |
我们公司用的是 GitLab,所以 GitLab CI 成了最自然的选择。但问题来了:资源。
运维老哥一听我要搞 CI/CD 自动化部署,第一反应是:“你确定要占 Runner 资源?现在测试环境都在排队等构建。” 原来公司为了省钱,只配了两台 4C8G 的虚拟机当 Runner,跑前端构建都卡成 PPT,更别说再加部署任务了。
于是我退而求其次:先在测试环境搞个简化版。目标很明确:
- 提交代码 → 自动构建镜像 → 自动部署到测试环境
- 支持一键回滚(别再让我手动
docker-compose down了) - 记录每次部署的 commit ID 和操作人(方便甩锅……啊不是,方便追溯)
我花了三天时间,参考网上教程 + Claude 辅助,终于搞出了一个 .gitlab-ci.yml:
stages:
- build
- deploy-test
variables:
DOCKER_IMAGE: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA
build-image:
stage: build
script:
- docker build -t $DOCKER_IMAGE .
- docker push $DOCKER_IMAGE
only:
- main
deploy-to-test:
stage: deploy-test
script:
- ssh deployer@test-server "cd /app && ./deploy.sh $DOCKER_IMAGE"
only:
- main
看起来挺美?结果第一次跑就炸了。原因?ssh 免密登录没配好,而且 deploy.sh 脚本里用了绝对路径,但不同服务路径不一样……
后来在运维老哥的“慈祥”指导下,改成了用 Docker-in-Docker (DinD) + Kubernetes Job 的方式(虽然我们还没全上 K8s,但测试环境搭了个 Minikube 凑合用)。最终方案虽然简陋,但至少做到了:
- 每次部署自动生成带 commit hash 的 tag
- 失败时自动通知企业微信群
- 回滚只需在 GitLab UI 点一下“重试上一个成功 job”
部署不只是技术问题,更是协作问题
折腾完工具,我才意识到:部署的本质,其实是“信任”问题。
- 产品希望快速上线,验证想法;
- 运营需要灵活调整活动配置,甚至临时下线某个功能;
- 开发想要稳定的环境,别总被线上 bug 打断节奏;
- 运维则希望一切可控、可审计、别半夜被叫醒。
而部署工具,就是在这四方之间搭一座桥。比如我们现在约定:
- 所有配置外置到 ConfigMap(运营改配置不用动代码)
- 每次发布必须带 changelog(产品能知道上了啥)
- 测试环境部署全自动,生产环境需人工审批(运维保命)
这种协作机制,远比选什么工具重要。工具只是载体,流程和共识才是核心。
给和我一样的新人一点建议
如果你也是刚转行、刚入职、面对一堆“祖传部署脚本”两眼一抹黑的新手,我的血泪经验送给你:
- 别一上来就想搞 K8s + Argo CD 全家桶。先搞清楚现有流程在哪断,哪里最痛。有时候一个简单的
Makefile+rsync就能解决 80% 的问题。 - 善用 AI,但别全信。Claude 给我的第一个 Helm Chart 示例直接把
replicas设成 100,差点把测试集群干崩。 - 和运维搞好关系。请他们喝奶茶,听他们吐槽“当年我们怎么用 Shell 脚本扛住双11”,你会学到很多书上没有的生存技巧。
- 把部署当成产品来做。你的用户是谁?是开发、测试、还是你自己?他们的痛点是什么?响应速度?可靠性?还是操作简单?
最后:为什么我要写这篇文章?
其实起因特别“功利”——我在准备跳槽。最近投了几家公司,面试官一听说我是转行的,立马抛出经典问题:
“你们公司的 CI/CD 流程是怎么设计的?”
以前我只能支支吾吾说“用 Jenkins……大概吧”。现在我可以理直气壮地讲清楚:我们遇到了什么问题,试了哪些方案,权衡了哪些因素,最终落地了什么,效果如何。
部署工具的选择,从来不是技术炫技,而是业务约束下的最优解。它背后牵扯着资源分配、团队协作、风险控制,甚至公司文化。
上周五,我又加班到九点。但这次不是因为部署事故,而是因为产品临时加了个小需求。不过没关系——我改完代码推上去,喝了口咖啡的功夫,测试环境已经自动跑起来了。看着 GitLab 上那个绿色的 ✔️,我突然觉得:嘿,这行代码,好像还真能改变点什么。
(完)
P.S. 如果你也在被部署流程折磨,欢迎留言交流!或者直接甩个错误日志给我,咱俩一起喂给 Claude 看看(笑)。

评论 0