Skip to content

故障排查

常见现象与定位路径,外加路由调优的三个旋钮。观测入口见 健康与状态


现象对照表

现象可能原因与怎么查
agent 连不上控制面检查 controller_url 可达且不带尾斜杠;常驻模式必须配 controller_url
新机器注册后没反应在等审批:查 GET /admin/registrations?status=pending
agent 报 pending-approval 循环已批准但还没 provision——下发 DesiredState 后才能拿 token
健康 stale没追上最新 generation 或太久没上报;看 status-events 的最后时间
健康 degraded应用失败或有漂移;看 status-events?kind=apply 的报错
健康 down超过 down_after 完全静默;检查 agent 进程与网络
控制面重建后全 fleet 掉线假象。 agent 在指数退避重连(上限 30 s),数据面不受影响。见下
BGP 全断又自愈多半是隧道或容器重建触发,1–3 分钟自愈,属正常
WireGuard 握不上手(handshake=0)入站 peer 的监听端口没落在端口池段位内、或没对外发布;对端是动态 IP 时等一轮 reresolve(45 s)。某接口公钥与其余不一致即密钥分叉,见下
eBGP 会话周期性(约 180 s)断连且导入 0 条MTU 黑洞三联征,见下
某节点比同 AS 节点缺路由多半各节点 internal_topology 不一致、iBGP 没全互联。机制与 checklist 见 内部互联
内网链路延迟异常高(100 ms+)跨境节点的 WireGuard 拨号方向拨反,见下
token 失效(401)过期或被轮换撤销。agent 的 401 自愈会重新注册;或重新签发并更新 identity
想先演练不动机器python -m agent.main --plan-only 跑一遍看计划
Docker 部署失败确认 agent 主机能访问 Docker socket;看 apply-result 的 errors

几类需要展开的故障

控制面重建后的「全员掉线」

控制面重建期间全部 agent 的 WebSocket 同时断开并进入退避重连,管理面看到「全 fleet 离线」。

这不是事故。 数据面完全不受影响——节点按最后一次已应用的配置继续转发;控制面失明不等于网络中断。重建完成后 1–2 分钟内 agent 自行回连。判断是否真出问题:看那之后的 GET /admin/health 是否仍有节点 down

密钥分叉

同一节点的某个 WG 接口公钥与其余接口不一致,即密钥分叉。表现是该接口握不上手,而同节点其它接口正常。

节点密钥现在是控制面单一事实源并由 materialize 无条件注入,正常路径不会分叉。历史成因是接口 spec 里填了占位符引用,导致 agent 另行生成一把托管密钥。不要往 private_key_ref 里手填任何值——schema 已强制拒绝 URI 形态,但仍不要绕过 materialize 的注入。

上报公钥与控制面记录不符时会被 409 拒绝并回滚事务,这是防止分叉扩散的闸门;遇到 409 应当查清哪一侧是对的,而不是绕过它。

MTU 黑洞

三联征:eBGP 会话周期性断连(间隔接近 hold timer)、导入 0 条路由小包 ping 正常

成因是接口 MTU 大于路径实际 PMTU,小报文过得去而大的 UPDATE 报文被黑洞,会话在 hold timer 到期时断开重来。

定位办法是用 DF 大包二分找路径 PMTU:

bash
docker exec dn42-<node>-dn42-debug-shell-1 ping -M do -s <payload> <对端隧道地>

找到阈值后把接口 MTU 调到该值以下。跨境链路上这是常态,需要显式配低于默认 1420 的值。

自动对等的会话可以直接调用 POST /autopeering/requests/{id}/probe-mtu 让服务端做这次二分。

拨号方向拨反

不对称跨境线路上,两端的「谁拨谁」不是随便选的:拨错方向会让流量走上劣质路径,表现为内网链路 RTT 突然高一个量级。

排查时先确认两端 wireguard_peer.endpoint 的配置——只有主动拨出的一端会填对端 endpoint。改方向就是把 endpoint 从一端移到另一端。

排查 BGP 状态要看实时,不看快照

runtime snapshot 是约 5 分钟一份的采样,排障时它可能已经滞后。要看当下状态直接连 BIRD:

bash
docker exec dn42-<node>-dn42-bird-router-1 birdc show protocols
docker exec dn42-<node>-dn42-bird-router-1 birdc show route protocol <sess> count

用 debug-shell 测连通性

router-netns 容器内没有 ping 二进制,对它 docker exec ping 会假阴性。

debug-shell 容器:它共享 router netns,带 ping / tcpdump / wg / dig

bash
# 验证本节点的任播 DNS 实例
docker exec dn42-<node>-dn42-debug-shell-1 dig @<任播地> example.dn42

# DF 大包找 PMTU
docker exec dn42-<node>-dn42-debug-shell-1 ping -M do -s 1400 <>

不登节点的等价手段是主动拨测


路由调优三件套

把「按前缀精调」和「社区」用起来的三个旋钮,从粗到细。字段定义见 BIRD 与路由

过滤器的完整判定顺序见 路由策略

旋钮位置作用注意
BgpSessionSpec.link_latency(1–9)会话给该会话学到的路由打 DN42 (64511, 档) 延迟社区(端到端取最差档),传播到全网可见⚠️ 仅可见性与信令。 本 fleet 据此选路——latency 社区只含 eBGP 链路、不含 fleet 内部跳数,据它选路会让节点弃近就远。选路仍交给默认的 hot-potato(IGP 距离已算进内部跳数)
Bird2ConfigSpec.cold_potato_med(默认 50)节点给带本节点同大区 region 社区的路由在导入时设此 MED(越低越优),优先就近同区域路径跨区域保持 100。改的是 MED,比 local_pref 温和——不越过 AS-path 与 eBGP-direct
Bird2ConfigSpec.route_local_pref节点精确匹配的单个前缀bgp_local_pref只影响该前缀,不波及会话其余路由;仅本节点导入侧、不导出。要全 fleet 优先某入口,只需在该入口节点配一条,经 iBGP 传播

不要用会话级 local_pref 做前缀调优。 BgpSessionSpec.local_pref 对整条会话生效——对 transit peer 用它,爆炸半径是该会话导入的全部前缀。按前缀精调一律用 route_local_pref

例:让 fleet 对某前缀优先走某入口

只在该入口节点的 base_template.bird.route_local_pref 加一条:

json
{"prefix": "172.20.62.160/27", "local_pref": 200}

验证只动了目标前缀、没波及透传:

bash
docker exec dn42-<node>-dn42-bird-router-1 birdc show route for 172.20.62.160/27 all   # local_pref=200
docker exec dn42-<node>-dn42-bird-router-1 birdc show route protocol <sess> count       # 其余仍 100

Web 界面的路由调优页覆盖节点级两项加会话级 link_latency