在 Kubernetes 中手动录制 Java Flight Recorder
本文档介绍了如何在没有额外工具的情况下,为容器化环境中的 Keycloak 创建 Java Flight Recorder 录制。
概述
Java Flight Recorder (JFR) 记录 Java 虚拟机的事件,包括线程转储,这些转储可以组装成火焰图,并用于分析性能。在完整的设置中,使用 Cryostat 捕获性能指标 提供了一种自动化的方式,并且不需要自定义 Keycloak 镜像。如果没有这样的设置,请按照以下说明捕获 JFR。
此方法不使用异步分析,因为据我所知,OpenShift 内部无法使用异步分析。因此,录制将存在安全点偏差问题。请参阅 在容器中分析 Java。 |
准备 Keycloak 镜像
以下步骤需要容器中存在 jcmd
来启动 Java Flight Recording,以及 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
然后按照 使用自定义 Keycloak 镜像在 Kubernetes 中进行部署 中的描述构建镜像。
向镜像添加其他 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 /
然后按照 使用自定义 Keycloak 镜像在 Kubernetes 中进行部署 中的描述使用镜像。
更新 JVM 选项
从 Keycloak 23 开始,不再需要覆盖 -XX:FlightRecorderOptions=stackdepth JVM 选项,因为 Keycloak 默认使用 512。 |
Keycloak 使用非常深的堆栈跟踪来进行调用。为了能够使用火焰图,请增加堆栈帧的数量,并添加以下 JVM 选项:
-XX:FlightRecorderOptions=stackdepth=512
当使用 Keycloak 运算符时,可以通过 Keycloak 的自定义资源将其传递给 Keycloak 镜像,如下所示
apiVersion: k8s.keycloak.org/v2alpha1
kind: Keycloak
spec:
unsupported:
podTemplate:
spec:
containers:
- env:
- name: JAVA_OPTS_APPEND
value: >
-XX:FlightRecorderOptions=stackdepth=512
如果您正在运行由运算符管理的 StatefulSet 或 Deployment,请考虑停止运算符并手动更新 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
是所有基于 Quarkus 的 Keycloak 容器的 Java 进程的默认进程 ID。对于基于 Wildfly 的发行版,这可能是不同的进程 ID。使用不带参数的 jcmd
列出所有 Java 进程 ID 以找到您要查找的进程 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 Flight Recorder 录制。