先别急着重写,我维护过最烂的一套系统
2021年我接手一套做仓储的老系统:CentOS 7.9、PHP 7.4.33、MySQL 5.7.42、Nginx 1.20.1、Redis 6.2.7,还有两个 Java 8 和 Java 11 混跑的服务。 刚开始我也觉得这种系统就该重写,后来算了一笔账:重写至少 6 个月、3 个人,旧系统每月维护成本大概 1.5 人天。 我先说个不太讨喜的观点:软件维护不是修 bug,也不是把版本号追到最新,它更像给风险定价。 维护预算我建议占研发时间的 20%-30%,低于 10% 基本就是等故障替你排期。 这套系统后来没重写,先做了监控、备份、回滚和补丁分级,半年后 P1 故障从 7 次降到 2 次,具体数字不算漂亮,但团队终于能睡整觉。
一套能落地的维护清单,先看这 6 块
第一块是资产:服务器、域名、证书、数据库、中间件、CI 变量、定时任务、外部 API key,全都要有 owner。 第二块是监控:磁盘 80% warning、90% critical;内存 >90% 持续 10 分钟告警;JVM Old Gen >75% 持续 15 分钟看 GC。 MySQL 开 slow_query_log,long_query_time=1 秒;连接数超过 max_connections 的 80% 要看;Nginx 5xx 超过 1% 持续 5 分钟必须告警。 第三块是备份:数据库、配置、Nginx conf、K8s YAML、Secrets、证书私钥、对象存储,别只备份数据库。 第四块是补丁:安全补丁、系统包、语言依赖、基础镜像、中间件、K8s API 弃用,都要有清单。 第五块是回滚:上一个镜像 tag、上一个配置版本、数据库变更脚本的回退方案,最好写成一页纸。 第六块是退役:三个月没人访问的服务、过期证书、没人认领的 cron,能下线就下线,维护量很多时候是“只进不出”堆出来的。
补丁管理别随缘,我按 P0-P3 分
P0 是正在被利用的远程漏洞,24 小时内处理;P1 是高风险可远程利用,7 天内;P2 是中危或需要本地条件,30 天内;P3 是低危,90 天或下个维护窗口。
维护窗口我们定在每月第二个周六 02:00-04:00,变更前 48 小时发通知,变更后观察 30 分钟,关键服务观察 2 小时。
真实漏洞别只看新闻标题:Log4j 要至少到 2.17.1;Spring4Shell 对应 Spring Framework 5.3.18/5.2.20、Spring Boot 2.6.6/2.5.12;OpenSSH 的 CVE-2024-6387 修复版本是 9.8p1。
xz-utils 的 CVE-2024-3094 影响 5.6.0 和 5.6.1,很多稳定版没中,但你需要知道自己的版本。
扫描命令可以先用 trivy image --severity HIGH,CRITICAL 你的镜像:tag,系统包用 yum update --security 或 apt list --upgradable。
依赖用 mvn versions:display-dependency-updates、npm outdated、pip list --outdated,别等 CI 红了才看。
灰度顺序我一般用 1 台 -> 10% -> 50% -> 100%,每一步至少留 30 分钟;数据库变更必须向前兼容,禁止 drop column 和代码发布放在同一批。
升级不是追新,是追支持周期
CentOS 7 已经在 2024-06-30 EOL,继续跑不是不行,是你要自己补安全洞。
Ubuntu 20.04 LTS 标准支持到 2025-05,ESM 到 2030-05;Node.js 18 LTS 到 2025-04-30,Node.js 20 LTS 到 2026-04-30。
Python 3.8 在 2024-10-07 EOL,Python 3.11 安全支持到 2027-10;MySQL 5.7 在 2023-10-21 EOL,MySQL 8.0 到 2026-04。
K8s 升级更坑:1.22 移除 extensions/v1beta1 Ingress,1.25 移除 PodSecurityPolicy,1.27 移除了部分 CSI migration,升级前先跑 kubectl api-resources 和 pluto detect-all-in-cluster。
我的观点是:小版本可以跟,大版本别乱跳;先把可观测和可回滚做好,再谈重构。
如果你维护的是金融、医疗、工控系统,升级窗口还要考虑审计和停机窗口,不是技术单方面能定。
对比一下:救火式维护是出事先重启,产品化维护是提前知道哪块会坏、坏了怎么退、退多久能好。
备份和恢复,不演练等于没备份
我们现在的策略是 3-2-1:3 份副本、2 种介质、1 份异地;每日保留 7 天,每周保留 4 周,每月保留 12 个月。
RPO 目标 15 分钟,RTO 目标 2 小时,这是给老板看的,不是给监控看的。
MySQL 逻辑备份用 mysqldump --single-transaction --routines --triggers,物理备份用 Percona XtraBackup,恢复演练每季度一次。
演练不是把备份文件解压就完事,要恢复到临时实例,校验表行数、金额汇总、关键业务 ID 的 checksum。
证书也要管:Let's Encrypt 90 天有效,提前 30 天续;内部证书提前 60 天,别等告警了才找私钥。
配置和密钥同样要备份,K8s Secrets、CI/CD 变量、Nginx 证书路径、crontab,少一样恢复时就卡住。
我见过最惨的一次不是没备份,是备份在同一个磁盘上,磁盘 100% 后 MySQL 直接起不来,df -h 一看 / 分区满了。
维护不是成本中心,是风险定价
救火式维护和产品化维护的差别,不在工具,在有没有固定动作。 救火式:没有资产清单,告警靠人吼,补丁随缘,备份没演练,回滚靠拍脑袋,维护预算为零。 产品化:有 CMDB,有 SLO,每月固定补丁窗口,备份每季度演练,回滚脚本进仓库,维护预算占 20%-30%。 如果你问我先做哪三件事,我会选:能回滚、能恢复、能告警;这三件做完,再谈技术债和重构。 重写不一定错,但很多重写项目死于“旧系统还在跑,新系统没上线,团队两边救火”。 系统可以老,但不能烂;维护的目标不是让它永远新,而是让它在可接受的风险里继续赚钱。 这套清单不高级,甚至有点土,但比每年年底通宵救火强。先做一个月,你会回来谢我,或者骂我漏了哪项,都行。