首页
/ Moby 内置网络诊断服务器详解:调试 Overlay 与 Swarm 网络问题的完整实战指南

Moby 内置网络诊断服务器详解:调试 Overlay 与 Swarm 网络问题的完整实战指南

2026-09-04 22:03:49作者:管翌锬

Moby(Docker 上游项目)在 libnetwork 中内置了一个网络诊断服务器(diagnostic server),用于检查 overlay 网络与 Swarm 服务发现数据在“网络数据库”中的实际状态。本篇以 daemon/libnetwork/cmd/diagnostic/README.md 为核心,结合 诊断服务器实现客户端实现热加载入口,完整讲解如何启用该工具、使用其 RESTful API 与 diagnosticClient 命令行工具排查集群网络故障,以及如何在排查结束后安全关闭它。

一、工具定位与风险边界:它看的是什么数据

该诊断工具自 Docker CE 17.12 引入,专门帮助定位运行在 Linux 主机上的 overlay 网络与 Swarm 服务问题。启用后,诊断服务器会在指定端口监听,对外提供诊断接口。文档明确要求:该工具只应在调试特定问题时临时启动,不应长期运行。

WARNING(原文档警示):该工具会改变 libnetwork API 的内部状态,使用必须谨慎并仔细阅读文档。误用会损坏甚至永久破坏网络配置。

理解它的前提是理解 overlay 驱动的数据模型:网络信息存储在“网络数据库”(networkdb)中,当前包含两类关键信息:

  • endpoint_table:服务发现(service discovery)信息,即各服务的 endpoint 记录;
  • overlay_peer_table:overlay 转发信息,即各节点间的 peer 记录。

从源码结构看,这两张表的条目都带有 owner(属主节点) 语义:每条记录归属于插入它的节点,并在该节点退出集群前保持持久。这一点直接决定了工具的使用姿势——例如对已加载 daemon 使用 -a 标志会触发 join/leave 网络的操作,副作用是“离开网络”,从而切断该 daemon 的数据路径。诊断客户端 main.go 中对孤儿条目(orphan entry)的检测也正是基于 owner 与当前网络 peer 集合的比对。

工具提供两种形态:

  1. 纯客户端dockereng/network-diagnostic:onlyclient,用于向本地 daemon 的诊断端口发请求;
  2. Docker-in-Docker 版本dockereng/network-diagnostic:17.12-dind,让诊断容器自身加入 Swarm,可诊断运行旧版引擎(早于 17.12)的集群。

二、启用诊断服务器:daemon.json 配置 + 免重启热加载

2.1 操作步骤

该工具目前仅支持运行在 Linux 上的 Docker 主机。启用步骤如下:

  1. /etc/docker/daemon.json 中把 network-diagnostic-port 设置为一个空闲端口:

    "network-diagnostic-port": <port>
    
  2. 获取 dockerd 进程的 PID(ps aux 输出中的第二列,通常是 2~6 位数字):

    $ ps aux |grep dockerd | grep -v grep
    
  3. 向该 PID 发送 HUP 信号,在不重启 Docker 的前提下热加载配置:

    kill -HUP <pid-of-dockerd>
    

    如果系统使用 systemd,执行 systemctl reload docker 即可达到同样效果。

成功后,Docker 主机日志中会出现类似消息:

Starting the diagnostic server listening on <port> for commands

2.2 源码级验证:配置项如何生效

该配置项是 dockerd 的一个(被标记为隐藏的)命令行/JSON 配置项,定义于 daemon/command/config.go

flags.IntVar(&conf.NetworkDiagnosticPort, "network-diagnostic-port", 0, "TCP port number of the network diagnostic server")
_ = flags.MarkHidden("network-diagnostic-port")

HUP/systemctl reload 触发的热加载逻辑位于 daemon/reload.goreloadNetworkDiagnosticPort

  • network-diagnostic-port 未配置或值为 0,则调用 netController.StopDiagnostic() 确保诊断关闭;
  • 若配置了有效端口,则调用 netController.StartDiagnostic(conf.NetworkDiagnosticPort) 启动诊断服务器。

服务器本体在 daemon/libnetwork/diagnostic/server.goServer 结构持有 enable 状态与 http.ServerEnable(ip, port) 启动监听并打印日志“Starting network diagnostic server listening on … for commands”(即上文日志消息的来源),Shutdown() 负责优雅停止并打印 “Network diagnostic server shutdown complete”。从 Enable 实现看,服务端设置了 5 分钟的 ReadHeaderTimeout 以缓解 Slowloris 类攻击,且源码注释标明该端口在 reload 时存在不可重配置的已知限制。

三、关闭诊断工具

对参与 Swarm 的每个节点重复执行以下操作:

  1. /etc/docker/daemon.json 中删除 network-diagnostic-port 键;

  2. 再次获取 dockerd 的 PID:

    $ ps aux |grep dockerd | grep -v grep
    
  3. 发送 HUP 信号热加载:

    kill -HUP <pid-of-dockerd>
    

主机日志中会出现:

Disabling the diagnostic server

这对应源码中配置未设置时走 StopDiagnostic() 分支的 reload 逻辑,实现的是调用 http.Server.Shutdown() 的优雅关闭(见 server.go 的 Shutdown 方法)。

四、访问诊断工具的 RESTful API

诊断工具暴露自己的 RESTful API:直接向监听端口发送 HTTP 请求即可。以下示例假设工具监听在 2000 端口(这也是客户端默认端口)。

4.1 获取帮助

$ curl localhost:2000/help

OK
/updateentry
/getentry
/gettable
/leavenetwork
/createentry
/help
/clusterpeers
/ready
/joinnetwork
/deleteentry
/networkpeers
/
/join

/help 会列出当前注册的全部端点(实现见 server.go 的 help handler,遍历 handlers map 输出路径)。/ready 返回 OK,供客户端做就绪探测——diagnosticClient 启动时的第一件事就是请求 http://<ip>:<port>/ready 并校验响应包含 OK

4.2 加入或退出网络数据库集群

$ curl localhost:2000/join?members=ip1,ip2,...
$ curl localhost:2000/leave?members=ip1,ip2,...

ip1ip2… 是 Swarm 节点 IP(通常一个即可)。

4.3 加入或离开某个网络

$ curl localhost:2000/joinnetwork?nid=<network id>
$ curl localhost:2000/leavenetwork?nid=<network id>

network id 需在 manager 上通过 docker network ls --no-trunc 获取,且必须是完整长度的标识符。客户端源码中也对这一点做了防御:当查询某网络但 peer 数为 0 时会提示“check the network ID, and verify that is the non truncated version”(见 main.go)。

4.4 列出集群 peer 与网络 peer

$ curl localhost:2000/clusterpeers

列出集群级 peer;列出连接到指定网络的节点:

$ curl localhost:2000/networkpeers?nid=<network id>

4.5 转储数据库表

两张表的含义:

  • overlay_peer_table:包含所有 overlay 转发信息;
  • endpoint_table:包含所有服务发现信息。
$ curl localhost:2000/gettable?nid=<network id>&tname=<table name>

4.6 操作指定表中的条目

$ curl localhost:2000/<method>?nid=<network id>&tname=<table name>&key=<key>[&value=<value>]

其中 <method>createentrygetentryupdateentrydeleteentry

注意(原文档强调):表操作具有**节点所有权(node ownership)**语义——条目会保持持久,直到插入它的节点仍在集群中。这正是排查“孤儿条目”的理论依据,也是删除操作不可逆的原因。

4.7 输出格式控制选项

server.go 的 ParseHTTPFormOptionstypes.go 的 HTTPReply 可以看到,所有端点都支持 URL 表单参数控制输出:

  • 追加 &json 返回 JSON 格式(application/json);
  • 追加 &json=pretty 返回缩进美化的 JSON;
  • 响应统一为 HTTPResult 结构:message 字段取值 OK/FAIL 等,details 承载具体内容(如 TableObjsizeentries,每个条目含 keyvalue(base64 编码值)、owner,见 types.go)。

diagnosticClient 内部请求 peers 与 table 时正是带上 &json 参数并反序列化 TablePeersResult / TableEndpointsResult(见 main.go 的 fetchNodePeers / fetchTable)。

五、使用 diagnosticClient 命令行工具

CLI 以 preview 形式提供、尚不稳定,命令和选项可能随时变化。可执行文件名为 diagnosticClient,通过独立容器提供:

docker run --net host dockereng/network-diagnostic:onlyclient -v -net <full network id> -t sd

README 给出的标志如下:

标志 说明
-t 表名,sdoverlay 之一。
-ip 要查询的 IP 地址,默认 127.0.0.1。
-net 目标网络 ID。
-port 目标端口,默认 2000。
-a join/leave 网络。
-v 启用 verbose 输出。

补充(来自当前源码):现在的 main.go 还实现了 README 未收录的 -r 标志(perform remediation deleting orphan entries),可在发现孤儿条目后交互式确认后通过 deleteentry 接口将其删除;删除前会明确提示“this operation is irreversible”并要求输入 Yes 才执行。

5.1 关于 -a 标志的关键注意事项(原文档 NOTE)

  • 默认情况下工具不会尝试 join 网络。这符合“不改变诊断客户端运行时节点状态”的设计意图,因此对运行中的 daemon 执行 diagnosticClient 是安全的——它只会转储当前状态;
  • 相反,在容器化版本中使用 diagnosticClient必须-a,否则会取回空结果;
  • 而对已加载的 daemon 使用 -a 会产生副作用:leave network 会切断该 daemon 的数据路径。

源码中对此有硬保护:若未设置 DIND_CLIENT 环境变量却带了 -a,客户端会直接 Fatal 退出并提示移除该标志(见 main.go);Dockerfile.dind 正是通过 ENV DIND_CLIENT=true 解锁该标志,并把 daemon.json(内容为 {"debug": true, "network-diagnostic-port": 2000})拷贝为容器内的 /etc/docker/daemon.json

5.2 典型用法示例(原文档 Examples)

记得使用完整网络 ID,可用 docker network ls --no-trunc 快速获取。

服务发现与负载均衡:

$ diagnosticClient -t sd -v -net n8a8ie6tb3wr2e260vxj8ncy4 -a

Overlay 网络:

$ diagnosticClient -port 2001 -t overlay -v -net n8a8ie6tb3wr2e260vxj8ncy4 -a

-t sd 对应转储 endpoint_table-t overlay 对应转储 overlay_peer_table(见 main.go 的 switch 分支)。工具会解码每条记录的 base64 值(sd 表解析为 libnetwork.EndpointRecordoverlay 表解析为 overlay.PeerRecord),并把 owner 不在当前网络 peer 集合中的条目标记为孤儿发出 Warn。

六、容器化版本的完整调试流程

容器化 CLI 基于 17.12 引擎,需要以 privileged 模式运行。

NOTE(原文档强调):表操作具有 ownership 语义,因此在诊断容器处于 Swarm 期间,任何 create entry 操作都会保持持久。

流程如下:

  1. 确保运行诊断客户端的节点不属于 Swarm,若属于则先执行 docker swarm leave -f

  2. 启动容器:

    $ docker container run --name net-diagnostic -d --privileged --network host dockereng/network-diagnostic:17.12-dind
    
  3. 通过 docker exec -it <container-ID> sh 进入容器,启动其中内置的诊断服务器:

    $ kill -HUP 1
    

    (向 PID 1 的 dind 内 dockerd 发 HUP,触发其加载容器内的 daemon.json,从而在 2000 端口启动诊断服务器;该容器镜像定义见 Dockerfile.dind,纯客户端镜像定义见 Dockerfile.client,基于 alpine + curl,ENTRYPOINTdiagnosticClient。)

  4. 将诊断容器加入 Swarm,然后在容器内运行诊断 CLI:

    $ ./diagnosticClient <flags>...
    
  5. 调试结束后,离开 Swarm 并停止容器。

七、使用建议小结

结合原文档警示与源码实现,可归纳出几条实践原则:

  1. 临时性:诊断端口只应在排查期间打开,排查完立即从 daemon.json 移除配置并 reload;
  2. 每节点操作:Swarm 场景下启用/关闭需要对每个参与节点执行;
  3. 只读优先:默认不加 -a 的客户端是纯只读的,可安全地对运行中 daemon 执行;一旦使用写入类端点(createentry/updateentry/deleteentry)或 -a-r,就要意识到 ownership 持久性与删除不可逆这两点;
  4. 完整网络 ID:所有 nid 参数都必须使用非截断的完整 ID,否则查询会得到空 peer 列表;
  5. 输出自动化:脚本化采集时优先使用 &json 参数,响应结构稳定(message + details),便于程序解析。

相关源码入口:诊断服务器 daemon/libnetwork/diagnostic/server.go、响应类型 daemon/libnetwork/diagnostic/types.go、客户端 daemon/libnetwork/cmd/diagnostic/main.go、热加载逻辑 daemon/reload.go、配置项定义 daemon/command/config.go

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.12 K
2.72 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
528
588
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
906
1.83 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
854
1.34 K
docsdocs
暂无描述
Markdown
891
5.78 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.53 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.34 K
1.45 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
987
506
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
540
384