Jenkins + SonarQube 从原理到实战一:基于 K8s 部署与使用(含中文插件与 Python 扫描)

发布于:2025-07-30 ⋅ 阅读:(36) ⋅ 点赞:(0)

前言

公司开发部门希望在 Jenkins 构建过程中自动集成 C/C++ 的代码扫描,正好我也没接触过 SonarQube,于是记录下从零开始部署 SonarQube 服务并集成到 CI/CD 的过程,供后来者参考。


一、SonarQube 原理与工作机制详解

1.1 什么是 SonarQube?

SonarQube 是一款开源的代码质量管理平台,通过静态代码分析识别代码中的 Bug、安全隐患、重复代码、不规范风格等问题。它支持 CI/CD 集成、质量门控、可视化报告、规则自定义等功能,有助于提升开发效率与软件质量。

设计目标包括:

  • 防止 Bug 潜入主干(Shifting Left)
  • 统一代码质量度量标准
  • 提升协作开发效率

1.2 工作机制与关键组件

SonarQube 的整体流程可概括为 3 个阶段:

🔍 阶段一:代码分析

  • 使用 SonarScanner 或 IDE 插件(如 SonarLint)对项目进行扫描
  • 收集源代码、控制流、函数结构、复杂度、注释等静态信息
  • 编译型语言(如 C++、Java)需借助 build-wrapper 或编译日志获取 AST 与依赖信息

🚀 阶段二:数据传输

  • 扫描结果打包成 .sonar 文件,通过 HTTP(S) 上传至 SonarQube Server
  • 上传时需配置 token 或用户名/密码

📊 阶段三:质量评估与展示

  • Server 接收数据后执行:

    • 规则匹配引擎(Rules Engine):查找违规代码
    • 质量门检查(Quality Gates):判断是否满足发布标准
    • 报告生成与持久化:结果写入数据库(如 PostgreSQL),UI 展示可视化报表

📘 例如,Python 代码中使用 eval() 会被标记为高危漏洞,质量门不通过,从而阻止 CI 发布。

💡 一开始我误以为是由 sonar-scanner 上传代码,SonarQube Server 再去分析,实际是本地的 sonar-scanner 完成分析,然后将结果上传到服务器展示。


二、SonarQube 的语言支持与扫描机制差异

不同语言使用不同的分析策略,以下是主流语言支持情况对比:

编程语言 内置支持 特殊要求 分析深度 说明
Java 支持完整语义分析
Python 可识别格式、Bug、注释等问题
JavaScript 可结合 ESLint 使用
C/C++ 需安装插件 + 构建信息 使用 sonar-cxx 插件 + build-wrapper
Go 分析速度较快
PHP 可配合 PHPUnit 报告
Kotlin 与 IntelliJ 兼容性好
HTML/CSS/TS 适用于前端项目

🔎 补充说明

  • 解释型语言(如 Python/JS):通过 AST + 规则匹配进行分析
  • 编译型语言(如 C++/Java):依赖编译输出、控制流图、符号表等更复杂结构
  • 通用指标包括:Bugs、Vulnerabilities、Code Smells、Coverage、Duplication,但其计算方式会根据语言有所差异

三、SonarQube 版本体系详解

SonarQube 提供多个版本以满足不同用户需求:

版本 收费 特性亮点
Community Edition 免费 支持主流语言、基本规则配置、质量门控、Web UI
Developer Edition 商用 支持 C/C++/Swift、数据流分析、分支分析、Git blame 支持
Enterprise Edition 商用 增加多项目仪表盘、多租户支持、安全审计、SAML 登录
Data Center Edition 商用 支持高可用集群部署、适合大型企业环境

本文使用的是 Community Edition,可通过插件支持 C/C++ 分析,但不支持商业功能如分支差异比较、安全数据流等。
如果社区版实现不了的功能,那就由社区版 + 开源插件实现。


四、在 K8s 上部署 SonarQube(+ PostgreSQL)

我存储用的是 NFS,请PV、PVC部分请根据实际情况改动。

SonarQube 不支持 MySQL
一般来说,SonarQube 里的 H2 数据库也够用,就不用不过具体看公司规模情况,不过生产环境还是用 PostgreSQL,后续更好维护一些。

PostgreSQL

PersistentVolume、PersistentVolumeClaim

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-postgresql
  namespace: sonar
spec:
  capacity:
    storage: 50Gi
  accessModes:
    - ReadWriteMany
  storageClassName: postgresql
  persistentVolumeReclaimPolicy: Retain
  nfs:
    server: NFS地址
    path: /k8s-nfs/sonar/postgresql
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc-postgresql
  namespace: sonar
spec:
  accessModes:
    - ReadWriteMany
  storageClassName: postgresql
  resources:
    requests:
      storage: 50Gi

Service、Deployment

kind: Service
metadata:
  name: postgresql
  namespace: sonar
spec:
  selector:
    app: postgresql
  ports:
    - protocol: TCP
      port: 5432
      targetPort: 5432
      name: postgresql
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: postgresql
  namespace: sonar
spec:
  replicas: 1
  selector:
    matchLabels:
      app: postgresql
  template:
    metadata:
      name: postgresql
      labels:
        app: postgresql
    spec:
      nodeSelector:
        group: it
      containers:
      - name: postgresql
        image: postgres:17
        env:
          - name: TZ
            value: 'Asia/Shanghai'
          - name: POSTGRES_USER
            value: sonar
          - name: POSTGRES_PASSWORD
            value: sonar_password
          - name: POSTGRES_DB
            value: sonar
        ports:
        - name: postgresql
          containerPort: 5432
        volumeMounts:
          - name: postgresql
            mountPath: /var/lib/postgresql
          - name: postgresql
            mountPath: /var/lib/postgresql/data
            subPath: data
      volumes:
        - name: postgresql
          persistentVolumeClaim:
            claimName:  pvc-postgresql

这里会一点小坑,在 dockerhub 上面搜 postgresql 会出现各种各样的数据库,但这都不是官方的,并且数据库目录 data 位置也不一样,官方的是 postgres

SonarQube

PersistentVolume、PersistentVolumeClaim

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-sonarqube
  namespace: sonar
spec:
  capacity:
    storage: 50Gi
  accessModes:
    - ReadWriteMany
  storageClassName: sonarqube
  persistentVolumeReclaimPolicy: Retain
  nfs:
    server: NFS地址
    path: /k8s-nfs/sonar/sonarqube
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc-sonarqube
  namespace: sonar
spec:
  accessModes:
    - ReadWriteMany
  storageClassName: sonarqube
  resources:
    requests:
      storage: 50Gi

Service、Deployment

apiVersion: v1
kind: Service
metadata:
  name: sonarqube
  namespace: sonar
spec:
  selector:
    app: sonarqube
  type: NodePort
  ports:
    - protocol: TCP
      port: 9000
      targetPort: 9000
      nodePort: 32018
      name: sonarqube
---
apiVersion: v1
kind: Pod
metadata:
  name: sonarqube
  namespace: sonar
  labels:
    app: sonarqube
spec:
  containers:
  - name: sonarqube
    image: sonarqube:lts-community #我这里是9.9.x版本
    env:
    - name: TZ
      value: 'Asia/Shanghai'
    - name: SONAR_JDBC_URL
      value: jdbc:postgresql://postgresql:5432/sonar
    - name: SONAR_JDBC_USERNAME
      value: sonar
    - name: SONAR_JDBC_PASSWORD
      value: sonar_password
    - name: SONAR_WEB_JVM_OPTS
      value: "-Xmx2G -Xms1G -XX:+HeapDumpOnOutOfMemoryError"
    ports:
    - name: sonarqube
      containerPort: 9000
    volumeMounts:
    - name: sonarqube
      mountPath: /opt/sonarqube/extensions
      subPath: extensions
    - name: sonarqube
      mountPath: /opt/sonarqube/logs
      subPath: logs
    - name: sonarqube
      mountPath: /opt/sonarqube/data
      subPath: data
    - name: sonarqube
      mountPath: /opt/sonarqube/conf
      subPath: conf
  restartPolicy: Never
  volumes:
  - name: sonarqube
    persistentVolumeClaim:
      claimName: pvc-sonarqube

然后给宿主机(Node 节点)修改下配置,否则es启动会报错:

echo "vm.max_map_count=262144" | sudo tee -a /etc/sysctl.conf
# 控制单个进程可拥有的虚拟内存映射区域(VMA)数量上限(例如内存映射文件、共享库等)
sudo sysctl -p
# 立即生效,无需重启系统

就可以 kubectl apply -f xxx.yaml运行起来了

📌 访问地址:http://NodeIP:32018

默认账号密码:admin,admin


五、中文插件离线安装指南

中文插件地址(github)
按对应版本下载:
在这里插入图片描述

简要步骤

下载的插件 .jar 文件,放到 sonarqube 的 extensions/plugins/ 路径下。
并重启服务后并重新登录,界面将变为中文。

个人感觉中文翻译很差,真的是机翻,还不如使用英文版。


六、Python 项目扫描实战

1. 新增项目

  • 左上角 “项目” - 右侧 :“新增项目” - “手工”
  • 输入 “显示名”“项目标识”“主分支名称”(可默认main),点击 “设置”;
  • 点击 “本地” ,确认 “令牌名称” ,点击 “创建” - “继续”
  • 点击 “其他 (比如 JS,TS,Go,Python,PHP…)”,并选择对内操作系统(我这里是Windows)

2. 安装 sonar-scanner

  • “新增项目” 做完后,下面会有下载链接和提示:
    在这里插入图片描述
  • 点击并访问,下载解压并且添加到系统/用户环境变量

    Linux 操作雷同。

3. 执行扫描:

  • 进入 Python 项目并执行:
    sonar-scanner.bat -D"sonar.projectKey=令牌名称" D"sonar.sources=." -D"sonar.host.url=http://sonar地址" D"sonar.login=sqp_91..."
    看到最后提示 SUCCESS 即成功。

4. 报告查看:

  • 在 Sonar 的 Web 页面上,选择相应项目可以查看。

注:
在 Windows 系统的扫描项目下配置sonar-project.properties文件不生效,Linux 系统反而没这个问题。

sonar-project.properties 只是把 -D 参数后面的东西写入配置文件,sonar-scanner.bat 执行时使用里面的配置而已。


结语

上面就是 SonarQube 的部署已经简单使用,后续将更新 SonarQube 如何通过 cxx 插件,实现 C/C++ 代码的扫描,以及打通 Windows AD 和 Jenkins。


网站公告

今日签到

点亮在社区的每一天
去签到