Sonarqube_实现项目质量管理


目录:

概述

SonarQube是一种自动代码审查工具,用于检测代码中的错误、漏洞和代码异味。 该文档选用sonarqube长期更新版本8.9.6 LTS。版本推荐与文章示例一致,作者尝试过使用8.9.8-community版本,无法正常启动。 数据库选用postgresQL,因为后续版本Sonarqube不再支持Mysl。 参考Sonarqube官方文档

部署

整个项目完全采用kubernetes进行部署,根据列出的Yaml文件及步骤,调整镜像及持久卷供应就可以实现部署。

目录结构

$ ll /usr/local/wlhiot/container/kubernetes/basic/sonarqube/
# 在创建storageclass之前需要kubernetes集群使用第三方文件系统以实现动态卷供应
-rw-r--r-- 1 root root  225 Apr 28 14:13 postgresql-pvc.yaml  # 2. 创建数据库的pvc
-rw-r--r-- 1 root root 1339 Apr 29 12:26 postgresql.yaml  # 3. 数据库
-rw-r--r-- 1 root root  225 Apr 28 14:16 sonarqube-pvc.yaml  # 4.sonarqube pvc
-rw-r--r-- 1 root root  139 Apr 28 14:13 sonarqube-storageclass.yaml  # 1. 创建storageclass动态卷供应(根据需要的PVC自动创建PV)
-rw-r--r-- 1 root root 2223 Apr 29 14:52 sonarqube.yaml  # 5.正式启动,各项配置可以从各YAML中查看

动态供应卷

$ cat sonarqube-storageclass.yaml 
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: sonarqube-data
provisioner: k8s-sigs.io/nfs-subdir-external-provisioner

数据库持久化存储

$ cat postgresql-pvc.yaml 
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: postgresql-data 
  namespace: basic
spec:
  accessModes:
    - ReadWriteMany
  storageClassName: "sonarqube-data"
  resources:
    requests:
      storage: 1Gi

数据库搭建

$ cat postgresql.yaml 
---
apiVersion: v1
kind: Service
metadata:
  name: postgresql-sonar
  namespace: basic
  labels:
    app: postgresql-sonar
spec:
  clusterIP: None
  ports:
  - port: 5432
    protocol: TCP
    targetPort: 5432
  selector:
    app: postgresql-sonar
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: postgresql-sonar
  namespace: basic
  labels:
    app: postgresql-sonar
spec:
  replicas: 1
  selector:
    matchLabels:
      app: postgresql-sonar
  template:
    metadata:
      labels:
        app: postgresql-sonar
    spec:
      containers:
      - name: postgresql-sonar
        image: 192.168.254.29:8080/library/postgres:11.4
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 5432
        env:
        - name: POSTGRES_DB
          value: "sonarDB"
        - name: POSTGRES_USER
          value: "sonarUser"
        - name: POSTGRES_PASSWORD 
          value: "wlhpostgresql"
        resources:
          limits:
            cpu: 1000m
            memory: 2048Mi
          requests:
            cpu: 500m
            memory: 1024Mi
        volumeMounts:
          - name: postgresql-persistent-storage-claim
            mountPath: /var/lib/postgresql/data
      volumes:
        - name: postgresql-persistent-storage-claim
          persistentVolumeClaim:
            claimName: postgresql-data

sonarqube持久化存储

$ cat sonarqube-pvc.yaml 
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: sonarqube-data 
  namespace: basic
spec:
  accessModes:
    - ReadWriteMany
  storageClassName: "sonarqube-data"
  resources:
    requests:
      storage: 10Gi

sonarqube搭建

$ cat sonarqube.yaml 
---
apiVersion: v1
kind: Service
metadata:
  name: sonarqube
  namespace: basic
  labels:
    app: sonarqube
spec:
  type: NodePort
  ports:
    - name: sonarqube
      port: 9000
      targetPort: 9000
      nodePort: 30010
      protocol: TCP
  selector:
    app: sonarqube
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: sonarqube
  namespace: basic
  labels:
    app: sonarqube
spec:
  replicas: 1
  selector:
    matchLabels:
      app: sonarqube
  template:
    metadata:
      labels:
        app: sonarqube
    spec:
      initContainers:
      - name: init-sysctl
        image: busybox
        imagePullPolicy: IfNotPresent
        command: ["sysctl", "-w", "vm.max_map_count=262144"]
        securityContext:
          privileged: true
      containers:
      - name: sonarqube
        image: 192.168.254.29:8080/library/sonarqube:8.9.6-community
        ports:
        - containerPort: 9000
        env:
        - name: SONARQUBE_JDBC_USERNAME
          value: "sonarUser"
        - name: SONARQUBE_JDBC_PASSWORD
          value: "wlhpostgresql"
        - name: SONARQUBE_JDBC_URL
#          value: "jdbc:postgresql://192.168.254.23:30013/sonarDB"
          value: "jdbc:postgresql://postgresql-sonar:5432/sonarDB"
        livenessProbe:
          httpGet:
            path: /sessions/new
            port: 9000
          initialDelaySeconds: 60
          periodSeconds: 30
        readinessProbe:
          httpGet:
            path: /sessions/new
            port: 9000
          initialDelaySeconds: 60
          periodSeconds: 30
          failureThreshold: 6
        resources:
          limits:
            cpu: 2000m
            memory: 2048Mi
          requests:
            cpu: 1000m
            memory: 1024Mi
        volumeMounts:
        - mountPath: /opt/sonarqube/conf
          name: data
          subPath: conf
        - mountPath: /opt/sonarqube/logs
          name: data
          subPath: logs
        - mountPath: /opt/sonarqube/data
          name: data
          subPath: data
        - mountPath: /opt/sonarqube/extensions
          name: data
          subPath: extensions
      volumes:
      - name: data
        persistentVolumeClaim:
          claimName: sonarqube-data

使用

使用方法有以下两种:

  • 将sonarqube直接集成进maven,更改maven配置并打包使其能被sonarqube服务器识别到(作为运维,不方便对代码侵入太深,所以不采用该方法);

mvn sonar:sonar -f "d:\work\project_test\wlh-project\pom.xml" -pl wlh-electric -am clean package

  • 使用sonar-scanner对Jar包进行扫描;

可以先下载sonar-scanner对Jar包扫描进行测试,正常输出结果再集成进Jenkins或Linux主机,扫描步骤如下:

  1. 下载sonar-scanner,修改conf/sonar-scanner文件
sonar.host.url=http://192.168.254.23:30010/
sonar.sourceEncoding=UTF-8
  1. 进入sonarqube服务器生成令牌

  2. 使用sonar-scanner命令进行扫描

sonar-scanner -D sonar.sources=./src/ -D sonar.projectname=ebox -D sonar.login=b0ab05fa97c90fb9f0aa9f86380aba6c6035781a -D sonar.projectKey=ebox -D sonar.java.binaries=./target/
# sonar.sources=[sonar检测的源文件目录]
# sonar.projectname=[sonarqube上的对应项目的名称]
# sonar.login=[步骤2创建的token]
# sonar.projectKey[sonarqube上的对应项目的key]
# sonar.java.binaries=[jar包路径]
  1. 登录sonarqube查看项目状态

集成OpenLDAP

$ vim conf/sonar.properties

# LDAP configuration
# General Configuration
sonar.security.realm=LDAP
ldap.url=ldap://192.168.254.31  # OpenLDAP服务器
ldap.bindDn=cn=admin,dc=wlhiot,dc=com  # 用户
ldap.bindPassword=openldap  # 密码

# User Configuration
ldap.user.baseDn=ou=product,ou=wlhiot,dc=wlhiot,dc=com
ldap.user.request=(&(objectClass=inetOrgPerson)(uid={login}))
ldap.user.realNameAttribute=cn
ldap.user.emailAttribute=mail

# Group Configuration
ldap.group.baseDn=ou=product,ou=wlhiot,dc=wlhiot,dc=com
ldap.group.request=(&(objectClass=posixGroup)(memberUid={uid}))