上周上线一个新服务,CI流水线跑得飞快,打包、镜像构建、推送全都没问题。结果一到K8s集群里,Pod直接 CrashLoopBackOff——查日志发现配置文件路径硬编码在代码里,而部署脚本压根没挂载对应 ConfigMap。
环境不一致:本地能跑,线上就崩
开发在 Mac 上用 Python 3.11 写了个部署脚本,本地测试完美;运维在 CentOS 7 的跳板机上执行,报错:ModuleNotFoundError: No module named 'venv'。原来系统自带的 Python 是 2.7.5,连 pip 都得手动装。更别提 Node.js 版本、Java JDK 小版本、甚至 shell 解释器(/bin/sh vs /bin/bash)的差异,一个 $(()) 算术扩展就能让脚本静默失败。
配置管理:不是所有“变量”都能靠 env 注入
有人把数据库密码写进 Jenkins 参数化构建里,再通过 -e DB_PASS=${DB_PASS} 传给容器。看似安全,但 Jenkins 控制台日志默认记录所有构建参数——密码明文躺在审计日志里。还有人把敏感配置塞进 Git 仓库,哪怕加了 .gitignore,也挡不住某次 git add -f 的手滑。
典型错误示例:
env:
- name: DB_PASSWORD
value: "my-secret-123" # ❌ 明文写死正确做法是用 Secret 挂载,或对接 Vault/KMS,但很多团队卡在“先跑起来再说”的惯性里,拖到出事才补。
依赖漂移:昨天还好的镜像,今天拉不下来
Dockerfile 里写 FROM ubuntu:latest 或 RUN pip install flask,看似省事。结果某天基础镜像更新,Python 升级导致某个 C 扩展编译失败;或者 Flask 发布 3.0,API 大改,应用直接启动报错。没人知道哪次构建悄悄引入了不兼容变更。
权限与上下文错乱:不是所有机器都“认你”
用 Ansible 批量部署时,一个 playbook 在测试环境跑通,推到生产却卡在 sudo systemctl restart nginx。登录一看,目标机上 sudoers 没配 NOPASSWD,而 playbook 默认没开 become_ask。更隐蔽的是 SSH Agent 转发问题:本地私钥能连跳板机,但跳板机没法用它连内网 DB 服务器——Agent 没转发,或者目标机没开 AllowAgentForwarding yes。
回滚不是点一下按钮的事
有团队引以为豪的“一键回滚”,实际只是 git reset + 重新 build + push 新 tag。但如果中间夹杂了数据库迁移(比如加了非空字段又没设默认值),回滚代码根本起不来。真正的回滚得同步考虑:镜像版本、配置快照、数据库 schema 状态、甚至消息队列积压数据的兼容性。
自动化不是把人干的活写成脚本就完事。它得经得起环境切换、权限变更、依赖更新、故障扰动的真实捶打。每次部署失败,别急着改脚本,先问一句:这个步骤,如果换台机器、换个账号、换个时间点,还能稳稳走通吗?