k8s部署SonarQube

k8s部署SonarQube

Scroll Down

环境说明:
Kubernetes 版本:1.15.4
SonarQube 版本:7.9
数据持久化配置: NFS

SonarQube 介绍

简介

SonarQube 是一个用于代码质量管理的开源平台,用于管理源代码的质量;SonarQube 还对大量的持续集成工具提供了接口支持,可以很方便地在持续集成中使用 SonarQube,此外 SonarQube 的插件还可以对 Java 以外的其他编程语言提供支持,对国际化以及报告文档化也有良好的支持

特性

  • 多语言的平台: 支持超过20种编程语言,包括Java、Python、C#、C/C++、JavaScript等常用语言
  • 自定义规则: 用户可根据不同项目自定义Quality Profile以及Quality Gates
  • 丰富的插件: SonarQube 拥有丰富的插件,从而拥有强大的可扩展性
  • 持续集成: 通过对某项目的持续扫描,可以对该项目的代码质量做长期的把控,并且预防新增代码中的不严谨和冗余
  • 质量门: 在扫描代码后可以通过对“质量门”的比对判定此次“构建”的结果是否通过,质量门可以由用户定义,由多维度判定是否通过

部署过程描述

这里我们将 SonarQube 部署到 Kubernetes 中需要提前知道的是 SonarQube 需要依赖数据库存储数据,且 SonarQube7.9 及其以后版本将不再支持 Mysql,所以这里推荐设置 PostgreSQL 作为 SonarQube 的存储库,下面将记录在 Kubernetes 中部署 PostgreSQL 和 SonarQube 过程

部署 SonarQube

部署 PostgreSQL

[root@k8s01 sonarqube]# vim postgres.yaml
apiVersion: v1
kind: Service
metadata:
  name: postgres
  namespace: test-env
  labels:
    app: postgres
spec:
  type: NodePort        #指定为 NodePort 方式暴露出口
  ports:
    - name: server
      port: 5432
      targetPort: 5432
      nodePort: 30543   #指定 Nodeport 端口
      protocol: TCP
  selector:
    app: postgres
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: postgres-data
  namespace: test-env
  labels:
    app: postgres
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 5Gi
  storageClassName: managed-nfs-storage
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: postgres
  namespace: test-env
  labels:
    app: postgres
spec:
  replicas: 1
  selector:
    matchLabels:
      app: postgres
  template:
    metadata:
      labels:
        app: postgres
    spec:
      containers:
      - name: postgres
        image: postgres:11.4
        imagePullPolicy: "IfNotPresent"
        ports:
        - containerPort: 5432
        env:
        - name: POSTGRES_DB             #PostgreSQL 数据库名称
          value: "sonarDB"
        - name: POSTGRES_USER           #PostgreSQL 用户名
          value: "sonarUser"
        - name: POSTGRES_PASSWORD       #PostgreSQL 密码
          value: "123456"
        resources:
          limits:
            cpu: 1000m
            memory: 2048Mi
          requests:
            cpu: 500m
            memory: 1024Mi
        volumeMounts:
          - mountPath: /var/lib/postgresql/data
            name: postgredb
      volumes:
        - name: postgredb
          persistentVolumeClaim:
            claimName: postgres-data
            
[root@k8s01 sonarqube]# kubectl apply -f postgres.yaml
service/postgres created
persistentvolumeclaim/postgres-data created
deployment.apps/postgres created
[root@k8s01 sonarqube]# kubectl get -n test-env po
NAME                        READY   STATUS    RESTARTS   AGE
postgres-75cb4fdb48-lp9wf   1/1     Running   0          69s   

部署 SonarQube

[root@k8s01 sonarqube]# vim sonarqube.yaml
apiVersion: v1
kind: Service
metadata:
  name: sonarqube
  namespace: test-env
  labels:
    app: sonarqube
spec:
  type: NodePort            #指定 NodePort 端口
  ports:
    - name: sonarqube
      port: 9000
      targetPort: 9000
      nodePort: 30900       #指定 NodePort 端口
      protocol: TCP
  selector:
    app: sonarqube
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: sonarqube-data
  namespace: test-env
  labels:
    app: sonarqube
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 5Gi
  storageClassName: managed-nfs-storage
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: sonarqube
  namespace: test-env
  labels:
    app: sonarqube
spec:
  replicas: 1
  selector:
    matchLabels:
      app: sonarqube
  template:
    metadata:
      labels:
        app: sonarqube
    spec:
      initContainers:               #设置初始化镜像,执行 system 命令
      - name: init-sysctl
        image: busybox
        imagePullPolicy: IfNotPresent
        command: ["sysctl", "-w", "vm.max_map_count=262144"]  #必须设置vm.max_map_count这个值调整内存权限,否则启动可能报错
        securityContext:
          privileged: true          #赋予权限能执行系统命令
      containers:
      - name: sonarqube
        image: "sonarqube:7.9-community"
        ports:
        - containerPort: 9000
        env:
        - name: SONARQUBE_JDBC_USERNAME
          value: "sonarUser"        #引用 PostgreSQL 配置中设置的用户名
        - name: SONARQUBE_JDBC_PASSWORD
          value: "123456"           #引用 PostgreSQL 配置中设置的密码
        - name: SONARQUBE_JDBC_URL
          value: "jdbc:postgresql://postgres:5432/sonarDB"   #指定 PostgreSQL 在 Kubernetes 中的地址
        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: sonarqube
          subPath: conf
        - mountPath: /opt/sonarqube/data
          name: sonarqube
          subPath: data
        - mountPath: /opt/sonarqube/extensions
          name: sonarqube
          subPath: extensions
      volumes:
      - name: sonarqube
        persistentVolumeClaim:
          claimName: sonarqube-data    #绑定上面创建的 PVC
          
[root@k8s01 sonarqube]# kubectl apply -f sonarqube.yaml
service/sonarqube created
persistentvolumeclaim/sonarqube-data created
deployment.apps/sonarqube created          
[root@k8s01 sonarqube]# kubectl get -n test-env po
NAME                         READY   STATUS    RESTARTS   AGE
postgres-75cb4fdb48-lp9wf    1/1     Running   0          13m
sonarqube-76786f7d95-9ps5m   1/1     Running   0          4m19s

注意:如果项目启动失败,或者显示无法执行 initContainers 操作,那么可能是没有 RBAC 权限导致,请创建一个有一定权限的 ServiceAccount 后,再在 SonarQube 部署文件中指定这个 ServiceAccount 即可
至此SonarQube已经搭建完成,可以通过IP+端口号访问,当然也可以配置域名sonal.k8s.com来访问,即通过添加ingress来完成

[root@k8s01 sonarqube]# vim ing.yaml
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: test-ing
  namespace: test-env
spec:
  entryPoints:
  - web
  routes:
  - match: Host(`sonar.k8s.com`)
    kind: Rule
    services:
      - name: sonarqube
        port: 9000
[root@k8s01 sonarqube]# kubectl apply -f ing.yaml
ingressroute.traefik.containo.us/test-ing created
[root@k8s01 sonarqube]# kubectl get -n test-env ingressroute
NAME       AGE
test-ing   16s

完成后本地添加hosts或者域名解析

配置 SonarQube

登录 SonarQube

通过sonar.k8s.com或者192.168.200.81:30090登录
sonar1.png
输入默认用户名”admin”,密码与用户名一致,进而登录到 SonarQube 控制台
sonar2.png

SonarQube 安装插件

SonarQube 需要安装许多插件来完善这个工具,这里安装 Chinese 和 SonarJava 俩个插件,其中第一个插件为界面提供汉化,第二个插件是 Java 语言分析插件,当然也可以选择你自己想安装的插件进行安装
待安装插件列表:

  • Chinese
  • SonarJava

安装 Chinese

打开 Administration->Marktplace ,然后搜索栏输入 “Chinese” ,等待一段时间(国内访问国外地址比较慢)后弹出相关插件列表,选择 Chinese Pack 进行安装
sonar3.png
安装完成后会弹出重启 SonarQube 服务的窗口,点击一下进行容器,再次进入后可以看到界面已经汉化
sonar4.png

安装 SonarJava

安装过程跟上面类似,搜索 “Java” 选择 SonarJava 插件安装
sonar5.png

安装过程中遇到的问题

对 Mysql 不再支持

SonarQube7.9 及以后版本将不再支持 Mysql,请使用 Postgresql 数据库

2020.07.04 04:40:50 INFO  web[][o.s.p.ProcessEntryPoint] Starting web
2020.07.04 04:40:50 INFO  web[][o.a.t.u.n.NioSelectorPool] Using a shared selector for servlet write/read
2020.07.04 04:40:51 INFO  web[][o.e.p.PluginsService] no modules loaded
2020.07.04 04:40:51 INFO  web[][o.e.p.PluginsService] loaded plugin [org.elasticsearch.join.ParentJoinPlugin]
2020.07.04 04:40:51 INFO  web[][o.e.p.PluginsService] loaded plugin [org.elasticsearch.percolator.PercolatorPlugin]
2020.07.04 04:40:51 INFO  web[][o.e.p.PluginsService] loaded plugin [org.elasticsearch.transport.Netty4Plugin]
2020.07.04 04:40:53 INFO  web[][o.s.s.e.EsClientProvider] Connected to local Elasticsearch: [127.0.0.1:9001]
2020.07.04 04:40:53 INFO  web[][o.s.s.p.LogServerVersion] SonarQube Server / 7.9.0.26994 / 687d8007c0f62bfaaa44a890d93397de0a588119
2020.07.04 04:40:53 ERROR web[][o.s.s.p.Platform] Web server startup failed: 
#############################################################################################################
#         End of Life of MySQL Support : SonarQube 7.9 and future versions do not support MySQL.            #
#         Please migrate to a supported database. Get more details at                                       #
#         https://community.sonarsource.com/t/end-of-life-of-mysql-support                                  #
#         and https://github.com/SonarSource/mysql-migrator                                                 #
#############################################################################################################

vm.max_map_count 错误

2020.07.04 04:39:13 INFO  app[][o.e.p.PluginsService] loaded plugin [org.elasticsearch.transport.Netty4Plugin]
ERROR: [1] bootstrap checks failed
[1]: max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144]
2020.07.04 04:39:19 WARN  app[][o.s.a.p.AbstractManagedProcess] Process exited with exit value [es]: 78

这个错误主要是镜像系统中设置的内存权限过小,需要初始化容器时候执行”sysctl -w vm.max_map_count=262144”命令,可以按下面方法解决:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: sonarqube-server
  labels:
    app: sonarqube-server
spec:
  replicas: 1
  selector:
    matchLabels:
      app: sonarqube-server
  template:
    metadata:
      labels:
        app: sonarqube-server
    spec:
      initContainers:               #设置初始化镜像,执行 system 命令
      - name: init-sysctl
        image: busybox
        imagePullPolicy: IfNotPresent
        command: ["sysctl", "-w", "vm.max_map_count=262144"]
        securityContext:
          privileged: true
        ......

exited with exit value [es] 错误

2020.07.04 02:40:53 WARN  app[][o.s.a.p.AbstractProcessMonitor] Process exited with exit value [es]: 1

发现这个错误主要原因是,Sonarqube 要求以非 root 用户启动,如果设置容器安全”runAsUser: 0”等参数,以 root 用户运行就会抛出以下错误,去掉 root 用户权限,设置镜像默认用户启动即可