前言
公司開發部門希望在 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。