JAVA 应用实现 APM 自动注入(Docker 篇)

简介
虽然 Kubernetes 已经成为行业容器编排的事实标准,但是当组织处于从 Docker 向 Kubernetes 过度的阶段或者不想引入 Kubernetes 带来的复杂性时仍然会有很多使用 Docker 做容器编排的情况,观测云现已支持对 Docker 部署的 Java 应用注入 APM 探针。
安装或者升级 DataKit
Docker 环境下的 Java 探针自动注入由 DataKit 在 1.66.0 版本中引入,在 1.69.0 版本中完善了 JVM 指标的导出机制,启用自动注入需执行 DataKit 安装或者升级操作,然后重新部署 Docker 应用。
全新安装 DataKit
登录观测云控制台,点击「集成」 -「DataKit」 - 「Linux」,复制安装命令。

在命令中增加环境变量 DK_APM_INSTRUMENTATION_ENABLED
,如下所示:
在 Linux 主机中以 root 权限执行以上命令即可完成 DataKit 安装。
升级已有的 DataKit
登录已经安装 DataKit 的 Linux 主机,以 root 权限执行以下命令,注意,即使已经安装了最新版本的 DataKit,仍然需要通过升级的方式打开自动注入。
启用必要插件
安装或升级完成后,如未开启 ddtrace、profile、statsd 插件,需执行以下步骤打开插件,允许 DataKit 收集并处理追踪、剖析和 JVM 指标数据。
注意, statsd 插件的配置文件在 1.67.0 版本后存在变更,增加了 statsd 插件的 socket 监听方式,因此升级前的版本小于 1.67.0,且已经打开了 statsd 插件的情况下,需要执行 statsd 插件的配置变更。
启用自动注入
进入应用的 Docker Compose 目录,执行以下操作重新部署应用。
当应用被访问时即可登录观测云控制台,点击「应用性能监测」查看上报的链路追踪数据,对于 SpringBoot 应用, 默认服务名来自 spring.application.name
。

如需通过环境和版本区分程序的性能差异,或者通过 Profile 分析慢调用的栈追踪,需要通过环境变量在 docker-compose.yml
中做进一步配置,举例如下:
配置完成后重新部署应用即可,一般来说区分数据的环境和版本是必须的,可以将以上配置集成至 CICD 流水线中,避免手动修改 Compose 文件。
停用自动注入
Docker 容器探针自动注入通过修改 Docker 的默认容器运行时为 dk-runc
实现,此运行时会为容器进程添加环境变量、挂载相关文件,最终以劫持 Bash 命令的方式修改 Java 进程启动参数,从而完成探针自动注入,探针采集的数据发送至 /var/run/datakit/datakit.sock
和 /var/run/datakit/statsd.sock
,因此停止自动注入需要完成以下步骤:
1、修改 Datakit 配置文件 /usr/local/datakit/conf.d/datakit.conf
中 instrumentation_enabled
的值为 "no";
2、执行命令 datakit tool --remove-apm-auto-inject
还原 DataKit 对 /etc/docker/daemon.json
所作的修改;
3、执行命令 datakit service -R
重启 DataKit;
4、执行命令 systemctl daemon-reload
;systemctl restart docker
重启 dockerd;
5、进入应用 Docker Compose 目录执行命令 docker compose up -d
重新部署应用;
6、确保应用已正常启动,容器是否自动重启与其重启策略有关。
如需卸载开启自动注入的 DataKit,需完成以下步骤:
1、执行命令 datakit tool --remove-apm-auto-inject
还原 DataKit 对 /etc/docker/daemon.json
所作的修改;
2、执行命令 datakit service -U
卸载 DataKit 服务;
3、执行命令 systemctl daemon-reload; systemctl restart docker
重启 dockerd;
4、进入应用 Docker Compose 目录执行命令 docker compose up -d
重新部署应用;
5、确保应用已正常启动,容器是否自动重启与其重启策略有关。
一般来说卸载 DataKit 无需移除 /usr/local/datakit
目录,如果未按照以上步骤执行操作直接移除了此目录,可能导致容器启动报错,例如:
此时,需确认 Docker 配置文件 /etc/docker/daemon.json
是否已经恢复、dockerd 是否已重启,以及应用是否已重新部署,预期情况下通过 docker inspect <container name> | grep Runtime
查询到的容器运行时应该为 runc。无法执行 datakit tool --remove-apm-auto-inject
命令时,可手动恢复 Docker 配置文件,举例如下:
问题排查
如果探针自动注入失败,请按照以下步骤进行问题排查:
1、执行命令件 docker inspect <container name> | grep Runtime
,检查当前容器的运行时是否为 dk-runc,如果仍然为 runc 请检查是否正确开启自动注入;
2、找到容器的 PID,假设 PID 为 xxx,执行命令 cat /proc/xxx/environ
,检查是否包含以下环境变量:
3、如果不包含 LD_PRELOAD
和 ENV_DATAKIT_SOCKET_ADDR
,说明 dk-runc 注入环境变量失败,执行命令 mkdir -p /usr/local/datakit/apm_inject/log/
开启 dk-runc 日志,重新执行 docker compose up -d
,即可在此路径下查看环境变量注入与文件挂载相关的日志;
4、如果包含 LD_PRELOAD
和 ENV_DATAKIT_SOCKET_ADDR
,不包含DD_TRACE_AGENT_URL
等,则可能是容器进程启动命令拦截失败导致相关环境变量注入异常,请通过观测云反馈渠道报告。
总结
使用 Docker 容器部署 Java 应用时,采用探针自动注入能够减少可观测数据采集所需的配置量,不过,需要确保在应用的开发、测试、生产环境注入相同版本的探针,把探针作为代码的一部分集成,而不是仅在生产环境注入。其实,在现代的 CICD 管道中集成探针是一种更好的自动化方案,有利于构建一个透明的系统。
评论