Jenkins + SonarQube 从原理到实战一:基于 K8s 部署与使用(含中文插件与 Python 扫描)
前言
公司开发部门希望在 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-postgresqlnamespace: sonar
spec:capacity:storage: 50GiaccessModes:- ReadWriteManystorageClassName: postgresqlpersistentVolumeReclaimPolicy: Retainnfs:server: NFS地址path: /k8s-nfs/sonar/postgresql
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:name: pvc-postgresqlnamespace: sonar
spec:accessModes:- ReadWriteManystorageClassName: postgresqlresources:requests:storage: 50Gi
Service、Deployment
kind: Service
metadata:name: postgresqlnamespace: sonar
spec:selector:app: postgresqlports:- protocol: TCPport: 5432targetPort: 5432name: postgresql
---
apiVersion: apps/v1
kind: Deployment
metadata:name: postgresqlnamespace: sonar
spec:replicas: 1selector:matchLabels:app: postgresqltemplate:metadata:name: postgresqllabels:app: postgresqlspec:nodeSelector:group: itcontainers:- name: postgresqlimage: postgres:17env:- name: TZvalue: 'Asia/Shanghai'- name: POSTGRES_USERvalue: sonar- name: POSTGRES_PASSWORDvalue: sonar_password- name: POSTGRES_DBvalue: sonarports:- name: postgresqlcontainerPort: 5432volumeMounts:- name: postgresqlmountPath: /var/lib/postgresql- name: postgresqlmountPath: /var/lib/postgresql/datasubPath: datavolumes:- name: postgresqlpersistentVolumeClaim:claimName: pvc-postgresql
这里会一点小坑,在 dockerhub 上面搜
postgresql
会出现各种各样的数据库,但这都不是官方的,并且数据库目录 data 位置也不一样,官方的是postgres
。
SonarQube
PersistentVolume、PersistentVolumeClaim
apiVersion: v1
kind: PersistentVolume
metadata:name: pv-sonarqubenamespace: sonar
spec:capacity:storage: 50GiaccessModes:- ReadWriteManystorageClassName: sonarqubepersistentVolumeReclaimPolicy: Retainnfs:server: NFS地址path: /k8s-nfs/sonar/sonarqube
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:name: pvc-sonarqubenamespace: sonar
spec:accessModes:- ReadWriteManystorageClassName: sonarquberesources:requests:storage: 50Gi
Service、Deployment
apiVersion: v1
kind: Service
metadata:name: sonarqubenamespace: sonar
spec:selector:app: sonarqubetype: NodePortports:- protocol: TCPport: 9000targetPort: 9000nodePort: 32018name: sonarqube
---
apiVersion: v1
kind: Pod
metadata:name: sonarqubenamespace: sonarlabels:app: sonarqube
spec:containers:- name: sonarqubeimage: sonarqube:lts-community #我这里是9.9.x版本env:- name: TZvalue: 'Asia/Shanghai'- name: SONAR_JDBC_URLvalue: jdbc:postgresql://postgresql:5432/sonar- name: SONAR_JDBC_USERNAMEvalue: sonar- name: SONAR_JDBC_PASSWORDvalue: sonar_password- name: SONAR_WEB_JVM_OPTSvalue: "-Xmx2G -Xms1G -XX:+HeapDumpOnOutOfMemoryError"ports:- name: sonarqubecontainerPort: 9000volumeMounts:- name: sonarqubemountPath: /opt/sonarqube/extensionssubPath: extensions- name: sonarqubemountPath: /opt/sonarqube/logssubPath: logs- name: sonarqubemountPath: /opt/sonarqube/datasubPath: data- name: sonarqubemountPath: /opt/sonarqube/confsubPath: confrestartPolicy: Nevervolumes:- name: sonarqubepersistentVolumeClaim: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。