SonarQube 升级指南:从 9.9.5.1 到 2025.1.0

概述

本文件描述了如何将 SonarQube 从版本 9.9.5.1(9.9.6)升级到 2025.1.0。由于此次升级涉及到操作员 4.0 版本的变化,因此现有的 SonarQube 实例需要迁移到新的版本操作员。

先决条件

  • 已在集群中安装新的版本操作员(sonarqube-ce-operator)
  • 确保有足够的系统资源可用于升级
  • 使用产品功能将 SonarQube 升级到版本 9.9.5.1
  • 根据 备份文档 进行完整的数据备份

升级步骤

1. 停止旧版本实例的部署

# 防止操作员自动同步
kubectl patch deployment <old-sonarqube-name>-sonarqube -n <old-instance-namespace> \
  --type=json \
  -p '[{"op": "add", "path": "/metadata/annotations/skip-sync", "value": "true"}]'

# 将部署规模缩减至 0
kubectl scale deployment <old-sonarqube-name>-sonarqube -n <old-instance-namespace> --replicas=0

2. 配置新版本实例

2.1 数据库配置

注意:SonarQube 9.9.5 支持 PG 版本 11-15,而 SonarQube 2025.1.0 支持 PG 版本 13-17。有关数据迁移到新 PG 版本的信息,请参阅官方 PG 文档

旧 SonarQube 版本使用的 PG 信息记录在 SonarQube 实例的 spec.database.secretName 中。

kubectl get sonarqube.operator.devops.alauda.io <old-sonarqube-name> -n <old-instance-namespace> -o jsonpath='{.spec.database.secretName}'

使用上述命令获取 secretName,然后使用

kubectl get secret <secretName> -n <old-instance-namespace> -o yaml 获取 secret 信息

该 secret 内容如下:

apiVersion: v1
data:
  database: <database base64>
  host: <host base64>
  password: <password base64>
  port: <port base64>
  sslmode: <sslmode base64>
  username: <username base64>
kind: Secret
metadata:
  name: old-sonarqube-pg-secret
type: Opaque
  1. 根据 备份文档 进行完整的数据备份。

  2. 为新的 SonarQube 实例创建一个新的 PG 数据库。

建议为部署新的 SonarQube 版本创建一个新的数据库,以避免污染旧数据库,并确保旧 SonarQube 仍能正常运行。

  1. 根据 备份文档 进行数据迁移。

  2. 创建一个新的数据库 secret。新版本的 secret 只需要存储密码:

# 注意:这里的密码是新部署的 PG 数据库的密码
kubectl create secret -n <namespace> generic sonarqube-db-secret \
  --from-literal=jdbc-password=<password>
  1. 创建一个新的 SonarQube 实例配置,使用数据库连接信息,连接到先前的 PG 实例。
spec:
  helmValues:
    postgresql:
      enabled: false  # 禁用默认 PostgreSQL
    jdbcOverwrite:
      enable: true
      # jdbcSecretName 是新创建的 secret 的名称
      jdbcSecretName: sonarqube-db-secret
      # username、host、port、database 是新的 PG 数据库的用户名、主机、端口和数据库
      jdbcUrl: jdbc:postgresql://<host>:<port>/<database>?socketTimeout=1500
      jdbcUsername: <username>

2.2 存储配置

根据旧 SonarQube 实例使用的存储类型选择相应的配置:

kubectl get sonarqube.operator.devops.alauda.io <old-sonarqube-name> -n <old-instance-namespace> -o jsonpath='{.spec.persistence.type}'

使用 StorageClass:

使用现有 PVC 部署新实例

spec:
  helmValues:
    persistence:
      enabled: true
      ## 旧版本 PVC 名称是 <old-sonarqube-name>-sonarqube
      existingClaim: <old-sonarqube-name>-sonarqube

使用现有 PVC:

使用以下命令获取旧 SonarQube 版本使用的 PVC 名称

kubectl get sonarqube.operator.devops.alauda.io <old-sonarqube-name> -n <old-instance-namespace> -o jsonpath='{.spec.persistence.pvc.webServiceExistingClaim}'

spec:
  helmValues:
    persistence:
      enabled: true
      existingClaim: <spec.persistence.pvc.webServiceExistingClaim from old instance YAML>

使用 HostPath:

注意:新旧版本的 HostPath 节点必须保持一致。path 应在旧版本路径的基础上添加一个 portal 目录。例如,如果旧版本路径是 /sonarqube/,则新版本路径应为 /sonarqube/portal/

spec:
  helmValues:
    nodeSelector:
      kubernetes.io/hostname: <node-name>
    persistence:
      enabled: false
      host:
        nodeName: <spec.persistence.location.nodeName from old instance YAML>
        path: <spec.persistence.location.path from old instance YAML>/portal # 旧版本在控制器中添加了一个 portal 目录,新版本需要保持一致

2.3 网络配置

由于旧版本实例尚未清理,新版本的网络配置不能与旧版本相同(即,ingress 不能使用相同的域名,nodePort 不能使用相同的端口),否则会导致冲突。暂时使用其他地址,待升级完成后,清理旧版本实例,然后再修改访问地址。

使用以下命令获取旧 SonarQube 版本使用的网络类型

kubectl get sonarqube.operator.devops.alauda.io <old-sonarqube-name> -n <old-instance-namespace> -o jsonpath='{.spec.service.type}'

Ingress 配置:

spec:
  helmValues:
    ingress:
      enabled: true
      hosts:
        - name: <spec.service.ingress.domainName from old instance YAML> ## 注意:当旧实例存在时,使用相同的域名会导致冲突,因此设置一个不同的域名
      tls: ## 如果旧版本是 https,则需要配置 tls,否则不要配置以下部分
        - secretName: <spec.service.ingress.secretName from old instance YAML> ## 旧版本证书可能位于 cpaas-system,需要复制到实例部署所在的命名空间
          hosts:
            - <spec.service.ingress.domainName from old instance YAML>

NodePort 配置:

spec:
  helmValues:
    service:
      name: sonarqube
      type: NodePort
      nodePort: <spec.service.nodePort.port from old instance YAML> ## 注意:当旧实例存在时,使用相同的 nodePort 会导致冲突,因此设置一个不同的 nodePort

配置 spec.externalURL:

spec:
  ## 如果网络配置为 Ingress 类型,<new-sonar-url> 的值为 <spec.service.ingress.domainName from old instance YAML>
  ## 如果网络配置为 NodePort 类型,使用命令 kubectl get nodes -o jsonpath='{.items[0].status.addresses[?(@.type=="InternalIP")].address}' 获取 IP 地址。<new-sonar-url> 的值为 IP:<nodePort>
  externalURL: <new-sonar-url>

其他配置

  • 保留插件:新版本需要保留旧版本的插件。添加配置 spec.helmValues.plugins.deleteDefaultPlugins 为 false。
  • SSO 配置迁移:根据 部署文档:SSO 配置 重新配置。
  • 资源配置迁移:根据旧实例的 spec.resourceAssign 为新实例配置 spec.helmValues.resources。
  • helmValues 配置迁移:旧实例的 helmValues 中的大多数数据可以直接迁移到新实例的 helmValues。例如,spec.helmValues.jvmOpts 可以直接迁移到新实例的 spec.helmValues.jvmOpts。

新版本的完整 YAML 示例:

apiVersion: operator.alaudadevops.io/v1alpha1
kind: Sonarqube
metadata:
  name: new-sonarqube
spec:
  helmValues:
    plugins:
      deleteDefaultPlugins: false # 保留旧版本插件
    prometheusExporter: # 禁用默认 prometheus 监控,启动时需要提前添加 jar 包
      enabled: false
    resources: # 设置资源限制,来源于旧实例 YAML 的 spec.resourceAssign
      limits:
       cpu: 800m
       memory: 4Gi
      requests:
       cpu: 400m
       memory: 2Gi
    postgresql: # 禁用默认 PostgreSQL 实例
      enabled: false
    jdbcOverwrite: # 使用旧版本实例的 PG 信息进行配置
      enable: true
      jdbcSecretName: sonarqube-db-secret # 使用新创建的 secret 名称
      jdbcUrl: jdbc:postgresql://<pg.host>:<pg.port>/<pg.database>?socketTimeout=1500
      jdbcUsername: <pg.username>
    service: # 根据旧版本实例进行配置
      name: sonarqube
      type: NodePort
      nodePort: <spec.service.nodePort.port from old instance YAML>
    persistence: # 根据旧版本实例进行配置
      enabled: true
      existingClaim: <spec.persistence.pvc.webServiceExistingClaim from old instance YAML>

5. 手动执行数据模式迁移

注意:提前备份旧版本数据

访问 new-sonar-url/setup 并按提示进行操作。

6. 验证升级结果

检查以下内容以确保升级成功:

  • 所有项目数据完整
  • 用户账户和权限正确
  • 插件状态正常(某些插件可能需要重新安装)
  • 历史分析数据可访问

7. 清理工作

  1. 在确认新实例稳定运行后,可以删除旧实例。
  2. 调整网络配置,使其与原始配置一致。

参考文档