简介:《IT自动化运维平台建设解决方案》PPT方案面向IT运维工程师、运维主管及正在推进运维体系升级的技术管理者,围绕人工运维向自动化、智能化演进中的平台规划与落地问题展开。内容从自动化运维概念与AIOps趋势切入,梳理当前IT运维所处阶段,并结合现状痛点给出总体规划方案:以数据整合为基础,经任务调度、智能监控、自动运维,最终落到风险诊断,配有总体架构、应用蓝图、本期功能架构与告警处理流程等模块,便于读者理解平台分层与建设路径。包内共1个PPT文件,压缩包约4.35MB,页面以架构图和要点说明为主,适合用于内部方案汇报、建设思路梳理及平台功能设计参考。已有1024人学习,可作为自动化运维平台立项与需求沟通的框架材料。
1. 一套监控跑得再稳,也扛不住凌晨两点的那通电话
一台核心交换机端口抖动,Zabbix 报警推到业务网管,值班工程师被电话叫醒,翻文档找脚本、登跳板机、敲命令,四十分钟后恢复。这套流程在 1.5 万台主机和数通设备的规模下每天要重复很多次,人越忙越容易出错,出错之后又没人说得清当时到底敲了什么。这份 IT 自动化运维平台建设解决方案要填的就是这段距离:把周期性、重复性、规律性的工作从人手里挪到平台上,让告警到处置之间不再依赖“谁值班、谁还记得那条脚本”。它适合两类读者,一类是正在把手工运维往平台化推的运维负责人,需要一份能说服主管领导的分期方案;另一类是要交一份完整 IT 运维平台设计方案的毕设或课设同学,需要一套能落地的模块划分和验收口径。下面按痛点怎么拆、架构怎么分层、模块怎么实现、上线怎么验收的顺序展开。
2. 痛点拆解:一条告警闭环里藏着四类必须解决的问题
几乎每个运维团队都能说出自己“哪里疼”,但真到写方案时,疼点往往被写成“效率低”“响应慢”这种没法验收的形容词。方案要立得住,第一步是把现有链路摊开,看清楚每个人在哪一步介入、介入时依赖什么、出了问题之后能不能查。这一章做的事情就是把模糊的抱怨翻译成可以量化、可以对应到具体模块的需求条目。
2.1 现有告警链路的五个环节与人为依赖
现有的闭环是这么走的:Zabbix 采集到指标异常后生成告警,输出至业务网管系统;业务网管通过电话或消息通道通知到值班运维;运维工程师登录目标机分析定位,判断是自己能处理还是要协调研发;处理完成后告警恢复,链路结束。五个环节里有四个必须有人在场,而且每个环节的输入输出都没有被结构化记录下来。
按 1.5 万台主机和数通设备的体量估算,哪怕每台设备日均只产生零点一条需要人过目的有效告警,一天也有上千条告警要走一遍这条路。真正的问题不在于告警多,而在于每一条告警的处理成本不一致——同一个“磁盘使用率超阈值”,A 工程师记得清日志脚本在哪,B 工程师要先去翻共享目录,C 工程师干脆手工 rm。处理方式不统一,后果就是同类故障反复发生,每次都在重新发明一遍解决方法。
更麻烦的是通知环节的不可控。电话打不通、消息沉在群里、值班人正在处理另一件事,都会让响应时间从分钟级滑到小时级。非工作时间的告警尤其被动,方案里写得很直白:被动式的告警处理方式,非工作时间无法保证第一时间被处理。这不是人的态度问题,是链路设计问题。
2.2 三类关键缺陷:过程无回溯、作业无自动化、经验无沉淀
第一类是过程缺乏回溯。现阶段的处理动作发生在跳板机和本地终端上,命令历史散落在各自的 bash_history 里,处理结果没有痕迹。事后复盘只能靠回忆,一旦涉及“这条配置是谁改的、为什么改”,就变成了没人能证明的糊涂账。运维操作过程缺乏管控,处理结果无痕迹,这句话在方案里出现过好几次,它不是套话,是审计和交接时的真实困境。
第二类是日常运维缺乏自动化。周期性任务比如巡检、日志清理、证书到期检查、配置基线核查,脚本和配置由各运维工程师自己控制,执行结果无法监控,也没有系统化的统一管理。有的人用 crontab,有的人写在自己电脑上定时跑,还有的人靠日历提醒手工做。平台看不到这些任务的执行状态,等于这批工作在管理上是不可见的。方案里提到的周期性任务执行结果无法监控,说的就是这个。
第三类是经验无沉淀。现阶段由运维工程师对告警信息进行定位分析,根据分析结果处理,根因判断留在个人脑子里。人一流动,同类告警就处理不了,无法平滑交接。这条在人员流动频繁的团队里杀伤力最大,一个熟手离职带走的不只是人力,还有一整套没写下来的处置逻辑。
还有一条容易被忽略:缺乏对潜在风险的预警。故障没发生但场景已经恶化的情况,比如连接数缓慢爬升、队列积压持续增长,靠阈值告警是抓不住的,只能靠人盯趋势图。这类问题在人工运维阶段基本无解。
2.3 把痛点翻译成可验收的能力清单
需求写得再动人,落到验收还是要看“上线之后哪几个数字变了”。我在做这类方案时习惯先做一张对照表,左边是痛点,中间是平台要提供的能力,右边是一期的验收口径。这张表后面会直接变成答辩时的功能演示顺序。
| 痛点 | 平台能力 | 一期验收口径 |
|---|---|---|
| 周期任务散落各处、执行结果不可见 | 任务调度中心统一纳管定时任务 | 存量 crontab 100% 迁移,任务执行记录可查 |
| 脚本分散、版本混乱、有篡改风险 | 脚本管理服务集中存储与版本管理 | 脚本变更全部留痕,高危脚本需审批 |
| 告警处理靠人、响应时间不可控 | 告警管理与规则引擎联动自动处置 | 梳理出的高频场景自动处置率 ≥ 60% |
| 处理过程无痕迹、无法交接 | 执行记录与工单闭环 | 每条自动处置都有 stdout、耗时和操作人 |
| 非工作时间响应慢 | 触发性任务 7×24 自动执行 | 夜间告警平均响应时间从小时级降到分钟级 |
| 风险只能等故障暴露 | 趋势识别与指标优化(二期) | 一期先做数据采集与指标入库,为二期铺路 |
这张表的第三列很关键。很多方案在写“提升运维效率”时戛然而止,评委或者主管一定要问“提升多少、怎么算”。把口径提前定死,等同于给自己留了一条退路:验收时按表逐条对,对不上的地方坦白说属于二期范围,比含糊其辞强得多。
3. 总体架构:三期演进路线与五个能力中心的职责边界
架构图最容易画成“什么都往上堆”,画完自己都说不清模块之间的调用关系。这套方案的思路是先按时间轴切三期,每一期交付的能力边界清晰;再按职责切中心,每个中心只干一类事。时间轴解决“先做什么”,职责划分解决“谁来做”,两条线交叉之后,模块的归属就没有争议了。
3.1 三期演进:自动化、智能化、自主化各自交付什么
一期是自动化运维,核心特征是“基于告警及任务指令”执行。故障告警来了,按预置规则跑对应脚本;到点了,按调度跑周期性任务。这一期不涉及任何模型,判断逻辑是人写死的规则,好处是可控、可解释、出错能查到具体哪条规则写错了。方案里把这期定位成“根据故障告警及所配置的周期性任务等明确的指令自动执行运维工作”,重点在“明确的指令”五个字。
二期是智能化运维,特征是“基于趋势型等规则,根据指标数据自动发现故障并自动执行修复”。区别在于触发源从“已经发生的告警”变成“正在恶化的趋势”。比如磁盘使用率还没到 90% 的告警线,但按最近 7 天的增长速度三天后就会写满,二期要能提前识别并触发扩容或清理。这一期开始引入规则模型和趋势识别,但仍然以规则为主、模型为辅,可解释性还是硬要求。
远期是自主化运维,特征是“基于历史故障与日志等数据,通过自学习模型发现潜在问题与风险并自行处理”。这一期才真正涉及机器学习模型,事件识别、机器模型诊断这些能力放在这里。方案里对远期的描述比较克制,只说“基于历史重大事件的自动运维”“基于历史数据分析的主动运维”,没有承诺具体指标,这是合理的——三期跨度太长,写死了反而做不到。
三期之间不是替换关系,是叠加关系。一期的任务调度和脚本管理在二期三期还在用,只是触发源变多了。这一点在设计表结构时必须提前想清楚,任务表里要留trigger_type字段区分周期、告警、趋势、模型四种来源,否则二期上线时要改表改代码,成本翻倍。
3.2 五个能力中心的模块划分与调用关系
平台的应用蓝图按职责切成五个中心,外加基础能力和对接系统两层。这套划分的好处是每个中心都能单独排期、单独验收,不会出现“全都要做完才能上线”的情况。
监控管理中心负责“看见”,包含监控对象管理、监控指标管理、监控配置管理、告警任务管理和告警列表。它的数据来源是 Zabbix 和业务网管,自身不产生监控数据,只做归集和展示。这一层要避免的误区是重复造轮子,Zabbix 已经在采集的数据不要再采一遍,平台只做二次加工。
运维作业中心负责“能做什么”,包含资源管理、参数管理、脚本管理、工单管理。脚本是这里的核心资产,shell、bat、Perl、Python、PowerShell 五类都要支持,因为存量脚本不可能一次重写。参数管理管的是系统接口地址、邮箱配置、账号这类全局变量,脚本里不能硬编码。
任务调度中心负责“什么时候做”,包含任务创建、任务调度、任务执行监控、任务执行报告、任务统计。它是整个平台的心脏,周期任务和触发任务在调度层用的是同一套执行器,只是入队来源不同。这个设计后面第 4 章会展开。
智能诊断中心和规则管理中心是一期的骨架、二三期的血肉。规则管理中心管技术规则、业务规则、规则作业和规则模型,一期的规则是“指标 > 阈值持续 N 分钟则执行脚本”这种形式化表达;智能诊断中心一期只做风险类别管理和基础的趋势识别,事件识别和机器模型诊断留到二期。
前端应用分四类角色,一线运维和值班主管看告警推送、告警查询、指令下发、执行结果确认;运维工程师做脚本配置、新建任务、任务执行结果确认;运维主管负责执行任务审批、执行过程管控、执行结果查看、执行痕迹查看;主管领导看大屏监控。角色不同,能看到的菜单和能做的动作必须不同,这块在权限设计上要提前规划,不能等上线了再补。
对接系统这一层有六个:业务网管、Zabbix Server、工单系统、CMDB、云管平台、日志平台。一期实际强依赖的是前三个——告警从业务网管来,指令通过 Zabbix Server 下发,需要留痕的故障推到工单系统。CMDB 和云管平台提供资源归属信息,能接就接,接不上可以先用手工维护的资源表兜底。
3.3 数据流设计:一条告警在平台内的完整旅程
把模块画完只是静态图,真正决定平台好不好用的是动态流。一条告警从产生到闭环,在平台里要走这么几步:
业务网管收集到告警信息后推送到自动化运维平台;平台根据规则服务和调度配置判断是否有对应的处置方案;有方案则调用 Zabbix Server 发送执行指令,同时监控执行过程;执行完成后取回执行后的指标,判断是否恢复;对于需要生成故障工单的告警,自动推送至工单系统,工单处理完成后回写状态,闭环结束。没匹配到规则或者执行失败的告警,转人工处理,同样要生成工单留痕。
这个过程里最容易设计错的是状态机。告警状态不能只有“未处理/已处理”两种,至少要区分:已接入、规则匹配中、已匹配待执行、执行中、执行成功待确认、执行失败待人工、已转工单、已闭环。每个状态之间的迁移条件要写清楚,比如“执行中”超过设定超时时间未收到回调,自动转为“执行失败待人工”,而不是永远卡在那里。
# alert_flow.py —— 告警状态机,状态迁移集中在一处,避免各处 if-else 打架 from enum import Enum class AlertState(Enum): RECEIVED = "received" # 已接入 MATCHING = "matching" # 规则匹配中 MATCHED = "matched" # 已匹配,等待执行 EXECUTING = "executing" # 指令已下发,等待结果 SUCCESS = "exec_success" # 执行成功,待人工确认 FAILED = "exec_failed" # 执行失败,转人工 TICKETED = "ticketed" # 已生成工单 CLOSED = "closed" # 已闭环 # 允许的迁移路径,白名单之外的一律拒绝 TRANSITIONS = { AlertState.RECEIVED: [AlertState.MATCHING], AlertState.MATCHING: [AlertState.MATCHED, AlertState.TICKETED], AlertState.MATCHED: [AlertState.EXECUTING, AlertState.TICKETED], AlertState.EXECUTING: [AlertState.SUCCESS, AlertState.FAILED], AlertState.SUCCESS: [AlertState.CLOSED, AlertState.TICKETED], AlertState.FAILED: [AlertState.TICKETED, AlertState.CLOSED], AlertState.TICKETED: [AlertState.CLOSED], } def transit(alert, to_state, reason: str = ""): if to_state not in TRANSITIONS.get(alert.state, []): raise ValueError(f"illegal transition {alert.state} -> {to_state}") alert.state = to_state alert.reason = reason # 迁移原因必须落库,事后复盘全靠它 alert.save()这段代码的价值不在于枚举写得多全,而在于把“状态怎么变”收敛到一个函数里。我在做类似系统时踩过的坑是:一开始图省事,各个模块直接改alert.status字段,结果上线三个月后没人说得清一条告警为什么从“执行中”直接跳到了“已闭环”。加上迁移白名单之后,非法跳转直接抛异常,配合日志能立刻定位是哪段逻辑写错了。
状态之外还要设计幂等。同一条告警可能被重复推送,规则匹配和执行下发都要带唯一键做去重,否则同一条磁盘告警触发三次清理脚本,第三次可能就把正在写的日志文件删了。
4. 核心模块落地:脚本集中管理、任务调度与工单闭环
架构讲清楚之后,真正决定这套平台能不能跑起来的是四个模块:脚本怎么存、任务怎么调、告警怎么触发、结果怎么留痕。这一章按这个顺序展开,每个模块给一段可以直接改改就用的实现,并说明为什么这么选。
4.1 脚本下发:两种方案的取舍与最终选型
Zabbix Server 下发指令有两种做法,方案差异很大,选错了后期很难改。
方案一是脚本提前预置在各服务器端,作业平台只与 Zabbix Server 做指令通讯,Zabbix 调用本地脚本执行。优点是脚本固化在本地,出错概率低;对 Zabbix agent 账号所需权限较小,无需提前赋权。缺点是灵活性低,改一次脚本要全网服务器同步;脚本配置变更由运维工程师控制,得单独赋权后做批量部署;脚本存放在服务器端,存在被篡改的风险。
方案二是脚本统一在自动化作业平台维护和配置,客户端通过接收 Zabbix Server 远程命令执行。优点是脚本集中化管理,可管可控;灵活高效,脚本调整后编辑即生效;风险高的脚本可以先经管理人员审批再配置;执行过程详细记录,可追溯。缺点是对 Zabbix agent 账号所需执行权限较高,需要提前赋权。
这套方案最终选了方案二。理由不是方案二没有缺点,而是方案一的缺点在这个场景下更致命——1.5 万台设备要同步脚本,本身就是一件需要自动化的事,用不自动化的方式去做自动化平台,逻辑上说不通。至于权限问题,靠 sudo 白名单和专用执行账号解决,而不是靠降低权限需求来回避。
注意:方案二的安全边界完全取决于 agent 账号的权限控制。给 root 加 NOPASSWD 是最省事也最危险的做法,一旦平台侧被攻破,等于全网设备失守。通常的做法是建一个专用账号,sudoers 里只放行脚本目录下的具体命令,且不允许通配符。
脚本的元数据用一张表管起来,正文可以放对象存储,库里只留哈希和版本,这样既避免大字段拖慢查询,也能通过哈希对比发现非平台侧的直接修改。
-- 脚本主表:只存元数据,正文进对象存储,库里留 hash 做变更检测 CREATE TABLE ops_script ( id BIGINT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(64) NOT NULL UNIQUE COMMENT '脚本名,执行时按名调用', lang VARCHAR(16) NOT NULL COMMENT 'shell/bat/perl/python/powershell', content_hash CHAR(64) NOT NULL COMMENT '正文 SHA256,用于发现绕过平台的改动', risk_level TINYINT NOT NULL DEFAULT 2 COMMENT '1低 2中 3高,3级必须审批', version INT NOT NULL DEFAULT 1, status TINYINT NOT NULL DEFAULT 1 COMMENT '1启用 0停用', updated_by VARCHAR(32) NOT NULL, updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ) COMMENT '脚本统一管理'; -- 执行记录表:每一次下发都要有一条,无论成败 CREATE TABLE ops_exec_log ( id BIGINT PRIMARY KEY AUTO_INCREMENT, exec_id CHAR(36) NOT NULL COMMENT '执行唯一号,与告警/任务关联', script_name VARCHAR(64) NOT NULL, target VARCHAR(128) NOT NULL COMMENT '目标主机或 IP', source_type VARCHAR(16) NOT NULL COMMENT 'cron/alert/trend/model', source_id VARCHAR(64) NOT NULL COMMENT '来源任务号或告警号', rc INT NOT NULL COMMENT '返回码,-1 表示超时', stdout TEXT COMMENT '截断到 4KB,防止撑爆表', cost_ms INT NOT NULL, operator VARCHAR(32) NOT NULL COMMENT '触发人,自动触发填 system', created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, KEY idx_source (source_type, source_id), KEY idx_target_time (target, created_at) ) COMMENT '执行留痕';risk_level这个字段值得单独说一句。它的作用不是分类好看,是决定审批路径:1 级脚本比如查询类命令免审批直接跑,2 级脚本比如日志清理要记录操作人,3 级脚本比如服务重启、配置变更必须走审批。分级标准建议让运维主管来定,工程师自己定级容易全都定成 1 级。
4.2 任务调度:周期任务与触发任务共用一套执行器
任务管理主要针对周期性任务,设置定时触发策略,支持执行脚本的关联、任务的启用禁用、执行结果的确认。告警管理那边是另一套入口,告警信息来源于业务网管平台,同样支持脚本关联和执行结果确认。两条入口如果各写一套执行逻辑,后期维护成本会翻倍,所以设计上把它们统一成同一个 Job 模型。
Job 的核心字段就几个:触发类型、触发条件、目标范围、关联脚本、参数、超时时间、失败策略。周期任务的触发条件是 cron 表达式,告警任务的触发条件是规则 ID,趋势任务的触发条件是趋势规则 ID。执行器不关心任务从哪来,只认 Job。
# executor.py —— 周期任务与触发任务共用的执行入口 import json, subprocess, time, uuid ALLOWED_SCRIPTS = {"svc_restart.sh", "disk_clean.sh", "log_rotate.py", "check_nginx.sh"} TIMEOUT = 120 # 秒,超过即判失败,避免僵尸任务占住执行槽 def run_job(job, target_host, params, operator="system"): """job: 任务定义字典; target_host: 目标主机; params: 全局参数渲染后的键值""" script = job["script_name"] if script not in ALLOWED_SCRIPTS: # 白名单,挡住任意命令执行 return {"code": 403, "msg": "script not in whitelist"} cmd = ["/usr/local/bin/run_script.sh", script, json.dumps(params)] started = time.time() try: r = subprocess.run(cmd, capture_output=True, text=True, timeout=TIMEOUT) return { "exec_id": str(uuid.uuid4()), "target": target_host, "script": script, "rc": r.returncode, "stdout": r.stdout[-4000:], # 截断,日志表不是文件系统 "stderr": r.stderr[-2000:], "cost_ms": int((time.time() - started) * 1000), "operator": operator, } except subprocess.TimeoutExpired: return {"code": 504, "msg": "exec timeout", "target": target_host, "cost_ms": TIMEOUT * 1000}几个参数需要按实际环境调整。TIMEOUT默认 120 秒,对重启类脚本偏短、对查询类偏长,通常的做法是按脚本分级配置,把超时写进脚本元数据而不是全局常量。ALLOWED_SCRIPTS用硬编码集合是为了示例清晰,生产环境应该改成查库比对ops_script表的status字段。stdout截断到 4KB 是经验值,日志清理脚本的输出可能很长,但真正有用的通常是最后几十行,截尾比截头合理。
并发控制是另一个必须提前想的问题。1.5 万台设备如果一次性下发,Zabbix Server 和网络都会被压垮。常见的做法是按批次分组,每批 100 到 200 台,批间隔 30 秒,同时对同一目标主机的并发执行数做限制,避免两个任务同时改同一个配置文件。这些参数写在调度中心的配置里,不要硬编码在代码中。
执行结果确认这一步不能省。方案里明确写了“责任人对任务执行结果进行确认”,意思是自动执行不等于自动闭环,成功与否要有人签字。这个设计看起来低效,实际上是责任边界:脚本返回码是 0 不代表业务真的恢复了,磁盘清理成功但服务还是连不上数据库的情况很常见。确认动作同时也是一个反馈入口,确认时填写的备注会变成后续优化规则的素材。
4.3 告警联动与工单闭环:规则、状态机与回调
规则是告警到动作之间的桥。一条规则要回答四个问题:匹配哪些告警、满足什么条件才触发、触发后干什么、干完之后怎么收尾。把它写成结构化配置比写成一堆 if-else 好维护得多,也方便运维主管自己改而不找研发。
# rules/redis_mem_high.yaml —— 告警到动作的映射规则 match: source: business_nms # 告警来源,与接入时的 source 字段对齐 metric: redis_used_memory_pct # 指标名,必须与指标字典一致 operator: ">" threshold: 85 duration: "5m" # 持续 5 分钟才触发,过滤瞬时抖动 scope: "prod-redis" # 只对生产 Redis 集群生效,测试环境不自动处置 action: type: script script: redis_bigkey_clean.sh params: threshold_mb: 512 dry_run: false # 首次上线建议置 true,只分析不删除 approval: false # 2 级脚本免审批 ticket: create: true # 无论成败都生成工单,留痕优先 assignee_group: "中间件组" on_fail: notify # 执行失败升级到人工,不静默吞掉duration这个字段是最容易被低估的。没有它,任何一次瞬时抖动都会触发脚本,而清理类脚本频繁执行本身就是风险。5 分钟是个起步值,缓存类指标可以放宽到 10 分钟,硬件类指标可以缩到 2 分钟,具体看业务对抖动的容忍度。scope用来隔离环境,这条如果不写,测试环境的告警一样会触发生产脚本,属于典型的翻车现场。dry_run是灰度开关,新规则上线第一周建议先开着,观察匹配量和误报率,确认无误再关。
工单闭环的关键在于状态双向同步。平台推送工单号给工单系统,工单系统处理完成后要回调平台,平台把告警状态推到已闭环。这个回调如果只做单向推送,就会出现工单已经关了、平台上告警还挂着执行中的情况,值班人看到一堆假活跃告警,很快就对平台失去信任。
// 工单回调报文示例,字段名要与工单系统约定死 { "ticket_id": "WO202405120001", "source": "ops_platform", "alert_id": "AL-8837261", "status": "resolved", // open/processing/resolved/closed "handler": "middleware_group", "remark": "清理大 key 3 个,内存回落至 62%", "resolved_at": "2024-05-12T14:32:11+08:00" }回调要做签名校验和幂等处理。签名防止伪造,幂等防止工单系统重试导致告警被反复关闭。这两条在联调阶段经常被跳过,等到生产环境出问题再补,改动面会很大。
4.4 参数管理与审批:把高危操作的后悔药提前备好
参数管理指的是系统变量这类全局性参数,比如工单系统接口地址、邮件服务器配置、Zabbix API 地址、脚本里用到的公共阈值。它的价值在于“改一处生效全平台”,避免每个脚本里各写一份 IP 地址,换一次环境要改几十个文件。
参数表设计上要注意两点:一是参数值要区分明文和密文,密码类参数在库里加密存储,前端只显示掩码;二是参数变更要留版本,改错了能回滚。我在类似项目里见过参数被误改导致全平台脚本调不通、排查了两个小时的情况,后来加了变更历史和生效时间,这类问题基本不再出现。
审批流是最后一道闸。高危脚本、批量执行、生产环境变更,这三类操作都应该走审批。审批设计的重点是别让审批变成走过场:审批页面必须能看到脚本内容、目标范围、影响评估和历史执行记录,只给一个“同意/驳回”按钮的审批等于没有审批。另外要设置超时自动驳回,避免任务卡在待审批状态一整晚,第二天早上告警堆积如山。
灰度执行也是同一个思路的延伸。1.5 万台设备不可能一次全推,正确做法是先选 1 台非核心设备跑通,再扩到一个小分组,确认指标正常后分批放量。执行监控页面要能看到当前批次、成功数、失败数、失败原因分布,出现批量失败要能一键暂停剩余批次。这个“后悔药”按钮平时用不上,用上一次就值回票价。
5. 避坑与排查:五条血泪经验对应的现象、原因和解决
方案写得再漂亮,上线头两周总会遇到各种意想不到的问题。下面这五条是这类平台在实施阶段出现频率最高的,每条按现象、原因、解决三段写,遇到时可以对着排查。
5.1 现象:脚本在平台点“执行”没反应,日志里也看不到记录
原因通常有两个方向。一是 Zabbix agent 侧的远程命令没开,EnableRemoteCommands默认为 0,平台下发了指令但客户端直接丢弃,两边都没有报错。二是 sudo 配置里写的是绝对路径加通配符,实际执行时命令行参数拼接方式和 sudoers 规则对不上,被静默拒绝。这两种情况都不会在业务日志里留下明显痕迹,属于典型的黑匣子问题。
解决的第一步是把链路拆开验证:先在目标机手工执行zabbix_agentd -t system.run["/path/script.sh"],确认 agent 自身能跑;再在 Zabbix Server 上用zabbix_get远程调用一次,确认网络和权限;最后才回到平台触发。排查顺序不能反,反了会在平台侧兜圈子。sudoers 建议写成具体的命令加参数模式,改完之后用sudo -l -U 执行账号核对实际生效的规则。
5.2 现象:同一批任务里部分主机成功、部分超时,失败率忽高忽低
原因多半是并发没控住。1.5 万台设备的批量任务如果一次性下发,Zabbix Server 的 poller 进程会被打满,后排队的请求超时;也可能是目标机负载本身较高,脚本执行被挤占。还有一种隐蔽情况是网络抖动,跨机房的设备 RTT 高,同样的超时阈值在总部机房够用,在分支机房就不够。
解决办法是分三件事做:调度层按分组分批下发,批大小从 100 开始压测,找到 Zabbix Server 的吞吐拐点;超时时间按网络区域差异化配置,跨机房适当放宽;执行记录里加上目标机的响应时间,方便判断是平台慢还是目标机慢。失败重试要有上限,建议最多两次,且第二次间隔拉长,避免把已经过载的机器彻底压死。
5.3 现象:告警明明已经恢复,平台上还显示“执行中”,值班人开始不信任平台
这是状态机没闭环的典型表现。原因通常是回调丢包或者工单系统那边改了状态但没回写,也可能是执行超时后平台只记了失败但没有推进状态。有些实现里执行结果靠轮询 Zabbix 拿,轮询间隔设得很长,也会造成长时间悬挂。
解决上,一是给每个处于中间状态的告警加超时兜底,超过设定时间自动迁移到“待人工”,并在界面上明确标出是超时导致;二是回调接口必须做重试和对账,每天凌晨跑一次全量对账,把平台侧和工单侧的未闭环单据拉出来比对;三是给值班人一个“手动纠正状态”的入口,允许填原因后强制闭环,所有手动操作进审计日志。这条兜底通道很关键,没有它,值班人遇到卡单只能干等。
5.4 现象:脚本版本对不上,明明改好了,跑起来还是旧逻辑
原因通常是脚本缓存在客户端侧。方案二虽然以平台为中心,但 Zabbix 远程命令执行时如果脚本本身在目标机有本地副本,很容易出现平台改了、本地没同步的情况。另一种情况是平台的脚本版本管理只做了入库没做发布,编辑后保存的是草稿,实际执行取的是上一个已发布版本。
解决靠两点:执行前校验脚本哈希,平台下发的哈希与目标机实际文件的哈希不一致就拒绝执行并告警;脚本管理页面明确区分草稿和已发布,发布动作单独记录操作人和时间。这一条看着繁琐,但脚本类平台最怕的就是“跑的不是我想跑的那份”,一次误执行的影响可能比不执行大得多。
5.5 现象:规则上线后误报频发,运维开始手动屏蔽,最后形同虚设
根因几乎都是规则写得太激进:阈值贴着告警线设、没有持续时间要求、没有环境隔离、没有排除已知的周期性波动。比如备份窗口期间磁盘 IO 必然飙高,这条如果不排除,每天晚上都会误触发一次。
解决思路是把规则当成代码来管:每条规则上线前用历史数据回放一遍,统计触发次数和其中的人工判定为误报的比例,比例超过两成就不许上线;规则必须有scope和duration,没有的一律打回;规则变更走审批并保留版本,出问题能立刻回滚到上一版。另外给运维一个“这条是误报”的反馈按钮,反馈数据积累起来,就是二期做趋势识别和模型训练的语料。
6. 验收与答辩:用一条告警链路跑通全流程
功能清单打勾式的验收没什么说服力,评委和主管想看的是“一条真实的告警进来,平台能不能自己走完”。我一般会把验收压缩成一条端到端链路,五个检查点全部通过才算交付:告警接入、规则命中、指令下发、执行留痕、工单闭环。演示时从造一条测试告警开始,到指标回落结束,全程不超过十分钟,比讲半小时架构图管用。
#!/usr/bin/env bash # accept.sh —— 一条告警的端到端验收,5 个检查点全 PASS 才算通过 set -u API="http://ops-platform.example/api/v1" ALERT_ID="AL-TEST-0001" # 1. 造一条告警:走正式接入接口,不走后门改库 curl -s -X POST "$API/alerts/mock" -d @alert_sample.json \ | grep -q '"accepted":true' && echo "PASS 告警接入" || echo "FAIL 告警接入" # 2. 规则命中:等 5 秒让规则引擎跑完,检查是否关联到预期脚本 sleep 5 curl -s "$API/alerts/$ALERT_ID/actions" | grep -q '"script":"redis_bigkey_clean.sh"' \ && echo "PASS 规则命中" || echo "FAIL 规则命中" # 3. 执行留痕:执行记录必须有 stdout 和耗时,缺一不可 curl -s "$API/executions?alert_id=$ALERT_ID" | grep -q '"stdout"' \ && echo "PASS 执行留痕" || echo "FAIL 执行留痕" # 4. 工单闭环:工单号必须回写到告警上 curl -s "$API/alerts/$ALERT_ID" | grep -q '"ticket_id":"WO' \ && echo "PASS 工单闭环" || echo "FAIL 工单闭环" # 5. 指标回落:3 分钟后复查监控指标,确认业务真的恢复了 sleep 180 curl -s "$API/metrics/redis_used_memory_pct?scope=prod-redis" \ | awk -F'"' '{print $4}' | awk '{exit !($1<85)}' \ && echo "PASS 指标回落" || echo "FAIL 指标回落"这个脚本有三个设计上的考量,答辩时可以主动讲。第一,告警走正式接入接口而不是直接写库,验证的是整条链路而不是某个模块。第二,每个检查点只验一个关键事实,失败时能立刻定位到是哪一段断了,不至于一出问题就全局排查。第三,最后一个检查点等 3 分钟看指标,这是区分“脚本跑完了”和“故障真的解决了”的关键——很多平台验收时只看返回码 0,上线后才发现脚本成功了但问题还在。
配套的验收表建议按模块列,每行写清楚验收项、验收方法、通过标准、责任人。表不用太长,一页纸能放下最好,答辩时直接投出来,比翻 PPT 找截图高效。
| 模块 | 验收项 | 通过标准 |
|---|---|---|
| 告警管理 | 业务网管告警接入 | 接入延迟 < 10 秒,字段完整率 100% |
| 规则引擎 | 规则匹配准确率 | 抽检 50 条告警,误匹配 ≤ 2 条 |
| 脚本管理 | 五类脚本执行 | shell/bat/Perl/Python/PowerShell 各跑通一次 |
| 任务调度 | 周期任务执行 | 连续 24 小时按 cron 触发,无漏执行 |
| 执行留痕 | 记录完整性 | 每条执行都有 stdout、耗时、操作人 |
| 工单闭环 | 双向同步 | 工单状态变更 30 秒内回写平台 |
| 权限 | 角色隔离 | 四个角色登录后菜单与操作权限符合设计 |
答辩时最容易被问的两个问题,一个是“自动处置失败了怎么办”,一个是“凭什么相信脚本不会误伤”。第一个问题的答案是失败升级到人工加自动生成工单,且失败率超过阈值自动暂停该规则;第二个问题的答案是白名单、分级审批、灰度执行和哈希校验这四道闸,缺一不可。这两个问题答得上来,基本就稳了。
从那以后我每次做这类平台,都会在上线前强制走一遍这条端到端链路,哪怕功能清单已经全部打勾。因为清单是给人看的,链路是给系统看的,两者中间隔着的那段距离,往往就是上线第一周出事的地方。希望帮到你。
本文还有配套的精品资源,点击获取