k8s 集群中 Golang pprof 工具的使用

大家好啊,我是码财同行。

1. pprof 工具

熟悉 Golang 的同学都知道,这门语言做的比较好的一点就是工程化能力,周边工具支持的还算不错。Golang 中的 pprof 就是一个非常重要且实用的定位问题的好工具。

当我们在浏览器中访问 pprof 监听的 http 地址时,会有很多 Go 程序对应的信息展示出来,包括cpu、内存分配及占用、协程等,如下图的样子:

通过pprof 提供的信息,我们还能利用工具分析更详细的信息,比如火焰图:

这么强大的工具,自然我们也希望在各种环境中都能很方便的使用。

那么问题来了

最近查问题,需要访问我们部署在 k8s 集群上的服务器进程,查看进程上 pprof 提供的数据。

2. k8s 集群中的 pprof

有用过 k8s 的同学应该清楚,k8s 集群中服务器提供的服务都是属于内部的,包括我们要用的 pprof,是不能直接对外的。

如果要访问 k8s 内部提供的服务,可以有两种方式:

  1. NodePort 做端口映射,将内部的端口映射到外部可以访问的端口。
  2. Ingress 类似 Ngix 的代理。

这两种方式都需要提前配置好,然后由 k8s 暴露出来。

然而,我们集群中的 pprof 只是监听了一个地址,没有特殊的做 NodePort 或者 Ingress 配置,如果再去增加配置,然后重新部署,会比较麻烦。

一开始我的想法是 login 到 k8s 的pod 内部,在容器里 download 一个 Go,然后 go tool pprof 本地端口,直接本地调试,但是不如 web 页面直观。

后来通过 AI 及搜索,发现原来可以通过 kubectl 提供的 port-forward 做端口转发,直接在外部做代理。

用图来表示这个过程,就是和 k8s 集群的 API server 通信,来转发请求:

具体来讲,其实是由 kubectl 命令行工具通过 https 协议和 k8s 集群的 API server 通信,API server 将消息转发到特定 Pod 所在机器上的 Kubelet 进程,再由 kubelet 转发给 pod 内的容器进程。

比如我在 k8s 集群外的一台 IP 为 a.b.c.d 的机器上做一个转发代理,就可以这样

sql 复制代码
$ kubectl port-forward --address 0.0.0.0 game-miscserver-0 :65334
Forwarding from 0.0.0.0:40565 -> 65334

命令行中 65334 是目标进程(game-miscserver-0)监听的 pprof 端口,而 kubectl 会随机分配一个本地端口(也可以指定)来代理 pprof 的访问。

这样就可以在浏览器上访问机器 a.b.c.d 上的 40565 端口了:

bash 复制代码
http://a.b.c.d:40565/debug/pprof

这个地址的输出就是 pprof 的输出,非常方便快捷。

不得不说 k8s 集群的 API server 设计得还是蛮不错的,很多能想到的功能它都支持。

3. 扩展

除了实时访问 pprof,有的开源项目可以支持类似 metrics 一样定时收集 pprof 数据存入时序数据库如 clickhouse 等,这样我们就能收集服务器进程的历史 pprof 数据并在之后查看了。

大概流程如下:

这个想法我觉得挺好,目前还没在项目中实施,有机会会尝试一下。

相关推荐
追逐时光者8 小时前
一款开源、现代化的 WinForm UI 控件库
后端·.net
花月C9 小时前
个性化推荐:基于用户的协同过滤算法
开发语言·后端·算法·近邻算法
cci10 小时前
还在用conda?,试试uv,提高包的安装速度
后端
cci10 小时前
设备每次插入Linux识别的串口不一样?试试udev!
后端
9ilk10 小时前
【C++】--- C++11
开发语言·c++·笔记·后端
码事漫谈12 小时前
VSCode CMake Tools 功能解析、流程与最佳实践介绍
后端
一条懒鱼66612 小时前
K8S-特殊容器
云原生·容器·kubernetes
火云牌神12 小时前
本地大模型编程实战(38)实现一个通用的大模型客户端
人工智能·后端
码事漫谈12 小时前
从C++/MFC到CEF与TypeScript的桌面架构演进
后端
冰块的旅行13 小时前
magic-api使用
后端