自定义 JVM 选项

SonarQube 在同一个 Pod 中运行三个 JVM 进程——Web server(UI 和 Web API)、Compute Engine(后台分析任务)以及 Search component(内嵌 Elasticsearch)。每个进程都有自己的 -Xmx / -Xms 内存预算。默认设置适用于小型部署,但更大的项目或更高的扫描并发通常需要为 Web 或 Compute Engine 分配更多堆内存,而 Search 堆通常也需要随着项目数量的增加而同步提升。

本操作指南演示如何通过 SonarQube CR 为每个进程设置 JVM 选项,以及如何验证更改已生效。

前提条件

  • 由此 operator 管理的正在运行的 SonarQube 实例。
  • 可以编辑 Sonarqube 自定义资源的权限。
  • SonarQube Pod 上的容器资源限制足够容纳新的堆预算——在不提高 Pod 内存限制的情况下增加 -Xmx,只会把 OOM 故障上移一层。

步骤 1 — 在 SonarQube CR 上设置 JVM 选项

编辑 SonarQube CR,并在 spec.helmValues.sonarProperties 下为每个进程添加 Java 选项。这三个属性名与 SonarQube 的三个进程一一对应:

属性进程典型用途
sonar.web.javaOptsWeb serverUI 响应速度、Web API 吞吐量。
sonar.ce.javaOptsCompute Engine后台分析任务的堆内存。在大型项目扫描因 OutOfMemoryError 失败时提高此值。
sonar.search.javaOptsEmbedded Elasticsearch索引内存。将 -Xms 设置为与 -Xmx 相同,这样 Elasticsearch 就不会在运行时调整堆大小。

示例:

apiVersion: operator.alaudadevops.io/v1alpha1
kind: Sonarqube
metadata:
  name: <RELEASE>
  namespace: <NAMESPACE>
spec:
  helmValues:
    sonarProperties:
      sonar.web.javaOpts: "-Xmx1G -Xms128m -XX:+HeapDumpOnOutOfMemoryError -server"
      sonar.ce.javaOpts: "-Xmx2G"
      sonar.search.javaOpts: "-Xmx2G -Xms2G"

将更改应用到 CR。operator 会在下一次 reconcile 时将该更改同步到 SonarQube ConfigMap。

步骤 2 — 验证 ConfigMap 已更新

SonarQube 进程会从一个生成的 ConfigMap 中读取这些选项,该 ConfigMap 的名称以 -sonarqube-config 结尾。在重启之前,请确认其中已包含新值:

kubectl -n <NAMESPACE> get configmap <RELEASE>-sonarqube-config -o yaml \
  | grep -E "sonar\.(web|ce|search)\.javaOpts"

如果这些键仍显示旧值,请等待几秒钟让 operator 完成 reconcile,然后重新检查。在 ConfigMap 反映出新值之前,不要继续下一步。

步骤 3 — 重启 SonarQube Pod

JVM 选项在进程启动时读取,因此新值只有在重启后才会生效:

kubectl -n <NAMESPACE> rollout restart deployment <RELEASE>-sonarqube
kubectl -n <NAMESPACE> rollout status deployment <RELEASE>-sonarqube

步骤 4 — 确认正在运行的 JVM 使用了新选项

在 SonarQube UI 中,转到 Administration → System,并展开 WebCompute EngineSearch 部分。每个部分都会显示实际使用的 JVM 标志——确认 -Xmx-Xms 的值与步骤 1 中设置的一致。

也可以从命令行通过检查 Pod 内运行中的 Java 进程来获取相同数据:

kubectl -n <NAMESPACE> exec <RELEASE>-sonarqube-xxxxx -- bash -lc \
  "ps -ef | grep -E '(WebServer|CeServer|elasticsearch)' | tr ' ' '\n' | grep -E '^-X(mx|ms)'"

如果没有看到新标志,最可能的原因是跳过了步骤 2——在 ConfigMap 更新之前就重启了 Pod。

说明

  • 关于 helmValues.jvmOpts / jvmCeOpts 较早的文档还提到 chart 级字段 jvmOptsjvmCeOpts。在此 operator 捆绑的 chart 中,这些字段为向后兼容而保留,但在上游 values 文件中已标记为 deprecated;当同时设置时,它们会被 sonarProperties.sonar.web.javaOpts / sonar.ce.javaOpts 明确 覆盖。Search 进程没有对应的 chart 字段——请使用 sonarProperties.sonar.search.javaOpts。建议为这三个进程都使用 sonarProperties 路径,这样配置更一致,也能在 chart 升级后保留。
  • 务必让 -Xmx 严格低于 Pod 的内存限制。 一个粗略经验法则是 sum(web + ce + search -Xmx) + 25% headroom ≤ container memory limit。如果堆大小总和达到该限制(或超过限制),当 JVM 正常使用完全部堆内存并加上堆外内存时,Pod 就会被 OOM-killed。
  • Search 堆。 Elasticsearch 在 -Xms 等于 -Xmx 时表现最佳。仅为 sonar.search.javaOpts 设置 -Xmx 会使堆在运行时调整大小,这会在大规模分析期间导致短暂停顿。
  • HeapDumpOnOutOfMemoryError 在排查间歇性 OOM 故障时,建议为 Web 和 Compute Engine 进程添加 -XX:+HeapDumpOnOutOfMemoryError。转储文件会写入 Pod 内 SonarQube 的工作目录;在 Pod 重新创建前,使用 kubectl cp 将其拷出。