如何在 Kubernetes Pod 内部调试 NodeJS 应用程序?

3
基本上问题已经提出。
我正在使用具有多个节点和运行Docker容器的多个Pod的k8s部署的Ubuntu系统。 其中一些Pod是运行以下命令的nodeJS微服务:
node app.js
有时,我需要通过添加日志,更改内部逻辑等来调试微服务。
在Windows中使用相同的微服务,我只需更改源代码并重新启动node.exe进程。 如何在具有Kubernetes部署的Linux中实现相同的效果?
我尝试运行shell:
kubectl exec my-microservice-XXXX -it -- sh
更改源代码并保存:nano app.js
查找node进程:ps aux
PID   USER     TIME  COMMAND
    1 root      0:00 npm
   22 root      0:00 npm
   42 root      0:27 node --max-http-header-size=65000 app.js

然后向 PID 42 发送 SIGTERM 信号:

kill SIGTERM 42

这会导致我被从容器中强制退出:

/usr/src/app # kill SIGTERM 42
sh: invalid number 'SIGTERM'
/usr/src/app # command terminated with exit code 137
test@node1:~$

一个新的Pod将自动启动:

my-microservice-XXXX                       0/1     Completed   1          19h
my-microservice-XXXX                       1/1     Running     2          19h

一点提醒:您误用了 kill 命令。另外,SIGTERM 是默认信号,因此您无需指定其类型,实际上您可以只使用 kill 42。如果您想指定信号的类型,则应使用以下语法:kill -<signal> <pid>-s <signal>--signal <signal>,例如 kill -SIGTERM 42 - mario
你实际上想通过杀死这个进程并重新启动Pod来获得什么?你不应该在运行中的Pod内进行任何更改。相反,你应该构建一个使用更新代码版本的镜像,并更新你的部署。 - mario
@maro - 我想杀掉进程,以便我所做的源代码更改生效。这是为了调试客户生产环境而设计的,我们无法重新编译代码更改并部署它,因为它是较大安装的一部分。 - Ko Ga
我认为在 Kubernetes 中不应该这样做。它不应该用于调试,而应该用于运行工作镜像。镜像应该是不可变的,即如果您更改了应用程序的代码,则应该使用包含新代码的新镜像替换旧镜像。这不是您应该使用 Kubernetes 的方式。请参见 @Sagar Chilukuri 提供的答案。正如他所提到的,应用程序代码应该是镜像的组成部分,不应存储在卷中。 - mario
2个回答

3

通过以下两个步骤,您可以在Kubernetes Pod中运行的Docker容器内调试Node应用程序:

  1. 登录容器并以调试模式运行Node应用程序:
kubectl exec -it <pod-name> bash
node --inspect-brk index.js

将本地端口的连接转发到 Pod 上的一个端口
kubectl port-forward <pod-name> 9229

注意:9229是默认的调试器监听的端口号,您不需要在Kubernetes配置yaml文件中公开此端口。
就这样。
现在您可以使用地址chrome://inspect打开Chrome浏览器,单击远程目标并开始调试。

1
这在Kubernetes中不是一种直接的方式,因为我们不管理容器(创建、终止等)。这是由Kubernetes完成的,因此该过程是短暂的。
如果您不想在容器重新启动时丢失更改,则可以使用卷挂载目录,其中您正在进行更改。(这完全违背了Docker容器化的目的,并且不建议将代码存储在卷中用于生产(任何)环境。)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接