JKube远程debug k8s中Java应用

676 阅读3分钟

前言

本文源代码在这:github.com/tzjavadmg/j…

部署k8s并以debug模式启动应用

运行mvn命令构建镜像并部署至minikube k8s集群

mvn clean package k8s:build k8s:resource k8s:apply

运行k8s:debug命令,此命令会删除之前的pod,并以debug模式重新启动。

PS D:\i-workspace\jkube-examples\remote-debug> mvn k8s:debug
[INFO] Scanning for projects...
[INFO] 
[INFO] k8s: Liveness probe will be disabled on Deployment remote-debug to allow attaching a remote debugger during suspension
[INFO] k8s: Enabling debug on Deployment remote-debug
[INFO] k8s: Updating Deployment remote-debug with Debug variables in containers
[INFO] k8s: Updating Deployment from kubernetes.yml
[INFO] k8s: Updated Deployment: remote-debug\target\jkube\applyJson\default\deployment-remote-debug-1.json
[INFO] k8s: No Active debug pod with provided selector and environment variables found! Waiting for pod to be ready...
[INFO] k8s: Waiting for debug pod with selector LabelSelector(matchExpressions=[], matchLabels={app=remote-debug, provider=jkube, group=com.codyzeng}, additionalProperties={}) and en
vironment variables {JAVA_DEBUG_SESSION=7522675627520338709, JAVA_DEBUG_SUSPEND=true, JAVA_ENABLE_DEBUG=true}
[INFO] k8s: Starting port forwarding to port 5005 on pod remote-debug-685f6f4756-6w2xn
[INFO] k8s: Port Forwarding started
[INFO] k8s: Now you can start a Remote debug session by using localhost and the debug port 5005
[INFO] k8s: -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005

在minikube dashboard中查看日志。可以看到开启了监听端口5005

image.png

IDEA中远程Debug

按下图所示新建一个Remote JVM DEBUG配置 image.png

不同的JDK版本启用远程debug的命令是不一样的。

JDK9以上:-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005
JDK5-8: -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005

由此猜测docker中使用的jdk是9以下版本,可进入pod容器使用java命令查看版本发现是17.

[jboss@remote-debug-685f6f4756-6w2xn ~]$ java -version
openjdk version "17.0.4" 2022-07-19 LTS
OpenJDK Runtime Environment (Red_Hat-17.0.4.0.8-2.el8_6) (build 17.0.4+8-LTS)
OpenJDK 64-Bit Server VM (Red_Hat-17.0.4.0.8-2.el8_6) (build 17.0.4+8-LTS, mixed mode, sharing)

估计是9以上版本两种试都兼容吧。。。

最后在浏览器中请求服务进入断点,可以愉快的进行远程debug了。 image.png

插件远程debug原理

执行jkube插件k8s:debug命令时,插件会作两件事:

1.添加java远程debug代理参数重新启动pod.

(-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005)

2.使用kubectl port-forward命令将debug端口转发至本地.

如果不使用插件,自定义dockerfile如下:

FROM maven:3.8.3-openjdk-17
#FROM quay.io/jkube/jkube-java:0.0.16
ENV JAVA_APP_DIR=/deployments
EXPOSE 8080 8778 9779 5005
WORKDIR /deployments
COPY maven/target/*.jar /deployments/app.jar
ENTRYPOINT [ "java", "-jar", "-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005","/deployments/app.jar" ]

启动pod后,然后使用命令行转发端口:

kubectl port-forward --address 0.0.0.0 deployment/service-discovery -n k8s-examples 5005:5005

其效果是一样的,只是用插件操作会更简单。

插件可选参数配置

使用jkube的debug功能以及其它一些参数配置支持,要满足以下条件:

1.docker要使用其提供的基础镜像(quay.io/jkube/jkube-java:0.0.16) 2.不能定义ENTRYPOINT.

如下定义dockerfile即可。

FROM quay.io/jkube/jkube-java:0.0.16
ENV JAVA_APP_DIR=/deployments
EXPOSE 8080 8778 9779 
WORKDIR /deployments
COPY maven/target/*.jar /deployments/app.jar

从上面配置可以发现,都不需要EXPOSE 5005端口。

如果不配置dockerfile,插件默认生成的dockerfile内容如下:

FROM quay.io/jkube/jkube-java:0.0.16
ENV JAVA_APP_DIR=/deployments
LABEL org.label-schema.description="Parent pom providing dependency and plugin management for applications built with Maven" org.label-schema.version=1.0-SNAPSHOT org.label-schema.schema-version=1.0 org.label-schema.build-date=2022-11-09T10:39:01.441359300 org.label-schema.name=service-discovery org.label-schema.vcs-ref=db1233b9e6e3371370cec932a09d77aa3dcf03e8 org.label-schema.vcs-url=git@github.com:/tzjavadmg/spring-cloud-k8s-examples.git
EXPOSE 8080 8778 9779
COPY /jkube-generated-layer-original/deployments /deployments/

jkube.debug.enabled启用后,pod启动默认java应用启动时带了debug参数,开启了debug端口,这样在运行k8s:debug命令时,就不需要杀掉原来的pod,再重启新的实例了。

jkube.debug.port 自定义debug端口

jkube.debug.suspend 等同于java debug参数中的suspend。如果要调试程序启动过程的问题,可设置为true。

有两种方式来配置这些参数:

1.在pom 中配置

<properties>
    <jkube.debug.enabled>true</jkube.debug.enabled>
    <jkube.debug.port>5005</jkube.debug.port>
    <jkube.debug.suspend>true</jkube.debug.suspend>
</properties>

2.在命令行指定

mvn k8s:debug -Djkube.debug.port=8000
mvn k8s:deploy -Djkube.debug.enabled=true
mvn k8s:debug -Djkube.debug.suspend