在 Kubernetes 中手动进行 Java 飞行记录器记录
这描述了如何在没有额外工具的情况下,为容器化环境中的 Keycloak 创建 Java 飞行记录器记录。
概述
Java 飞行记录器 (JFR) 记录 Java 虚拟机的事件,包括线程转储,然后可以将其组装成火焰图,并可用于分析性能。在一个功能完善的设置中,使用 Cryostat 捕获性能指标 提供了一种自动化方法,并且不需要自定义 Keycloak 镜像。如果此类设置不可用,请按照这些说明捕获 JFR。
这没有使用异步分析,因为在 OpenShift 内部 AFAIK 中不可用。因此,记录将具有安全点偏差问题。请参阅 在容器中分析 Java。 |
准备 Keycloak 镜像
以下程序需要容器中存在 jcmd
才能启动 Java 飞行记录,以及 tar
才能使用 kubectl cp
从容器中检索记录。
虽然较旧版本的 Keycloak 包含这些工具,但较新的 Keycloak 镜像版本不包含它们,以使镜像更小更安全。因此,第一步是创建包含这些工具的自定义 Keycloak 镜像。有两种方法可以做到这一点:从头开始创建 Keycloak 镜像,或者使用必要的软件包更新 Keycloak 镜像。
从头开始构建 Keycloak
如果您正在从 Keycloak 的主存储库构建自定义 Keycloak 发行版,请更改文件 quarkus/container/Dockerfile
并交换行
RUN bash /tmp/ubi-null.sh java-17-openjdk-headless glibc-langpack-en
与
RUN bash /tmp/ubi-null.sh java-17-openjdk-devel tar glibc-langpack-en
然后按照 在 Kubernetes 中部署使用自定义 Keycloak 镜像 中描述的步骤进行构建镜像。
向镜像添加额外的 RPM 软件包
Keycloak 关于容器的文档 包含关于如何添加软件包的部分。要添加两个软件包 java-17-openjdk-devel tar
,请使用如下 Dockerfile 进行操作
FROM registry.access.redhat.com/ubi9 AS ubi-micro-build
RUN mkdir -p /mnt/rootfs
RUN dnf install --installroot /mnt/rootfs java-17-openjdk-devel tar --releasever 9 --setopt install_weak_deps=false --nodocs -y; dnf --installroot /mnt/rootfs clean all
FROM quay.io/keycloak/keycloak
COPY --from=ubi-micro-build /mnt/rootfs /
然后按照 在 Kubernetes 中部署使用自定义 Keycloak 镜像 中描述的步骤使用该镜像。
更新 JVM 选项
从 Keycloak 23 开始,不再需要覆盖 -XX:FlightRecorderOptions=stackdepth JVM 选项,因为 Keycloak 默认使用 512。 |
Keycloak 为其调用使用非常深的堆栈跟踪。为了能够使用火焰图,请通过添加以下 JVM 选项来增加堆栈帧的数量。
-XX:FlightRecorderOptions=stackdepth=512
当使用 Keycloak Operator 时,可以通过 Keycloak 的 CustomResource 将其传递给 Keycloak 镜像,如下所示
apiVersion: k8s.keycloak.org/v2alpha1
kind: Keycloak
spec:
unsupported:
podTemplate:
spec:
containers:
- env:
- name: JAVA_OPTS_APPEND
value: >
-XX:FlightRecorderOptions=stackdepth=512
如果您正在运行由 Operator 管理的 StatefulSet 或 Deployment,请考虑停止 Operator 并手动更新 StatefulSet 或 Deployment 以添加或扩展 Java 选项。
开始记录
要开始记录,请在容器中发出命令
kubectl exec -n namespace pod -- jcmd 1 JFR.start duration=60s filename=/tmp/recording.jfr settings=/usr/lib/jvm/java/lib/jfr/profile.jfc
值 1
是 Java 进程的进程 ID,它是所有基于 Quarkus 的 Keycloak 容器的默认值。对于基于 Wildfly 的发行版,这可能是不同的进程 ID。使用不带参数的 jcmd
列出所有 Java 进程 ID 以找到您要查找的进程。
如果 Pod 中运行着多个容器,请添加 CLI 选项 -c container
。
profile.jfc
包含关于要捕获内容的说明。profile.jfc
是 JVM 附带的标准配置文件之一,代表 “性能分析”:它收集大量信息,并应收集几分钟的信息。一分钟的记录将已经收集约 5 兆字节的数据,因此请寻求较短的时间跨度。根据需要调整它以收集您需要的信息。
检索记录
要检索记录,请发出以下命令
kubectl cp -n namespace keycloak pod:/tmp/recording.jfr recording.jfr --retries 999
如果 Pod 中运行着多个容器,请添加 CLI 选项 -c container
。
CLI 选项 --retries 999
有助于恢复大型文件的下载 否则可能会失败。
分析记录
有关详细信息,请参阅 分析 Java 飞行记录器记录。