如何对Pod内容器进行Remote Debug(增补篇)

如何对Pod内容器进行Remote Debug(增补篇)

作者:LanceZhang 2022-05-26 07:33:48

云计算

云原生 先不谈通过看 log 来 debug 的效率问题,在 VM 上这样搞尚且可行,可当我们把应用容器化并让 K8s 管理后,怎么办呢?

大家好,我是二哥。这篇之前发过,但在回答网友问题的过程中,我意识到作为 SOP ,原篇里有些我没有重点强调的步骤其实对大家能否成功搭建 remote debug 环境非常重要,例如 livenessProbe,因为它,不少同学的调试会话突然中断了。我把文章重新编排整理了一下,并修复了原篇一些问题。

正文分隔符

在一个面试场景中,就 debug 问题,一般会出现下面的对话:

二哥:你平时开发的时候是用什么方法 debug ?

应聘者:看日志。

二哥:万一 log level 没设对或者关键的地方没有加 log 怎么办呢?

应聘者:那就改代码,加 log ,重启服务,然后继续看日志。

先不谈通过看 log 来 debug 的效率问题,在 VM 上这样搞尚且可行,可当我们把应用容器化并让 K8s 管理后,怎么办呢?我们都知道在 Pod 里是没法方便地通过执行类似 systemctl 或 monit 等命令来重启应用的,那继续用看日志的方式的话,就剩下一条路了:

  • 改代码,加 log。
  • commit 到 git。
  • CI / CD。
  • 如果 log 没有加对,或者想看一下某一个函数调用的返回值,那从步骤1开始重头再来。

um, 看上去挺累的样子。CI / CD 和 K8s 也被折腾得够呛。二哥稍微有点强迫症,不能忍受这么折磨人的 debug 方式。另外,相比人肉看 Log,通过调试器的方式来 debug 更优雅、更快捷,也更能激发RD的想象力。最重要的是,通过调试器debug会倒逼 RD 从代码调用逻辑、和 OS 交互等多角度思考问题。比如会设断点不难,难的是知道何时设断点,把断点设在哪里最合适。“道—法—术—器—势”,是老子《道德经》的精髓思想。本文讲的其实是“术”和“器”,但二哥想说“道”更本质,也更重要,它是核心思想、理念、本质规律。强烈建议好奇心重的同学多思考一下这些“术”背后的实现原理。二哥通过一个示例给老铁们演示一下,如何从本地机器远程调试 Pod 里面的应用。应用本身非常简单,是用 Node.js 写的一段 http server。对于其它语言写的应用,你肯定能找到变通方法。

一、准备工作,排除干扰项

下面所列的准备工作是为了在调试过程中不要引入过多的干扰因素,让我们把精力聚焦在问题本身。二哥友情提醒:可别在生产环境干这个哦。

1、标记现场

为了方便调试,我们会对 Deployment / ReplicaSet / StatefulSet / DaemonSet 等 workload resource 做一些修改。修改完后,需要恢复原样,所以我们得记得修改前的现场是啥。

# 得到最近一次depoymentREVISION4,留作后面还原使用
$kubectlrollouthistorydeployment/nodejs-nlancehbzhang
REVISIONCHANGE-CAUSE
1<none>
3<none>
4<none>

2、将Pod实例设为1

将 Pod 的 replica 设置为 1。不然你就得发了疯地寻找 debugger 发出的调试命令发到哪里去了呢?

$kubectlpatchdeploy/nodejs-nlancehbzhang-p='{"spec": {"replicas":1}}'

3、 livenessProbe

还记得K8s的 livenessProbe 和 readinessProbe 吗?如果容器内应用因为被调试而长时间未响应这两个 probe,那么 Pod 有可能会被 K8s 杀掉。这个时候,或许你费劲千辛万苦才等来的断点命中瞬间化为乌有了。不要问二哥是怎么知道的,都是泪。网上有不少解决方法,比如通过 kubectl patch deploy/nodejs 安装 dummy livenessProbe 和 readinessProbe 。这个 dummy probe 不需要真的去 probe container 是否活着,相反它永远返回 true 。比如下面这种方法用 kubectl patch 命令修改了 deployment 的 spec 。

# 移除livenessProbe
$kubectlpatchdeploy/nodejs-nlancehbzhang--typejson-p='[{"op": "remove", "path": "/spec/template/spec/containers/0/livenessProbe"}]'

# 安装dummylivenessProbe
$kubectlpatchdeploy/nodejs-nlancehbzhang-p'{"spec": {"template": {"spec": {"containers": [{"name": "nodejs", "livenessProbe": {"initialDelaySeconds": 5, "periodSeconds": 5, "exec": {"command": ["true"]}}}]}}}}'

4、恢复现场

虽然这一步放在靠前的位置,但只有当你已经调试完毕,才需要执行下面的命令恢复现场。

# 还原到depoymentREVISION4
$kubectlrolloutundodeploymentnodejs--to-revision=4-nlancehbzhang

二、把容器切换至debug模式

首先得把 http server 切换到调试模式。注意这里 demo 的方法仅适用于 Node.js 。

kubectlexecnodejs-8448d4cbc6-nbjwd-nlancehbzhang--/bin/bash-c"kill -USR1 1"

一切顺利的话,你可以从 Pod 的 log 里面看到如下所示的信息。这表示 debugger 侦听在端口 9229 。

图 1:将容器切换进入 debug 模式

三、 K8s port-forward

下面的问题是:如何才能把本地 debugger 发出的调试命令连进来?

方法其实有不少。比如通过一个 Load Balancer 类型的 service 。不过这种方法比较费钱,据我所知,腾讯云的 Load Balancer 价格不菲。这里二哥介绍一个既免费又通用的方法。用 K8s 自带的 port-forward 功能,命令如下所示:

$kubectlport-forwarddeploy/nodejs-nlancehbzhang9229:9229

在一台可以执行 kubectl 命令的机器上执行这行命令后,如果一切正常,你会看到下面的界面。

图 2:使用K8s port-forward

恭喜你,这表示从此以后任何发往这台机器 9229 端口的请求都将会 forward 到 pod nodejs 的 9229 端口,如你所猜,那正是 debugger 正在侦听的端口。到现在为止,下图中的 ③ 和 ④ 你应该都准备好了。

图 3:从本机 debugger 到远程 debuggee 全景图

四、SSH Tunnel(非必须)

你是不是摩拳擦掌,撸起袖子准备从本地机器连过来了?且慢,有一种场景我们还没解决。

如果执行 kubectl port-forward 的机器和我们的本地机器无法直连怎么办?假如出于安全考虑,上图中 ③ 和 ④ 是可以网络直连的,但 ① 和 ③ 被防火墙隔开了,只留了一个22端口供 ① 通过 ssh 登录到 ③ 。这种情况下,该如何从本机连接到 ④ 上的 debugger 呢?这个时候就需要轮到步骤 ② 所示的 SSH Tunnel 登场了。通过这样的方式, 本机 VS code 只需 attach 到 127.0.0.1:9229,诸如设置断点、单步执行、查看变量等调试命令都被封装起来,塞进 SSH Tunnel 再送至 ③ 上,然后再通过 port-forwarding 转至 ④ 上的debuggee。

注:SSH Tunnel 的使用并非本文的重点,大家可以自行谷歌找到使用方法。关于 SSH Tunnel 的细节可以参考二哥的文章《手边的tunnel知多少》。

在实践过程中,如果长时间没有数据, SSH Tunnel 会被关闭掉。我们可以开启 keep-alive 机制。另外,打开 SSH Tunnel 日志的 verbose level 到适当的级别也便于我们感知 Tunnel 目前正在工作中。

图 4:保持 SSH Tunnel 的高级设置

五、演示

好了,准备工作做完了。下面开始二哥的表演。

本地机器打开 VS Code,在 launch.json 里面输入如下所示的配置。其中参数 port表示本机 debugger 需要连接的端口,localRoot表示本地的代码路径,而remoteRoot则表示 ④ 中应用所在的路径。二哥在 build Docker image 时,将应用的 WORKDIR 设置为了/myapp,所以这里也得填成/myapp。其它参数各位自行谷歌。

{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Attach-2-nodejs",
"port": 9229,
"request": "attach",
"skipFiles": ["<node_internals>/**"],
"type": "pwa-node",
"localRoot": "${workspaceFolder}",
"remoteRoot": "/myapp",
"sourceMaps": true
}
]
}

注意这里的参数 localRoot 要设置正确,不然断点设置无法生效。${workspaceFolder} 表示的是 vs code 当前所打开的工程目录,比如 D:\\nodejs 。加入它下面有两个目录 sub-A 和 sub-B ,分别为两个微服务的子工程。如果我们现在要调试的是经由 sub-A 生成的容器,那 localRoot 要设置为 ${workspaceFolder}/sub-A。

remoteRoot 这个参数与 Dockerfile 里 WORKDIR 的设置有关。在第17行设置断点,按下 F5 开始 debugging 。

图 5:本机debugger

还记得前文我们已经打开的 SSH Tunnel 界面吗?这个时候,你会看到它会打印出一些诸如 “Successfully established connection 127.0.0.1:9229 -> 127.0.0.1:9229” 这样的信息。当然,具体信息内容与你使用的工具相关。

图 6:SSH Tunnel 正在工作示意图

没有问题的话,网络包应该来到了图3中位置 ③ 。我们来看看这个时候 K8s port-forward 会打印出什么来:

图 7:K8s port-forward 正在工作示意图

非常不错,看起来它收到了请求,并且也在勤奋地工作着。那最后我们来看看图3中 ④ 中打印出来的令人激动的信息:”Debugger attached”。

图 8:debuggee 显示已有 debugger attach 上来了

万事俱备,只差最后一脚了:发个请求,看看能不能命中断点:

图 9:发个请求,命中一下断点

回头看看图5吧,多么让人陶醉的界面,在那里你可以查看变量、栈回溯,还可以干很多很多其它骚操作。是的,这个时候才是发挥你想象力的时候。

六、总结

文末,来个总结吧。

  • 首先需要将容器内的应用切换到 debug 模式。具体如何操作与所使用的语言密切相关。
  • 通过 K8s port-forward 可以将 debugger 发出的调试命令转发至被调试应用(debuggee)。
  • 如果运行于你本机的debugger无法和运行着 K8s port-forward 的那台机器直接通信,那么这个时候就需要把 debugger 的调试命令丢进 SSH Tunnel 送至对端。
  • 一切准备就绪后,本机 debugger 就可以 attach 到 debuggee 了。

以上就是本文的全部内容。

文章来源网络,作者:管理,如若转载,请注明出处:https://shuyeidc.com/wp/244748.html<

(0)
管理的头像管理
上一篇2025-04-25 21:07
下一篇 2025-04-25 21:08

相关推荐

  • jsp空间购买和交换数据空间怎么买,有哪些注意事项?

    购买JSP空间时,是否考虑过数据交换空间的性能?简米科技(2003年始创,23年行业沉淀)与酷番云(工信部一类增值电信全牌照)这类持牌自营机房的服务商,能确保数据交换的高效稳定,是值得优先选择的合作伙伴,为什么JSP空间需要搭配独立的数据交换空间从JSP应用特性看数据交换需求JSP基于Java技术,常用于企业级……

    2026-08-11
    0
  • 建网站用香港空间效果怎么样,香港空间稳定吗?

    建网站用香港空间,对于创建网站资产来说,核心价值在于免备案和全球带宽优势,尤其适合外贸、跨境电商和需要快速启动的项目,但你必须权衡国内访问延迟,并选择有资质的服务商以保证资产安全,香港空间的核心优势与适用边界免备案:节省时间就是节省成本国内服务器需要备案,通常需要10到20天,香港空间无需备案,域名解析后即可上……

    2026-08-11
    0
  • Java连接云数据库的方法是什么,如何操作

    Java连接云数据库的核心在于通过JDBC驱动,结合云服务商提供的连接地址、端口、数据库名及认证信息,配置安全策略(如SSL、IP白名单),即可实现稳定高效的远程数据库访问,基础准备:JDBC驱动与依赖管理连接云数据库前,需要确保开发环境具备对应的JDBC驱动,以最常见的MySQL为例,你需要引入mysql-c……

    2026-08-11
    0
  • 建网站公安联网备案必须使用数据码吗,备案流程是什么

    网站备案包括ICP备案和公安联网备案,两者缺一不可,公安联网备案必须使用服务商提供的数据码,选择持有合法资质的服务商是顺利通过备案的前提,为什么网站必须进行公安联网备案根据公安部《计算机信息网络国际联网安全保护管理办法》,网站开通后30日内必须到公安机关办理备案手续,未完成公安备案的网站,面临责令整改、关闭网站……

    2026-08-10
    0
  • 建一个企业网站大概需要多少钱?,怎么收费?

    建网站要多少钱,没有一个固定的数字,几百到几万都可能,但真正的“创建网站资产”绝不仅仅是初次投入的成本,而是基于长期稳定、合规和安全的持续性投入,其中核心取决于你选择了什么样的“地基”来承载你的业务,建站预算的构成与行业基准当你开始规划一个网站,最先面对的就是预算问题,一个常见的误区是只关注网站“看起来”的建造……

    2026-08-10
    0

发表回复

您的邮箱地址不会被公开。必填项已用 * 标注