Cilium Hubble Relay 本地端口转发:从 kubectl 手动操作到 Hubble CLI `-P` 自动转发的完整实践
2026/9/14 12:15:26 网站建设 项目流程

Cilium Hubble Relay 本地端口转发:从 kubectl 手动操作到 Hubble CLI-P自动转发的完整实践

【免费下载链接】ciliumeBPF-based Networking, Security, and Observability项目地址: https://gitcode.com/GitHub_Trending/ci/cilium

在 Cilium 集群中,Hubble Relay 服务将各节点 Cilium agent 的流量观测数据汇聚为集群级 API,但该服务通常只暴露给集群内部。Documentation/observability/hubble/port-forward.rst这份文档正是为了解决“本地如何访问 Hubble Relay”这一具体问题:它介绍了 Hubble CLI 的-P--port-forward)标志自动转发机制,以及cilium hubble port-forwardkubectl port-forward两种手动建立本地通道(端口 4245)的方式。读完本文,你将掌握三种端口转发方案的命令细节与适用场景,并理解从 Cilium CLI 到 Hubble CLI 的完整源码调用链,能够独立排查本地访问 Relay 失败的问题。

为什么需要端口转发

从 Hubble 的整体架构看(见 Documentation/observability/hubble/index.rst):默认情况下 Hubble API 只运行在单个节点上,Hubble CLI 通过本地 Unix Domain Socket 查询本机 agent;部署 Hubble Relay 后,网络可视范围扩展到整个集群乃至 ClusterMesh 场景,此时 Hubble CLI(hubble)需要连接 Hubble Relay 服务才能获取集群级数据。

Hubble Relay 在 Kubernetes 中是一个 Service,其端点地址(如hubble-relay.kube-system.svc)通常只能从集群网络内部解析和访问。要让运行在本地的hubble命令连上它,最通用的手段就是把 Relay 服务的 80 端口(其首个配置端口)映射到本机的 4245 端口——这也是 Hubble 生态约定的 Relay 本地端口,在源码hubble/pkg/defaults/defaults.go中可以看到默认服务地址即localhost:4245

// hubble/pkg/defaults/defaults.go ServerAddress = "localhost:4245"

方式一:手动端口转发(Cilium CLI)

按照原文档,你可以直接使用 Cilium CLI 建立转发通道:

$ cilium hubble port-forward ℹ️ Hubble Relay is available at 127.0.0.1:4245

该命令的行为在 cilium-cli/cli/hubble.go 中定义(newCmdPortForwardCommand,第 32–56 行):

  • 命令注册在cilium hubble子命令组下,短描述为 “Forward the relay port to the local machine”;
  • 提供一个--port-forward整型标志,默认值 4245,帮助文案明确说明 “0 will select a random port”(传 0 则由系统随机分配本地端口);
  • 通过signal.NotifyContext监听SIGINT/SIGKILL,因此按Ctrl+C即可干净地退出转发;
  • 实际执行委托给 cilium-cli/hubble/relay.go 中的RelayPortForwardCommand

RelayPortForwardCommand的核心实现只有几行,但把整条链路的语义都交代清楚了:

// cilium-cli/hubble/relay.go func (p *Parameters) RelayPortForwardCommand(ctx context.Context, k8sClient *k8s.Client) error { // default to first port configured on the service when svcPort is set to 0 res, err := k8sClient.PortForwardService(ctx, p.Namespace, "hubble-relay", int32(p.PortForward), 0) if err != nil { return fmt.Errorf("failed to port forward: %w", err) } p.Log("ℹ️ Hubble Relay is available at 127.0.0.1:%d", res.ForwardedPort.Local) <-ctx.Done() return nil }

其中几个值得注意的实现细节(见 cilium-cli/k8s/dialer.go 第 18–24 行):

  • 固定转发目标为指定命名空间下的hubble-relayService(命名空间取自全局-n/--namespace参数,默认为kube-system);
  • localPort传 0 时选择随机本地端口;svcPort传 0 时使用 Service 上配置的第一个端口——这正是文档中4245:80之所以不用写死的原因,只要 Relay Service 首个端口是 80 即可;
  • 转发在后台 goroutine 中执行,取消 context 即可停止转发;
  • 成功后打印127.0.0.1:<本地端口>,端口以实际转发结果为准(随机端口场景下可能不是 4245)。

方式二:手动端口转发(kubectl)

不依赖 Cilium CLI 时,原文档给出等价的原生 kubectl 命令:

$ kubectl -n kube-system port-forward service/hubble-relay 4245:80 Forwarding from 127.0.0.1:4245 -> 4245 Forwarding from [::1]:4245 -> 4245

要点:

  • -n kube-system指定 Hubble 所在命名空间,与 Cilium CLI 的全局-n参数语义一致(-P模式下 Hubble CLI 的--kube-namespace默认值同样是kube-system);
  • 4245:80表示把本地 4245 端口映射到hubble-relayService 的 80 端口,即hubble-relayService 的第一个配置端口;
  • 输出中同时列出 IPv4(127.0.0.1:4245)和 IPv6([::1]:4245)两条转发规则,说明本地回环两种地址族均可访问。

方式三:Hubble CLI 的-P标志(自动转发)

三种方式中最省事的,是在 Hubble 命令上直接加-P--port-forward)标志,由 Hubble CLI 自行建立到 Relay Pod 的转发通道,无需先起一个手动转发进程。例如:

# 列出集群流量(等价于先 cilium hubble port-forward 再 hubble observe) $ hubble observe -P # 查询 Relay/节点状态 $ hubble status -P $ hubble list nodes -P

-P及一组配套标志在 hubble/cmd/common/config/flags.go 的initServerFlags中统一注册,完整参数如下:

标志类型/默认值作用
-P, --port-forwardbool,默认false自动把 relay 端口转发到本机。源码注释:“Analoguous to running: 'cilium hubble port-forward'.”
--port-forward-portuint16,默认4245本地转发端口;设为0时随机选择端口。仅在--port-forward开启时生效
--kube-contextstring,默认空Kubernetes 配置上下文。仅在--port-forward开启时生效
--kube-namespacestring,默认kube-systemCilium/Hubble 所在命名空间。仅在--port-forward开启时生效
--kubeconfigstring,默认空kubeconfig 文件路径。仅在--kube-namespace同级条件生效,即仅--port-forward时考虑
--serverstring,默认localhost:4245Hubble 服务器地址;当提供--port-forward--input-file时被忽略

这些描述与hubble observe的帮助输出(hubble/cmd/observe_help.txt 第 156–162 行)完全一致,可直接作为参数速查表。

源码链路:-P是如何工作的

Hubble CLI 的连接创建逻辑集中在 hubble/cmd/common/conn/conn.go 的NewWithFlags(第 127–157 行):

func NewWithFlags(ctx context.Context, vp *viper.Viper) (*grpc.ClientConn, error) { server := vp.GetString(config.KeyServer) if vp.GetBool(config.KeyPortForward) { kubeContext := vp.GetString(config.KeyKubeContext) kubeconfig := vp.GetString(config.KeyKubeconfig) kubeNamespace := vp.GetString(config.KeyKubeNamespace) localPort := vp.GetUint16(config.KeyPortForwardPort) pf, err := newPortForwarder(kubeContext, kubeconfig) // ... // default to first port configured on the service when svcPort is set to 0 res, err := pf.PortForwardService(ctx, kubeNamespace, "hubble-relay", int32(localPort), 0) // ... server = fmt.Sprintf("127.0.0.1:%d", res.ForwardedPort.Local) } conn, err := New(server) // ... }

从源码结构看,-P的工作流程是:

  1. --kube-context/--kubeconfig构造 Kubernetes clientset(NewK8sClient,第 159–179 行);
  2. --kube-namespace(默认kube-system)中的hubble-relayService 为目标执行端口转发,svcPort传 0 即取 Service 首个端口,与 Cilium CLI 的实现策略完全相同;
  3. 把 gRPC 目标地址改写为127.0.0.1:<实际本地端口>,再调用New建立普通 gRPC 连接。

这也解释了为什么--server-P模式下被“忽略”:服务器地址在转发建立后由本地转发结果动态决定,而非用户输入。

三种方式对比与选择建议

方式命令特点
Cilium CLI 手动转发cilium hubble port-forward端口由--port-forward控制(默认 4245,0 为随机);独立前台进程,转发一次、多命令复用;Ctrl+C停止
kubectl 手动转发kubectl -n kube-system port-forward service/hubble-relay 4245:80不依赖 Cilium CLI,只要求 kubectl 可达集群;显式指定 4245:80 映射
Hubble CLI-Phubble <cmd> -P一条命令完成“转发 + 查询”,转发随命令生命周期存在;支持--kube-namespace/--kube-context/--kubeconfig定位集群

实践上的取舍:

  • 临时查一次状态hubble statushubble list flows):直接用-P最简洁;
  • 持续观察多条流hubble observe长时间运行):可以先cilium hubble port-forward保持一个长连接,再运行不带-Phubble observe连接localhost:4245,避免每次查询都重建转发;
  • 本机没有 Cilium CLI、只有 kubectl:用方式二,注意端口映射写成4245:80,即本地 4245 到 Service 80 端口。

排错要点

结合上述源码实现,本地访问 Relay 失败时可按以下顺序排查:

  1. 命名空间不对-P模式默认在kube-system中查找hubble-relay,若 Hubble 安装在其他命名空间,需显式传--kube-namespace <ns>(kubectl 方式则对应-n <ns>);
  2. 本地端口冲突:4245 被占用时,cilium hubble port-forward --port-forward 0hubble observe -P --port-forward-port 0会随机选一个端口,注意以命令输出/转发结果中的实际端口为准(源码中日志打印的是res.ForwardedPort.Local,即真实本地端口);
  3. 集群不可达-P依赖 kubeconfig 上下文,多集群环境需确认--kube-context/--kubeconfig指向的目标集群中确实部署了 Hubble Relay(可通过hubble status -P验证 Relay 与各 agent 的连通状态);
  4. 确认 Service 首端口为 80:Cilium CLI 与 Hubble CLI 均按“Service 首个配置端口”转发,若 Relay Service 的端口定义被定制过,kubectl 方式的4245:80需相应调整目标端口。

小结

port-forward.rst文档给出的三种访问方式——hubble -P自动转发、cilium hubble port-forward手动转发、kubectl port-forward原生转发——共享同一套底层实现:在kube-system(或指定命名空间)中对hubble-relayService 建立本地端口映射,并以 Service 首个端口(80)作为目标,本地默认落在 4245。理解了 cilium-cli/k8s/dialer.go、hubble/cmd/common/conn/conn.go 中的PortForwardService调用链和 hubble/cmd/common/config/flags.go 中的参数定义后,你可以按场景自由选择方式,并在端口冲突、命名空间差异等情况下快速定位问题。Hubble Relay 打通本地访问通道后,即可结合 hubble-cli.rst 中的observe/list/status等命令,以及 setup.rst 中 Relay 的部署与 TLS 配置,完成集群级流量观测的完整闭环。

【免费下载链接】ciliumeBPF-based Networking, Security, and Observability项目地址: https://gitcode.com/GitHub_Trending/ci/cilium

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询