- 云原生
- 开发工具
- 微服务
- 网络
【免费下载链接】telepresence
Local development against a remote Kubernetes or OpenShift cluster
导读
本指南面向需要在本地调试 Telepresence 的 Docker 网络插件 teleroute 的开发者。Telepresence 在--docker模式下会把守护进程运行在容器中,而 teleroute 正是负责让该容器获得集群网络连通能力的关键组件(详见 Docker 使用说明)。读完本文,你将掌握:如何将 Telepresence 客户端指向 debug 版插件、如何用一条make debug构建并启用调试插件,以及如何借助runc实时跟踪插件日志并定位 gRPC 连接、双栈路由等常见问题。
背景:teleroute 是什么,为什么需要调试它
teleroute 是 Telepresence 以 Docker Engine 插件形式分发的网络驱动(network driver)。在 Docker 模式下,telepresence connect --docker会在容器中启动守护进程,而 teleroute 插件为守护进程容器创建网络、加入端点并注入通往远端 Kubernetes 集群的路由。它对外暴露的是标准的docker.networkdriver/1.0插件接口,因此任何 Docker 网络故障(容器无法访问集群 Service、双栈集群 IPv6 路由失效等)都可以而且应该在插件层面排查。
从仓库源码看,插件的完整形态包括:
- 插件配置:声明入口
/bin/docker-network-teleroute、Unix socketteleroute.sock、网络接口docker.networkdriver/1.0,并声明需要CAP_NET_ADMIN能力且使用 host 网络,同时暴露一个可在创建插件时修改的DEBUG环境变量。 - 插件主程序:创建
/var/log/teleroute.log日志文件,并根据DEBUG环境变量决定日志级别(slog.LevelInfo或slog.LevelDebug),随后以 Unix socket 方式启动网络驱动服务。 - 网络驱动实现:实现
CreateNetwork、CreateEndpoint、Join、Leave等 Docker libnetwork 驱动回调。 - 驱动与守护进程的交互:通过 gRPC 与守护进程的 teleroute 服务通信,协议定义在 rpc/teleroute/service.proto。
调试这类插件比调试普通进程麻烦:它不是常规容器或二进制,而是由 Docker Engine 以插件形式管理,日志与运行状态都藏在插件内部。下面按官方开发文档的流程逐步展开。
第一步:让客户端使用 debug 版插件
在开始调试前,先要让 Telepresence 客户端不再检查/拉取最新版插件,而是使用本地的 debug 构建版本。方法是在config.yml中加入如下片段:
intercept: teleroute: tag: debug配置文件的存放位置依操作系统而定:
- Linux:
~/.config/telepresence/config.yml - macOS:
"$HOME/Library/Application Support/telepresence/config.yml"
这里的intercept.teleroute.tag告诉客户端采用 tag 为debug的插件,而不是默认的最新发布版本。这样后续make debug构建出的插件才能被客户端实际加载。如果跳过这一步,客户端仍会去寻找远端 registry 的正式版插件,你调试的本地代码根本不会生效。
第二步:构建并启用调试插件
在cmd/teleroute目录下执行:
$ make debug该目标“既构建又启用插件”,它并不是简单地编译二进制,而是完整走一遍插件的打包与注册流程。拆解 Makefile 可以看到它的实际步骤:
rootfs:使用docker buildx build --platform linux/$(PLUGIN_ARCH)依据 Dockerfile 构建插件根文件系统(rootfs),并将 config.json 一并拷贝到build-output目录。Dockerfile 采用多阶段构建:先在golang:alpine中交叉编译出/bin/docker-network-teleroute,再将其放进一个仅含 bash 的alpine运行时镜像。docker plugin create $(PLUGIN_DEV_IMAGE)-debug $(BUILD_DIR):用刚生成的 rootfs 创建名为ghcr.io/telepresenceio/teleroute-<arch>-debug的本地插件。docker plugin set ... DEBUG=true:这是关键一步——通过 config.json 中声明的可设置环境变量DEBUG把调试开关打开,使插件以 debug 日志级别运行。docker plugin enable ...:启用插件,让 Docker Engine 可以调用它。
Makefile 顶部的变量默认值也值得注意:PLUGIN_ARCH取自go env GOARCH,PLUGIN_REGISTRY默认为ghcr.io/telepresenceio,PLUGIN_NAME为teleroute,因此默认调试插件全名是ghcr.io/telepresenceio/teleroute-<arch>-debug。如果你需要为其他架构构建,可以覆盖PLUGIN_ARCH。
为什么 debug 流程要专门设置DEBUG=true?看 main.go 的日志初始化逻辑就清楚了:主程序启动时读取DEBUG环境变量,解析为布尔值后决定日志级别——false(默认)时仅记录slog.LevelInfo及以上,true时才会输出slog.LevelDebug的详细调试信息。插件驱动中的clog.Debug/clog.Debugf调用(如CreateNetwork、Join时的参数打印)只有在 debug 级别才会落到日志中,这正是排障时需要的信息。
第三步:用 runc 实时跟踪插件日志
插件启用后,日志并不在普通容器里,因此要用runc直接进入插件运行时来读取日志文件:
sudo runc --root /run/docker/runtime-runc/plugins.moby exec $(docker plugin list --no-trunc -f capability=networkdriver -f enabled=true -q) tail -n 400 -f /var/log/teleroute.log这条命令分两部分理解:
docker plugin list --no-trunc -f capability=networkdriver -f enabled=true -q:筛选出当前已启用的网络驱动插件,返回其 ID(配合--no-trunc保证是完整 ID,-q只输出 ID 供脚本使用)。实际运行时也可以直接替换为插件 ID 或名称。runc --root /run/docker/runtime-runc/plugins.moby exec <plugin-id> tail -n 400 -f /var/log/teleroute.log:以runc进入插件运行时的根文件系统,先输出/var/log/teleroute.log末尾 400 行,再持续-f跟踪新增日志。
日志文件路径与格式由 main.go 决定:插件启动时通过os.Create(pluginLog)创建(或截断)/var/log/teleroute.log,并使用clog+slog写入,时间格式为15:04:05.0000。因此tail -f能实时看到CreateNetwork、Join、Leave等每次驱动回调的执行痕迹。
调试时的常见排查点与源码依据
拿到 debug 日志后,可以结合以下源码热点快速定位问题:
1. 插件是否连上了守护进程的 gRPC 服务
插件与守护进程之间通过 gRPC 通信(协议见 rpc/teleroute/service.proto,服务名为Teleroute,包含Connect、CreateEndpoint、RemoveEndpoint、Join、Leave五个 RPC)。CreateNetwork时驱动会解析host、port两个必需选项(options.go),然后以backoff重试方式发起Connect流式调用(network.go):每 50ms 重试一次、最多 20 次,只有收到codes.Unavailable才继续重试。如果日志中出现持续的重试或unable to create gRPC connection to daemon,说明host/port配置不正确或守护进程的 teleroute 服务未启动。连接建立成功后,日志会打出Connected to <name> version <version>。
2. 双栈(dual-stack)集群的路由下一跳是否正确
Join时驱动会把守护进程返回的路由转换为 libnetwork 的静态路由(staticRoutesFromResponse)。这里的逻辑是:IPv4 路由使用守护进程的 IPv4 地址作为下一跳(via_ip_v4),IPv6 路由使用 IPv6 地址(via_ip_v6);若某地址族没有对应下一跳,则退化为直连路由(RouteType 1)而不是错误地借用另一族的地址;老版本守护进程只返回单一via字段时,则回退使用该字段以保证向后兼容。
这一点有专门的单元测试佐证(driver/network_test.go):
TestStaticRoutesFromResponse_dualStack:验证混合地址族路由集下每条路由都拿到本族的下一跳;TestStaticRoutesFromResponse_missingFamilyVia:验证某族无下一跳时生成直连路由而非错配下一跳;TestStaticRoutesFromResponse_legacyVia:验证老守护进程的单一via回退路径。
如果你在双栈集群中遇到“容器能通 IPv4 但 IPv6 路由失效”,应重点检查Join日志及这些字段的解析。
3. 网络选项是否完整
CreateNetwork要求 Docker 网络在com.docker.network.generic中携带host(守护进程所在默认桥接网络上的 IP)与port(守护进程 teleroute 服务的端口)。缺少任一必需项会直接报option "host" is required之类的错误(options.go);遇到不认识的选项键会报illegal option。排查时先确认创建该网络的调用是否正确传入了这两个值。
4. 网络清理与重建
客户端侧在连接时会调用teleroute.CreateNetwork创建插件网络,失败且网络已存在时尝试重建,还会执行teleroute.NetworkGC垃圾回收残留网络(pkg/client/cli/connect/connector.go)。如果调试过程中反复启停插件,残留的旧网络可能导致“network already exists”类问题,此时先停用/删除旧的 debug 插件再重新make debug,并确认客户端配置的tag: debug已生效。
调试流程速览
把上面的步骤串起来,一次典型的调试会话如下:
# 1. 修改 ~/.config/telepresence/config.yml(Linux)或 # "$HOME/Library/Application Support/telepresence/config.yml"(macOS) # 加入 intercept.teleroute.tag: debug # 2. 在 cmd/teleroute 下构建并启用 debug 插件 $ make debug # 3. 启动/重连 telepresence(--docker 模式) $ telepresence connect --docker # 4. 跟踪插件日志 $ sudo runc --root /run/docker/runtime-runc/plugins.moby exec \ $(docker plugin list --no-trunc -f capability=networkdriver -f enabled=true -q) \ tail -n 400 -f /var/log/teleroute.log调试完成后,如需恢复到正式版本,将配置中的intercept.teleroute.tag移除或改回正式 tag,并执行make的正式构建/推送流程(make push,见 Makefile 中的push、push-latest目标,其按PLUGIN_VERSION是否为x.y.z语义版本决定是否打latest标签)。
小结
teleroute 的调试链路并不复杂,核心就三步:用config.yml的intercept.teleroute.tag: debug把客户端指向本地插件、用make debug构建并启用带DEBUG=true的插件、用runc实时跟踪/var/log/teleroute.log。理解插件的config.json、主程序日志初始化、gRPC 连接重试与双栈路由转换逻辑,能让你从“看到日志”快速进阶到“看懂日志、定位根因”,从而高效解决 Docker 模式下 Telepresence 的网络连通问题。
- 云原生
- 开发工具
- 微服务
- 网络
【免费下载链接】telepresence
Local development against a remote Kubernetes or OpenShift cluster
相关推荐
工控安全與物聯網資安:TW-Security-and-CTF-Resource中的特殊領域學習指南
工控安全與物聯網資安:TW Security and CTF Resource中的特殊領域學習指南 在數位轉型的浪潮下,工業控制系統(ICS)和物聯網(IoT)
文档网络安全知识库突破插件开发瓶颈:notepad--断点调试与日志系统实战指南
突破插件开发瓶颈:notepad 断点调试与日志系统实战指南 你是否在开发notepad 插件时遇到调试困难、日志信息混乱的问题?本文将从插件架构解析、断点调试
桌面应用Flannel网络插件深度排障指南
Flannel网络插件深度排障指南 前言 Flannel作为Kubernetes生态中广泛使用的CNI网络插件,在实际部署过程中可能会遇到各种网络连接问题。本文
云原生网络
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考