服务器一升级,24 个流量复制任务全挂:AI 15 分钟查清根因,之后一句话修好
服务器一升级,24 个流量复制任务全挂:AI 15 分钟查清根因,之后一句话修好
TL;DR 上一篇讲对账,前提是线上流量能源源不断地复制到测试机器上。可有一天,线上服务器升级了一次,24 个流量复制任务全部停摆。
这篇复盘 AI 是怎么修好它的:它没有瞎试,而是去读了平台的源码,15 分钟内找到一个很隐蔽的坑:同一台机器有两个 IP,只有其中一个能用。 修好以后,我让它花 2 分钟把整个过程沉淀成 Skill。后来再遇到同样的情况,我只需要说一句话。
文末整理了让 AI 执行运维操作时,我给它定的几条规矩。
一、出了什么事
先回顾一下背景。为了验证新代码,我在一个内部云平台上建了 24 个流量复制任务:每个任务把一台线上机器收到的请求实时复制一份,发给一台测试机器(沙箱)。12 台线上机器,每台对应 A、B 两台沙箱,正好 24 个任务。
有一天,运维对线上服务做了一次蓝绿升级。
蓝绿升级:先启动一批装着新版本的机器(绿),确认没问题后把流量切过去,再下线旧机器(蓝)。好处是升级过程中服务不中断,代价是升级完以后,所有机器都换了一批,IP 全变了。
流量复制任务里记的是旧机器的 IP。旧机器下线后,24 个任务全部报错停止,报错信息是:“源 IP 未运行,请检查”。
手动修的话,要在控制台里一个个处理:查每个任务原来对应哪组机器,从新机器里挑一台,填好配置,再启动。24 个任务,点到手软,还容易填错。
于是我把问题丢给了 AI。
二、AI 的排查过程:不猜,去读源码
我给的指令是这样的:
“集群因为蓝绿升级 IP 改变,所有流量复制都失败停止了。沙箱 IP 不变。你看能直接修改源 IP 吗?或者删除旧的新建新的。要求:任务名称不变,沙箱 IP 不变,源 IP 从集群当前对应分组里正在运行的机器里选。”
注意这句话里有三个“不变”和一个“从哪里选”。这是我给它画的边界,后面会讲为什么重要。
第 1 步:能不能直接改?读源码找答案(2 分钟)
最省事的办法是直接编辑任务,把源 IP 改掉。但 AI 没有直接去试,而是先去读了这个云平台的前后端源码(公司内部平台,我本地有代码)。
两分钟后,它给出了结论:改不了,只能删了重建。 证据有两条:
- 前端:编辑弹窗里,源 IP 这个输入框在编辑模式下是隐藏的,页面上根本改不了;
- 后端:就算绕过页面直接调接口,编辑逻辑也只会更新目标 IP、端口、时长这几个字段,源 IP 压根不在更新范围里。
它还顺手确认了一件事:删除是物理删除,删完以后,用原来的名字新建任务不会报重名。所以“删了重建”这条路走得通,任务名称也能保持不变。
如果它直接调接口去改,接口会返回“成功”,但源 IP 并没有变。这种“假成功”比直接报错更坑人。
第 2 步:按方案执行,却全部失败(这里才是真正的坑)
我回了一句:“你来执行,除了源 IP,其他都和当前任务一致就行。”
AI 调用平台接口,查到了每个分组下正在运行的机器,用这些机器的 IP 重建了任务。然后点击启动:
还是“源 IP 未运行”。
机器明明是运行中的,为什么平台说它没在运行?
第 3 步:找一个成功的样本做对比
24 个任务里,恰好有一个启动成功了。AI 没有放过这个线索,拿它和失败的任务做对比,很快发现了规律:
- 失败的任务:源 IP 是一个网段(下面叫“甲段”);
- 成功的那个:源 IP 是另一个网段(“乙段”);
- 平台在新建任务的下拉框里,列出来的“可选源 IP”全是乙段,一个甲段的都没有。
第 4 步:再读一次源码,定位根因(13 分钟时)
AI 又回去读了“启动任务”的后端代码,发现平台判断“源 IP 是否在运行”时,查的是一张存活节点表,而这张表里登记的只有乙段 IP。
再回头看查询机器列表的接口,问题就清楚了。同一台机器,接口返回了两个 IP 字段:
| 字段 | 示意值 | 是什么 | 流量复制认不认 |
|---|---|---|---|
ip | 甲段 | 容器内部的虚拟网卡 IP | ❌ 不认 |
podIP | 乙段 | 平台网络层真正可路由的 IP | ✅ 只认这个 |
AI 第一次重建时,用的是 ip 字段。从名字上看它最像“机器的 IP”,但流量复制系统只认 podIP。
同一台机器,两个都叫 IP 的字段,只有一个是对的。 这种坑,文档里不会写,报错信息也不会提示,只能从代码里找。
第 5 步:修复,全部恢复(18 分钟)
改用 podIP 重建,24 个任务全部启动成功,状态都是“运行中”。重建时还保留了一个约束:同一组的 A、B 两个任务,必须复制同一台线上机器的流量(否则上一篇的三方对账就对不上了)。
从我提出问题到全部恢复,一共 18 分钟。
可带走的经验:
- 内部平台的行为说不清楚时,让 AI 去读平台源码,比让它反复试错靠谱得多。代码就是最准确的文档;
- 排查时遇到**“有一个成功、其余都失败”**,一定要拿成功的那个去对比,规律往往就藏在差异里;
- 警惕“名字看起来对”的字段。
ip和podIP的教训是:用之前先确认这个字段是给谁用的。
三、修好之后,2 分钟沉淀成 Skill
任务恢复后,我只说了一句:
“好的,保存为技能,后续还会用。”
两分钟后,AI 生成了一个叫 tcpcopy-recover 的 Skill,包含两部分:
1. 说明文档(给 AI 看的):什么情况下用这个 Skill,以及这次踩到的三个坑:
- 为什么不能直接改源 IP(前端隐藏 + 后端不更新);
- 为什么删了能同名重建(物理删除);
- 必须用
podIP,不能用ip(附原因)。
2. 自动化脚本:一条命令完成“查任务 → 查新机器 → 删除 → 重建 → 启动 → 校验”。另外支持一个 --dry-run 参数:只打印准备怎么改,不真的执行。
# 先看计划
python3 recover_tcpcopy.py --cluster <集群名> --dry-run
# 任务: 对照A1 | 旧源IP: x.x.x.1 -> 新源IP: y.y.y.7 | 目标: 沙箱A1
# 任务: 对照B1 | 旧源IP: x.x.x.1 -> 新源IP: y.y.y.7 | 目标: 沙箱B1
# ...
# 确认无误后再真正执行
python3 recover_tcpcopy.py --cluster <集群名>
以后再遇到蓝绿升级,我只要说一句“修复流量镜像任务”,AI 就会自己找到这个 Skill。批量操作之前,我会让它先跑一遍 dry-run 给我看计划,确认无误再动手。
可带走的经验:一件事第一次让 AI 做成功了,马上让它沉淀成 Skill,这时候上下文最完整,坑也记得最清楚。第二次再做,往往就能省掉 90% 的时间。这一步的成本是 2 分钟和一句话。
四、进化:不调接口了,直接操作浏览器
两天后,又来了一个新需求:给 24 台沙箱升级版本。流程是:
停止全部 24 个复制任务 → 逐台升级 24 台沙箱 → 重新启动全部任务 → 检查流量是否正常
AI 一开始还是打算去找平台接口。我想了一下,回了一句:
“不找接口,直接操作我的浏览器,是否可以?”
于是它改用浏览器自动化:在我已经登录的 Chrome 里打开平台页面,像人一样点击“停止”,打开升级对话框,选择版本,提交,再回到任务列表逐个启动。
什么时候调接口,什么时候操作浏览器? 我的经验是:
| 调接口 | 操作浏览器 | |
|---|---|---|
| 前期准备 | 要先搞清楚接口地址、参数和鉴权方式 | 几乎不需要,看页面就行 |
| 速度 | 快 | 慢,要一步步点 |
| 稳定性 | 接口不变就一直能用 | 页面一改版就可能失效 |
| 适合 | 高频、批量的操作,比如这次的修复任务 | 低频、一次性的操作,或者接口很难找的场景 |
升级沙箱一个月也就几次,花时间去研究升级接口不划算,直接操作页面反而更快。
验收时发现了一个隐藏问题
24 台沙箱全部升级完成,24 个任务全部显示“运行中”。如果到这里就结束,看起来已经大功告成了。
但我要求它多做一步:登录沙箱,看日志里到底有没有收到流量。 结果查出 23 个正常,有 1 个虽然显示“运行中”,实际一个请求都没收到。原因是那台沙箱上旧进程占着的端口还没释放(Address already in use)。AI 给出了处理办法:等几分钟端口释放后,在页面上重启这一个任务。
可带走的经验:
- 调接口和操作浏览器不是二选一,按操作频率来选;
- 验收不能只看状态。“运行中”只说明任务启动了,不说明流量真的到了。要去看真实的效果(这里是日志),才算真的做完。
五、让 AI 动手做运维,我的几条规矩
删除任务、重建任务、升级机器,这些都是会改变线上平台状态的操作。我敢放手交给 AI,是因为有这几条规矩兜底:
| 规矩 | 这次怎么做的 |
|---|---|
| 先确认影响范围 | 流量复制只是“抄送”一份流量给沙箱,任务全删了也不影响线上用户。会影响真实用户的操作,我不会这样交给 AI 做 |
| 用约束把边界写死 | “任务名称不变、沙箱 IP 不变、源 IP 只能从对应分组里选”。AI 只能在这个范围里做选择 |
| 先看计划,再执行 | 脚本有 dry-run,批量操作前先打印“准备把什么改成什么” |
| 用自己的登录态,不交出密码 | 脚本读取我本机浏览器里已登录的会话,浏览器自动化也在我自己的 Chrome 里操作。不需要把账号密码交给 AI |
| 验收要看真实效果 | 不只看“运行中”的状态,还要登录机器确认流量真的到了 |
| 做完马上沉淀 | 坑和对策写进 Skill,下次 AI 直接带着经验上场 |
这个 Skill 还不完美
说实话,这个脚本还有几处我不太满意,留着以后改:
- 判断任务属于哪个分组,靠的是任务名里的关键字,换一个集群就得改代码;
- 它会重建所有任务,不只是失败的那几个;
- 任务状态用的是数字(比如 3 代表运行中),可读性差。
不过它已经实实在在地帮我省了好几次时间。先能用,再逐步改好,对内部小工具来说,这样的顺序是合理的。
结语
回头看这次故障,AI 真正值钱的地方不在于“它会调接口”,而在于这两件事:
- 遇到不确定的情况,它会去读源码找证据,而不是反复试错:两次判断(改不了只能重建、要用
podIP)都来自代码; - 它能把一次性的排查,变成一个可以重复使用的 Skill。
而我做的事情很简单:画好边界,要求先看计划,最后亲自验收。