运维自动化实践:告警治理、自动化巡检与故障复盘
干了几年运维,最怕听到两句话:一句是“线上好像有点问题,你看下”,另一句是“这个之前不是你负责的吗”。前者意味着你的周末提前结束,后者意味着你的锅已经提前预定。所以当有人在群里甩出“干运维是条不归路”这句话时,底下一片“+1”,我也默默点了个赞——但点完我就去把手上的值班表、告警规则和一键巡检脚本重新捋了一遍。跑路这两个字,我理解得比较实在:不是拍拍屁股换个工位,而是把自己从“人肉救火”的那条路上挪出来,挪到一条能积累、能复用、能按时下班的路上。这篇内容就是把这几年踩过的坑、改过的流程、写过的脚本摊开讲,适合刚入行一两年、天天被电话叫醒的朋友,也适合干了五六年、开始琢磨要不要转岗的老哥。不吹方法论,只讲我自己验证过能落地的那部分。
1. 先把“不归路”这三个字拆开看
1.1 运维为什么会干成一支“救火队”
很多人对运维的印象停留在“装机器、重启服务、半夜接电话”。这个印象不全错,但它描述的只是运维工种里最原始的那一层:人肉执行层。处在这一层,你的产出和你的在线时长强绑定,你在工位上坐十二个小时,价值就是十二个小时;你请假三天,系统就敢给你表演三天。这种模式最要命的地方在于,它不会自己变好——故障越多,你越熟练;你越熟练,故障处理越依赖你;越依赖你,你越走不开。这就是“不归路”这个说法的真实来源,它不是行业诅咒,而是角色定位卡在了错误的位置上。
我自己最早也是这样。那会儿一台机器起不来,我能抱着键盘盯到凌晨三点,第二天还沾沾自喜地跟人说“我搞定了”。现在回头看,那次故障的价值不在于“我搞定了”,而在于“为什么只有我能搞定”。如果这个答案一直是“因为我记得那台机器的脾气”,那你就是在给自己挖坑,而且挖得挺开心。真正的分水岭出现在你开始问第二个问题的时候:这件事能不能写成脚本、写进文档、写进流程,让下一个人不用问我也能搞定。
所以我不太认同“运维是条不归路”这种绝对化的说法,但我完全理解为什么这么多人这么讲。因为这个岗位的默认路径确实通向救火队,而跳出默认路径需要主动做功,没人会替你安排。你不主动做,五年后你还是那个“最熟悉这台机器的人”,只不过头衔从初级变成了资深,电话还是那些电话。
1.2 四种典型的“走岔”方式
我把身边见过的情况归了归类,大致是四种走向。这四种不是按能力高低排的,而是按“时间花在哪儿”排的,你可以对照看看自己在哪一格里。
| 类型 | 日常状态 | 短期表现 | 三年后的样子 |
|---|---|---|---|
| 人肉执行型 | 手动登录、手动改配置、手动重启 | 反应快,救火及时 | 越来越忙,事情越来越多,人越来越难请假 |
| 工具堆砌型 | 装了一堆平台,用起来一半 | 汇报材料好看 | 平台没人维护,告警照样炸,团队信任度下降 |
| 深度专精型 | 死磕一个方向,比如数据库或网络 | 某类问题只有你能解 | 稀缺性高,但在小团队里容易被“供起来”而缺少横向空间 |
| 体系构建型 | 把重复动作沉淀成流程和工具 | 前期见效慢,甚至被说“不干正事” | 团队不再依赖某个人,自己有了可迁移的方法论 |
我早期掉进的是第一格,后来短暂掉进过第二格——有段时间特别迷恋“上平台”,觉得只要工具到位,一切迎刃而解。结果装了三个监控、两个发布系统,最后一个都没用透,告警该响还是响,发布该回滚还是回滚。这段经历给我的教训特别朴素:工具解决的是“有没有”,流程解决的是“顺不顺”,人解决的是“愿不愿”。三样缺一样,平台就是个摆设。
1.3 我给运维价值划的三条线
后来我自己琢磨出一个比较土的分法,把运维的成长分成三条线,你可以拿来当自我检查表用。
- 第一条线:能不能让系统跑起来。这是基本功,装机、部署、配网络、看日志、定位常见的服务异常。这条线不过关,谈什么转型都是空的。
- 第二条线:能不能让系统自己跑起来。这里的关键词是自动化、标准化、可重复。同一件事做第二遍就该写脚本,做第三遍就该进流程,做第四遍还在手动敲,那就是在浪费生命。
- 第三条线:能不能让系统跑得划算。到这一层就开始算账了:资源利用率、故障成本、变更成功率、平均恢复时间。你开始用数字说话,而不是用“我感觉最近挺稳的”说话。
大部分人卡在第一条线和第二条线之间,不是因为不会写脚本,而是因为没时间写脚本——时间全花在第一条线上了。这看起来是个死循环,其实有解,解法在下一节。
2. 值班和告警:先把自己从“随时待机”里捞出来
2.1 告警治理的四条硬规矩
如果只能改一件事,我建议先改告警。因为告警是你和系统之间唯一的高频通道,这个通道一旦失真,你对系统的判断就全废了。我给自己团队定过四条规矩,执行下来效果比任何工具升级都明显。
第一条:能被忽略的告警,就不该存在。判断标准很简单,如果一条告警连续出现十次,有八次没人处理,那它就不是告警,是噪音。噪音的危害不只是烦人,它会训练所有人对告警脱敏,等到真出事的那一条混在里面,没人会当回事。
第二条:告警必须指向动作,而不是指向现象。“CPU 使用率超过 80%”是现象,“订单服务 P99 延迟连续五分钟超过 500 毫秒”才是能导向动作的描述。前者你看到之后第一反应是“再看看”,后者你会去想是数据库慢查询还是下游超时。
第三条:分级必须有,而且级别要和通知方式绑定。我见过太多团队分级只写在文档里,实际通知全发一个群。级别不绑定通道,分级就是自娱自乐。
第四条:告警要有人认领。每条规则背后得有归属模块,不然出了事就是“这个我不清楚是谁配的”。
按这四条过一遍,通常能砍掉三到五成的规则。砍的时候心里会发虚,觉得万一漏了呢。我的经验是:漏掉的概率远小于噪音造成的注意力损耗,而且漏掉的第一次会很快补回来,噪音可是天天在消耗你。
2.2 值班表怎么排才不散架
值班这件事,排得好是保障,排不好是消耗。我试过三种排法,最后稳定下来的是一周一轮、主备双岗、白天重叠。
- 一周一轮:太短会频繁切换上下文,太长会让人精神紧绷到极限。一周是比较舒服的颗粒度。
- 主备双岗:主岗第一响应,备岗在主岗十五分钟未响应时接手。这条很关键,单岗制最大的问题是“不敢睡”,双岗制给了人一个可以闭眼的安全垫。
- 白天重叠:交接放在工作日白天,两个人对着屏幕过一遍未闭环的问题,比在群里发一段文字交接有效十倍。
交接内容我固定成四行,写在值班文档最上面:昨天动了什么、有什么没闭环、有哪些临时绕过的方案、今天重点关注什么。第四行最容易被跳过,但它恰恰是判断“今天能不能安心”的关键。临时绕过方案也特别值得记,因为绝大多数“莫名其妙又好了”的故障,都是上一次绕过留下的雷。
注意:值班制度最怕的是“名义上有备岗,实际上备岗也在忙自己的事”。备岗必须明确写进排期,不能靠人情。我吃过这个亏,主岗打了六个电话没人接,最后是已经下班的同事远程救的场。
2.3 告警降噪的一次实操记录
说个具体的。之前有个核心接口,一天能报两百多条超时告警,团队已经麻木了。我花了一个下午做了一次收敛,流程是这样的。
第一步,先把原始数据捞出来看分布。不看不知道,两百多条里有接近七成集中在凌晨两点到四点,而且是同一个下游依赖的批量任务时段。也就是说,绝大部分告警是预期内的资源竞争,不是故障。
第二步,把“瞬时抖动”和“持续劣化”分开。瞬时抖动用单点阈值判断必然误报,需要引入持续时间窗口。我把规则从“单次超过阈值”改成“连续三个采集周期都超过阈值”,误报直接掉了一半。
第三步,按业务影响重新分级。影响下单链路的,定义为高优,直接电话;影响报表、日志检索这类旁路功能的,定义为低优,进日报。同样一条延迟告警,落在不同链路上,紧急程度差着数量级。
第四步,把规则写成可版本管理的文件。手点出来的规则最大的问题是没人知道它为什么长这样,改也不敢改。写成文件之后,每次调整都有记录,谁改的、为什么改,一眼能看出来。
下面是我当时用的一个简化版规则骨架,思路是把“阈值 + 持续时间 + 分级 + 通知通道”这四件事绑在一起:
groups: - name: order-service-latency rules: - alert: OrderApiP99LatencyHigh expr: histogram_quantile(0.99, sum(rate(http_request_duration_seconds_bucket{service="order"}[5m])) by (le)) > 0.5 for: 3m labels: severity: critical owner: order-team annotations: summary: "订单接口 P99 延迟超过 500ms 且持续 3 分钟" runbook: "https://internal.example/runbook/order-latency" action: "先看下游库存服务 RT,再查慢查询,最后看连接池占用"这段配置里有三个点值得单独说。for: 3m就是前面提到的持续时间窗口,它的作用是过滤抖动;runbook和action两个注解是给半夜被叫醒的人看的,人的记忆在凌晨是不可靠的,写在规则里比记在脑子里靠谱;owner标签是为了后面做归属统计,谁家的告警多,谁家的稳定性就该被拿出来聊。
阈值怎么定,很多人凭感觉。我的做法是拿最近三十天的真实数据算分位数,取 P99 作为基线,再上浮百分之二十到三十作为告警线。比如这个接口三十天的 P99 是 380 毫秒,那 500 毫秒就是个合理的位置——它明显高于日常水平,又没高到要等系统彻底卡死才报警。这个算法不精密,但它有依据,比拍脑袋强。
3. 把重复动作变成资产:自动化和平台化
3.1 自动化该从哪三件事下手
一提自动化,很多人脑子里想的是“搞个平台”。这个念头很危险,因为平台是个大工程,做完之前你什么收益都没有。我的建议是先做三件小事,每件都能在一周内看到效果。
第一件,环境巡检。磁盘、内存、进程数、证书有效期、备份是否成功,这些东西每天看一遍和每周看一遍,出事概率完全不同。巡检脚本的好处是它不会忘,而人会。
第二件,发布回滚。这是收益最高的一块。发布流程如果还靠人手敲命令,回滚就永远慢半拍,而回滚速度直接决定了故障时长。把发布和回滚做成一条命令,是投入产出比最高的自动化。
第三件,日志收集与检索。不是为了好看,是为了在故障现场能三秒内捞到关键日志。很多人排查慢,不是不会分析,是找日志花了二十分钟。
这三件事做完,你会发现一个变化:你开始有余裕了。余裕是所有的起点,没有余裕,什么体系、什么转型都是空谈。
3.2 一个批量巡检脚本的完整实现
我把巡检脚本的骨架贴一下,它是纯 Shell 加一点点逻辑,没有依赖任何平台,扔到任何一台 Linux 机器上都能跑。之所以不用更高级的方案,是因为这个脚本要在几百台机器上分发,依赖越少越好维护。
#!/bin/bash # 用途:主机基础巡检,输出结构化结果,供后续汇总 # 设计原则:单机可独立运行,失败不中断,输出机器可读 HOST=$(hostname -s) REPORT="/var/tmp/inspect_${HOST}_$(date +%Y%m%d).log" WARN=0 log() { echo "[$(date '+%F %T')] $*" >> "$REPORT"; } # 1. 磁盘:根分区使用率超过 80% 告警 ROOT_USED=$(df -P / | awk 'NR==2 {gsub("%","",$5); print $5}') log "disk_root_used=${ROOT_USED}%" if [ "$ROOT_USED" -ge 80 ]; then log "WARN disk_root_used high" WARN=$((WARN+1)) fi # 2. 内存:可用内存占比低于 10% 告警 MEM_AVAIL_PCT=$(free | awk '/Mem:/ {printf "%d", $7/$2*100}') log "mem_avail_pct=${MEM_AVAIL_PCT}%" if [ "$MEM_AVAIL_PCT" -lt 10 ]; then log "WARN mem_avail_pct low" WARN=$((WARN+1)) fi # 3. 关键进程存活检查,进程名从清单文件读取 if [ -f /etc/inspect/process.list ]; then while read -r p; do [ -z "$p" ] && continue if pgrep -x "$p" > /dev/null; then log "proc_${p}=alive" else log "proc_${p}=down" log "WARN proc_${p} not running" WARN=$((WARN+1)) fi done < /etc/inspect/process.list fi # 4. 证书有效期:剩余不足 15 天告警 if [ -d /etc/ssl/private ]; then find /etc/ssl/private -name "*.crt" 2>/dev/null | while read -r c; do END=$(openssl x509 -enddate -noout -in "$c" 2>/dev/null | cut -d= -f2) [ -z "$END" ] && continue DAYS=$(( ( $(date -d "$END" +%s) - $(date +%s) ) / 86400 )) if [ "$DAYS" -lt 15 ]; then log "WARN cert_expiring file=$c days=$DAYS" fi done fi log "warn_total=${WARN}" exit 0这个脚本有几个我反复权衡过的设计点。exit 0是故意的,巡检脚本本身不能成为故障源,某台机器上某个检查报错不应该让整批任务失败;输出格式选成key=value,是为了后面用grep或awk直接汇总,不用写解析器;告警项统一带WARN前缀,汇总时一行grep -c WARN就能统计异常机器数。
分发这一步,用最朴素的批量执行就行,比如:
# 假设主机清单在 inventory 文件里,每行一个主机名 while read -r h; do scp -q inspect.sh "ops@${h}:/var/tmp/" && \ ssh -o ConnectTimeout=5 "ops@${h}" "bash /var/tmp/inspect.sh" & done < inventory wait # 汇总:捞出所有含告警的行,按主机分组 grep -h "WARN" /var/tmp/inspect_*.log | sort | uniq -c | sort -rn并发执行那个&加wait的写法很土,但很好用。几百台机器几分钟跑完,比一台一台串行快得多。ConnectTimeout=5是必须的,不加的话一台失联机器能把整个批次拖到天亮。
3.3 配置管理的坑:别让自动化变成批量事故
自动化最大的风险不是脚本写不对,是脚本写得太对——它会在几百台机器上同时、准确地执行你的错误。我第一次用批量工具改配置,漏了一个引号,十分钟内让二十多台机器的服务全挂。那次之后我给自己定了三条铁律。
铁律一:任何批量操作先在单台上跑通。单台跑通的标准不是“没报错”,是“业务功能验证通过”。配置类改动尤其如此,语法正确和业务可用是两回事。
铁律二:批量范围默认从一台开始,逐级放大。一台、五台、百分之十、全量,每一级都要看指标。这个节奏会让人觉得慢,但它把事故半径控制住了。
铁律三:所有变更必须有回滚路径,而且回滚路径要验证过。没验证过的回滚方案约等于没有方案。我现在的习惯是,做变更之前先演练一遍回滚,哪怕它看起来很明显。
还有一个容易被忽略的点:配置项的最终真相到底在哪。如果一部分配置在仓库里,一部分在机器上手工改过,那你所有的自动化都是建立在流沙上的。我见过最离谱的情况是同一台机器上有三份不同的配置,服务到底读哪一份没人说得清。这种时候先别急着建平台,先把配置收敛到唯一来源,这一步不做,后面全是白干。
4. 故障现场:把“背锅”变成“定位到系统”
4.1 故障分级和响应动作
故障处理最怕两件事:一上来就全员扑上去,结果十个人互相问“现在什么情况”;或者所有人都觉得“应该没事”,等发现的时候已经过去四十分钟。解法是提前定好分级和对应动作,事发时只判断级别,不讨论流程。
| 级别 | 判定标准 | 响应动作 | 目标恢复时间 |
|---|---|---|---|
| P0 | 核心链路完全不可用,或数据出现错误 | 立即拉应急群,主岗止损,同步通知业务方 | 30 分钟内恢复或降级 |
| P1 | 核心链路部分受损,或有明显性能劣化 | 主岗处理,备岗待命,十五分钟一同步 | 1 小时内恢复 |
| P2 | 非核心功能异常,有可用替代路径 | 工作时间处理,进当日工单 | 24 小时内 |
| P3 | 无业务影响,仅指标异常 | 进周会讨论,不单独响应 | 一周内 |
这张表的作用不是让你照本宣科,是让凌晨三点被叫醒的人能在三十秒内做出判断,而不是花二十分钟讨论这算不算大事。判断标准里我最看重“数据出现错误”这一条,因为它比服务不可用更隐蔽也更严重,很多时候系统看起来好好的,只是悄悄算错了数,这种问题必须单列。
处理过程中有个小技巧我用了很多年:先止损,再定位。大部分人的本能是先搞清楚原因再动手,这在故障现场是错的。原因是,定位可能需要一小时,而止损可能只需要一分钟。先回滚、先切流、先降级,把业务恢复过来,然后你有大把时间从容分析。我见过太多因为急着找根因,硬扛了四十分钟才回滚的案例,最后根因也确实找到了,但业务损失已经造成。
4.2 复盘模板:对着系统,别对着人
复盘这件事,做得好是团队最值钱的资产,做得不好就是公开处刑,做完之后所有人都学会了下一次怎么把话说圆。我坚持的原则是:复盘的对象是系统和流程,不是某个人。
模板我固定成五块,写下来不超过一页:
- 时间线:从第一个异常信号到完全恢复,每五分钟记一笔。这条最有价值,因为人的记忆会自我美化,时间线不会。
- 影响面:影响了哪些业务、多少请求、多长时间。要具体到数字,不能写“部分用户”。
- 直接原因和根本原因:直接原因是“什么坏了”,根本原因是“为什么它能坏”。比如直接原因是连接池被打满,根本原因是某个查询没有超时控制。
- 临时措施和长期措施:临时措施要写清楚什么时候撤,长期措施要有负责人和时间点。没有负责人的措施等于没有措施。
- 检测和响应环节的问题:这一点经常被跳过,但它往往比技术原因更值得改。比如“为什么监控没报”“为什么报了没人看”“为什么看了判断错了”。
第四条里“临时措施什么时候撤”是我加的,因为我吃过大亏。有一次为了止损临时调大了一个超时时间,事情过去了没人管,三个月后这个临时值成了新的隐患,还顺带掩盖了一个慢查询问题。
提示:复盘会上有个简单的话术技巧,把“你为什么没发现”换成“我们的监控为什么没覆盖到”。同样的意思,一个指向人,一个指向系统,聊出来的东西完全不一样。
4.3 容量和预案:给自己留后路
运维干久了会有一个体会:绝大部分严重故障,本质都是容量问题,只不过表现形态各不相同。连接池打满是容量,磁盘写满是容量,线程队列堆积也是容量。所以容量这件事,值得当成日常功课,而不是等到告警了再处理。
我的做法是给每个核心服务记三个数:日常水位、峰值水位、扩容阈值。日常水位是平峰期的资源占用,峰值水位是大促或者批量任务时的最高点,扩容阈值定在峰值水位的百分之七十左右。三个数一摆,什么时候该扩,扩多少,心里就有数了。
扩容不是万能的,有些地方加了机器反而不行,比如锁竞争、单点写库、串行依赖。这类地方只能靠预案。预案我一般会准备三个档次:
- 降级预案:关掉非核心功能,保住主链路。比如临时关掉推荐、关掉历史查询。
- 限流预案:给入口设一个最大并发,宁可拒绝一部分请求,也不让整个系统雪崩。
- 切换预案:切到备用链路或者只读模式。
这三档要提前写好开关,而且开关必须能在一分钟内生效。写在文档里但需要改代码才能生效的预案,等于没有预案。
5. 技能栈和转型:运维人的几条出口
5.1 一张能自查的技能地图
我把运维相关的技能分成四层,从下往上。你可以拿这张表勾一下,看看自己缺的是哪一块。缺底层就去补底层,缺上层就去补上层,别一上来就追新概念。
| 层级 | 核心能力 | 常见抓手 | 判断标准 |
|---|---|---|---|
| 系统层 | 操作系统、网络、存储、进程模型 | 排查 CPU、内存、IO、连接异常 | 给你一台陌生的机器,能独立定位性能瓶颈 |
| 服务层 | 中间件、数据库、容器运行时 | 部署、调参、备份恢复 | 能说清一个请求从入口到落库经过了哪些环节 |
| 工程层 | 脚本、配置管理、持续集成、可观测性 | 自动化发布、监控体系、日志体系 | 能不靠人肉完成一次完整发布和回滚 |
| 架构层 | 容量规划、高可用设计、成本控制 | 稳定性指标、故障演练、资源评估 | 能用数字说明系统当前的风险点在哪 |
这张表的用法是“往下扎”和“往右走”结合。系统层是地基,它决定了你排查问题的上限;架构层是天花板,它决定了你在团队里的话语权。中间两层是最容易卡住的,因为日常杂事全堆在这里。
5.2 四条转型路径的真实差异
这几年身边同事走出去了不少,路子大概有四种。我把观察到的实际感受写下来,不做优劣判断,因为适配度比“哪个更好”重要得多。
| 方向 | 做的事情 | 适合什么人 | 门槛与代价 |
|---|---|---|---|
| 稳定性工程方向 | 定义指标、做容量、做演练、推动治理 | 喜欢和数据、流程打交道,能推动别人 | 需要较强的沟通和推动力,短期很难看到成果 |
| 平台工程方向 | 把运维能力做成产品,给别人用 | 喜欢写代码,愿意打磨工具 | 需要补工程能力,编程底子差会很吃力 |
| 专项深挖方向 | 数据库、网络、性能调优等垂直领域 | 专注度高,能忍受长时间啃一个方向 | 学习曲线陡,且在小团队容易被当工具人 |
| 技术管理方向 | 带人、定优先级、对外沟通 | 能扛压,擅长拆解和分配 | 会离技术越来越远,心理落差需要适应 |
我自己的选择偏平台工程和稳定性工程之间。选这条路的理由很实际:我写代码不算特别强,但比大部分人愿意写;我喜欢把重复的事变成工具,因为那能让我少加几次班。这个理由一点都不高大上,但它真实,而且它让我愿意在这个方向上持续投入。
关于转型,我特别想说的是:别把转型理解成“换个岗位从零开始”。运维积累的东西里,排查思路、系统视角、对故障的敏感度,这三样在任何技术岗位都值钱。真正要补的是表达能力——你能不能把一次故障讲清楚,能不能把一套方案写明白,能不能用业务听得懂的话说明白为什么要投这笔资源。这个能力比多学一门语言重要得多。
5.3 时间从哪来:给学习排个可行的节奏
“没时间学习”是所有运维人的共同困境,我也不例外。后来我换了个思路,不追求“每天学两小时”,而是把这几个动作嵌进工作本身。
动作一:每次排查完,写一段记录。不求完整,写清楚现象、判断过程、最后怎么解决的就行。三个月下来你就有了一本自己的故障手册,而且是带着思考过程的那种。
动作二:每次重复操作,抽二十分钟写个脚本。哪怕只写了一半,下次再遇到就能接着写。我现在手上那些工具,一半是这么攒出来的。
动作三:每周抽一小时看一个已有系统。不看教程,就看自己手里的系统,挑一个模块,问自己“它为什么这么设计”。这个动作的效果比刷视频课好得多,因为它是贴着真实场景的。
动作四:给自己设一个可交付的小目标。比如“这个季度把发布流程自动化跑通”,比“这个季度学好容器”具体得多,也容易坚持。
心得:别把学习计划和加班混在一起。加班的时候学不进去,学的时候想着工单没关,两头都干不好。我现在是固定周三晚上不碰工单,就用来写点东西或者看系统,这个边界感很关键。
6. 常见问题速查和踩坑实录
6.1 高频问题排查表
把常见问题和最容易走偏的判断列一下。这张表的用法是:出事的时候先扫一眼,别急着往下钻。
| 现象 | 容易误判的方向 | 优先检查的位置 |
|---|---|---|
| 服务响应变慢但 CPU 不高 | 以为是网络问题 | 连接池占用、下游 RT、线程阻塞、GC 停顿 |
| 间歇性超时,复现困难 | 以为是偶发 | 采集窗口是否太短、是否有定时任务、是否有连接重建 |
| 磁盘突然写满 | 以为是大文件 | 先看被删除但仍被占用的文件、再看日志轮转是否失效 |
| 机器内存持续上涨 | 以为是业务量增长 | 缓存是否无上限、连接是否未释放、文件句柄是否泄漏 |
| 发布后问题消失 | 以为修好了 | 可能是重启掩盖了问题,重点看是否有状态未清理 |
| 告警忽多忽少 | 以为是系统不稳 | 先看告警规则本身是否有抖动,再看采集是否丢点 |
表里第五行是我特别想强调的。“重启一下就好了”这句话在运维圈流传甚广,它的危险之处在于它总能生效,于是很多人把它当成了解决方案,而不是临时手段。重启确实能让症状消失,但状态没清干净,问题还会回来,而且下次回来往往更严重。
6.2 几个我实打实踩过的坑
坑一:把监控当成万能答案。有段时间我以为监控覆盖度上去了,问题自然就少了。实际是,监控只能告诉你“哪里不对”,不能告诉你“为什么不对”。指标体系建得再全,没有配套的排查路径,现场还是一片混乱。后来我在每条关键告警后面都补了一行“下一步动作”,情况才好转。
坑二:文档写完就不再看。我曾经很认真地写过一套运维手册,写了六十多页,结果半年后自己都不信里面的内容了,因为环境变了三轮。现在的做法是把文档拆成小块,每块标注最后验证时间,超过三个月没验证的自动降级为“待确认”。文档的价值不在于长,在于准。
坑三:只做加法不做减法。新工具、新流程、新报表,一直在加。加到后来,团队每天要填三个表、看两个平台,真正干活的时间被挤没了。后来我们定了一条规矩:任何新流程上线,必须说明它能替代掉哪个旧流程。不能替代的,就先不上。
坑四:把“我扛得住”当成能力。这是最隐蔽的坑。能连轴转、能半夜爬起来、能一个人扛三个人的活,这些确实说明你能力强,但它们不该成为常态,更不该成为评价标准。一个健康的运维体系,标志是“少了谁都能转”,而不是“少了谁都不行”。我花了挺长时间才想明白这件事。
坑五:不敢说不。需求方说“这个改一下很快吧”,你说“行”;业务方说“今晚发个版”,你说“没问题”。边界一旦失守,后面全是默认。我现在会明确给出时间窗口和影响范围,比如“这个改动今晚可以做,但需要两小时窗口,期间只读”。说清楚比答应得快重要。
6.3 几个能立刻用上的小技巧
最后放几个不需要任何预算、当天就能试的小动作。
- 给所有批量脚本加一个
--dry-run开关,默认只打印不执行。这个习惯救过我至少三次。 - 所有变更记录里加一列“回滚方式”,哪怕写的是“重新部署上一版本”,也要写。
- 值班文档第一行永远写“当前系统状态”,用三个词:正常、降级、异常。交接的人第一眼就看到。
- 给每个核心服务准备一条“一分钟自检命令”,出问题时先跑它,比翻文档快。
- 复盘记录单独建个目录,按季度归档。年底翻一遍,你会发现重复问题集中在两三个地方,那才是真正该投入的地方。
跑路这件事,我现在理解得比较清楚了。真正该跑的不是这个行业,是那种“靠个人硬扛”的工作方式。我把值班表定清楚、告警砍干净、脚本写好、复盘做实,日子就慢慢回来了。这个过程不快,我花了差不多两年才看到明显变化,但它是可积累的——今天写的脚本明天还在用,今天定的流程下个月还在跑。这大概就是我对“不归路”这三个字最后的态度:路是自己走出来的,走成什么样,多半取决于你愿不愿意在忙的时候还挤出二十分钟,把刚才那件事变成以后不用再做的事。