(文章翻译自https://github.com/fcrisciani/libnetwork/blob/be91c3ed62817bc3899ebe154eea07c573395b0c/cmd/diagnostic/README.md)
Docker CE 从17.12版本开始加入网络调试的工具,使用这个工具可以帮助排查Linux上的docker overlay网络以及swarm service的问题。当开启网络调试选项时,Docker daemon会在指定的端口启动一个网络诊断的服务以提供网络诊断信息的获取。这个调试工具只建议在需要排查特定的网络问题时开启,不应该一直开启着这个调试服务。
被保存在数据库中的网络的信息可以通过诊断的API获取到,目前这个数据库中主要包含了overlay网络的数据,以及服务发现的数据。
Docker目前也提供了一个预览版的CLI的集成工具,这个工具通过访问Docker暴露的诊断API来查询和控制网络的接口,但这个工具的实现和命令选项并没有完全确定下来,后续可能随时会改变。
目前可以以下两种方式来使用这个调试工具:
- 只有客户端的工具的镜像:
dockereng/network-diagnostic:onlyclient
- Docker in docker的镜像:
dockereng/network-diagnostic:17.12-dind
Docker in docker的方式提供的工具是为了在集群版本小于17.12中使用,利用这个镜像中的Docker去获取到集群的网络信息。
打开诊断服务
这个工具目前只能在Linux上的Docker节点使用,通过下面的步骤打开:
-
通过在
/etc/docker/daemon.json
中配置network-diagnostic-port
,在节点上设置一个空闲的端口分配给诊断服务:"network-diagnostic-port": <port>
-
使用下面这个命令找到dockerd的进程id(PID):
$ ps aux |grep dockerd | grep -v grep
-
不需要重启Docker daemon,直接通过发送HUP信号给刚才找到的进程ID来reload配置:
kill -HUP <pid-of-dockerd>
如果Docker是用systemd启动的,上面这一步也可以直接使用systemctl reload docker
来reload配置。reload之后可以在docker的日志看到:
Starting the diagnostic server listening on <port> for commands
关闭诊断服务
- 从
/etc/docker/daemon.json
中移除掉network-diagnostic-port
的配置 - 像上面一样找到dockerd的进程ID
- 像上面一样reload下dockerd的配置 reload后可以看到dockerd打出如下日志:
Disabling the diagnostic server
诊断API
诊断的API通过http暴露到上面指定的端口上,通过HTTP请求访问这个端口来访问这个诊断API,下面的命令中我们假定定义的端口是20000
。
例如:
获取API帮助(API列表):
$ curl localhost:2000/help
OK
/updateentry
/getentry
/gettable
/leavenetwork
/createentry
/help
/clusterpeers
/ready
/joinnetwork
/deleteentry
/networkpeers
/
/join
加入或离开网络集群
$ curl localhost:2000/join?members=ip1,ip2,...
$ curl localhost:2000/leave?members=ip1,ip2,...
ip1
, ip2
, ... 这些是swarm集群中的其他节点IP
添加或者删除掉一个网络
$ curl localhost:2000/joinnetwork?nid=<network id>
$ curl localhost:2000/leavenetwork?nid=<network id>
network id
可以在swarm集群的manager节点中通过docker network ls --no-trunc
看到,这里必须使用完整的network id
罗列集群的peer
$ curl localhost:2000/clusterpeers
罗列拥有某个网络的节点列表
$ curl localhost:2000/networkpeers?nid=<network id>
network id
可以在swarm集群的manager节点中通过docker network ls --no-trunc
看到,这里必须使用完整的network id
Dump 网络信息数据库的表
这些表包含 endpoint_table
和overlay_peer_table
,overlay_peer_table
中包含了网络的转发信息。 endpoint_table
包含了服务发现的信息。
$ curl localhost:2000/gettable?nid=<network id>&tname=<table name>
修改指定的数据库表
这些表包含 endpoint_table
和overlay_peer_table
$ curl localhost:2000/<method>?nid=<network id>&tname=<table name>&key=<key>[&value=<value>]
注意:这里只是更新了执行的节点上的表,这意味着在这个节点同步集群之前会一直保持着这个更新的值。
使用诊断的客户端来访问网络信息
这个工具的实现和命令选项并没有完全确定下来,后续可能随时会改变。 这个工具可以直接通过执行一个的镜像中的diagnosticClient
可执行文件来调用网络信息。
docker run --net host dockereng/network-diagnostic:onlyclient -v -net <full network id> -t sd
下面是支持的命令:
选项 | 描述 |
---|---|
-t | 访问的table的名称 sd 或 overlay . |
-ip | 要访问的API的IP地址. 默认是 127.0.0.1. |
-net | The target network ID. |
-port | 要访问的API的端口. 默认是 2000 |
-v | 显示verbose级别日志 |
Docker in docker版本的诊断工具
这个命令行工具内置了docker 17.12的docker daemon,并且需要以privileged模式运行。
注意: 每个更新操作例如(create entry)只是更新了执行的节点上本地的表,这意味着在这个节点同步集群之前会一直保持着这个更新的值。
- 保证诊断的节点不在集群中,如果已经加入到了一个集群中,可以
docker swarm leave -f
离开集群 -
可以使用下面这个命令来启动这个容器:
$ docker container run --name net-diagnostic -d --privileged --network host dockereng/network-diagnostic:17.12-dind
-
通过
docker exec -it <container-ID> sh
进入到这个容器中,使用下面这个命令启动诊断服务器:$ kill -HUP 1
-
把诊断容器的docker daemon加入到已有的docker swarm集群中,然后再容器中执行诊断的可执行工具。
$ ./diagnosticClient <flags>...
-
完成诊断后,离开现有的这个集群,并停止这个诊断容器。
示例:
下面的这些命令会dump下来服务发现的表以及验证和集群别的节点的关系:
注意: 使用完整的网络ID,网络ID可以方便的通过docker network ls --no-trunc
获取到。
服务发现和负载均衡:
$ diagnostiClient -c sd -v -net n8a8ie6tb3wr2e260vxj8ncy4
Overlay网络:
$ diagnostiClient -port 2001 -c overlay -v -net n8a8ie6tb3wr2e260vxj8ncy4