Đăng vào

Dùng ArgoCD cài đặt SonarQube Community trên Kubernetes

Giới thiệu

SonarQube Community Edition là phiên bản miễn phí và mã nguồn mở của nền tảng SonarQube – một công cụ mạnh mẽ để phân tích chất lượng mã nguồn (Static Code Analysis). Phiên bản này phù hợp cho các cá nhân, nhóm nhỏ hoặc tổ chức muốn kiểm tra lỗi, bảo mật và các vấn đề về chất lượng mã mà không cần trả phí.

Tính năng chính của SonarQube Community Edition

  1. Phát hiện lỗi và mã xấu (Code Smells)

    • Tự động quét mã nguồn (Java, C#, JavaScript, Python, Go, PHP, v.v.) để tìm lỗi, lỗ hổng bảo mật và mã khó bảo trì.
    • Phân tích theo tiêu chuẩn CWE, OWASP Top 10 (một phần).
  2. Đo lường chất lượng mã

    • Đánh giá độ phức tạp, tỷ lệ trùng lặp, số lượng lỗi, và các chỉ số khác.
    • Tính toán Technical Debt (nợ kỹ thuật) để ước lượng thời gian cần để sửa chữa.
  3. Hỗ trợ nhiều ngôn ngữ

    • Hỗ trợ 20+ ngôn ngữ (Java, Python, C/C++, JavaScript, TypeScript, Kotlin, v.v.), nhưng một số tính năng nâng cao (như phân tích .NET) chỉ có ở bản trả phí.
  4. Tích hợp với CI/CD

    • Làm việc với Jenkins, GitLab CI, GitHub Actions, Azure DevOps để tự động hóa quét mã.
  5. Báo cáo và Dashboard

    • Giao diện trực quan hiển thị chi tiết các vấn đề, xu hướng chất lượng mã theo thời gian.

Hạn chế so với bản trả phí (Developer/Enterprise)

  • Không hỗ trợ một số ngôn ngữ như Swift, ABAP, T-SQL.
  • Không có tính năng Pull Request Analysis (tích hợp trực tiếp vào GitHub/GitLab để review code).
  • Giới hạn rules (quy tắc kiểm tra) so với bản trả phí.
  • Không hỗ trợ LDAP/Active Directory (chỉ có cơ chế đăng nhập cơ bản).

Mặc dù bản SonarQube Community có nhiều hạn chế nhưng đối với các dự án nhỏ, ngân sách hạn chế chúng ta vẫn có thể sử dụng nó nhằm đảm bảo chất lượng của dự án.

Cài đặt

Về cách cài cài đặt thì SonarQue hỗ trợ nhiều phương thức như: cài trực tiếp trên Server, sử dụng docker compose, hoặc helm chart nếu cài đặt trên Kubernetes cluster.

Trong bài viết này mình sẽ trình bày cách cài đặt SonarQube trên Kubernetes cluster bằng ArgoCD.

Thiết lập Database Postgres

Việc cài đặt SonarQue đòi hỏi chúng ta phải cung cấp 1 database Postgres để lưu trữ các thông tin cần thiết.

Tốt nhất là bạn nên có 1 server chuyên dụng hoặc sử dụng các dịch vụ Database chuyên nghiệp để việc quản lý, sao lưu,... được dễ sàng và thuận tiện nhất.

Hiện tại việc cài đặt và vận hành Database trên Kubernetes cluster ở môi trường Production là hoàn toàn có thể, tuy nhiên việc triển khai và vận hành sẽ phức tap hơn rất nhiều so Với phương thức truyền thống.

Trong ví dụ này, mục đích để test việc cài đặt và hơn nữa mình không có database riêng nên sẽ sử dụng CloudNativePG làm giải pháp Database. Ở bài viết trước mình đã có giới thiệu cách cài đặt CloudNativePG trên Kubernetes bằng ArgoCD

sonarqube.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: sonarqube
  namespace: argocd
  finalizers:
    - resources-finalizer.argocd.argoproj.io
  labels:
    name: sonarqube
spec:
  syncPolicy:
    automated:
      selfHeal: true
      prune: true
      allowEmpty: false
    syncOptions:
      - Validate=false
      - CreateNamespace=true
      - PrunePropagationPolicy=foreground
      - PruneLast=true
      - RespectIgnoreDifferences=true
      - Replace=true
  project: default
  sources:    
    - chart: cluster
      repoURL: https://cloudnative-pg.github.io/charts
      targetRevision: 0.*
      helm:
        releaseName: sonarqube-db
        passCredentials: false
        parameters:
          - name: "version.postgresql"
            value: "13"
            forceString: true
          - name: "cluster.instances"
            value: "1"
          - name: "cluster.superuserSecret"
            value: "supperadmin-cred"
          - name: "cluster.storage.storageClass"
            value: "nfs-csi"
          - name: "cluster.walStorage.storageClass"
            value: "nfs-csi"
          - name: "cluster.walStorage.enabled"
            value: "true"
          - name: "cluster.monitoring.enabled"
            value: "true"
          - name: "cluster.initdb.database"
            value: "sonarqube"
          - name: "cluster.initdb.owner"
            value: "sonarqube"
          - name: "cluster.initdb.secret.name"
            value: "admin-cred"
    - repoURL: https://github.com/your-repo/gitops
      targetRevision: HEAD
      path: deploys/sonarqube-community/manifests
  destination:
    server: "https://kubernetes.default.svc"
    namespace: sonarqube
  revisionHistoryLimit: 3
  ignoreDifferences:
    - jsonPointers:
        - /spec/volumeName
        - /spec/storageClassName
      kind: PersistentVolumeClaim

Với cấu hình file YAML của ArgoCD ở trên, chúng ta thấy nó bao gồm 2 sources:

  • https://cloudnative-pg.github.io/charts: Đây là đường dẫn đến Helm chart của CloudNativePG, toàn bộ các cấu hình bạn vui lòng xem trên file values.yaml của chart. Dưới đây là một

    • cluster.superuserSecret: secret chứa thông tin của supper user
    • cluster.initdb.database: tên của database được tạo sau khi cài đặt xong Helm chart ở trên
    • cluster.initdb.owner: username của admin ứng với database vừa được khởi tạo
    • cluster.initdb.secret.name: secret chửa thông tin username và password của cluster.initdb.owner
  • https://github.com/your-repo/gitops: Đây là đường dẫn đến GitHub nơi lưu một vài cấu hình mà không có trong Helm Chart. Ở đây, mình sẽ để một file sealedsecrets.yaml dùng để khai báo Secrets cho cluster.superuserSecretcluster.initdb.secret.name. Tuy nhiên, nếu để thông tin Secret mà để trên Git thì rất nguy hiểm, nên mình khuyến cáo nên mã hóa lại bằng SealedSecret (Xem thêm: Quản lý secrets trên Kubernetes bằng Bitnami Sealed Secrets) và có thể an toàn để lên Git.

    sealedsecrets.yaml
    ---
    apiVersion: bitnami.com/v1alpha1
    kind: SealedSecret
    metadata:
      name: supperuser-cred
      namespace: sonarqube
    spec:
      encryptedData:
        password: AgAAuFvOiX4Gky0NEJ6GVB1eisTaO9e1XvJn7yV7yVh97Ft3FNpryZSPOG9P...
        username: AgCWO2bwNIPoPl7QNOqSraVDOl7vDSeFiiZpK3ahA2HhFtuC8N8lEwrmDGA1...
      template:
        metadata:
          name: supperuser-cred
          namespace: sonarqube
        type: kubernetes.io/basic-auth
    ---
    apiVersion: bitnami.com/v1alpha1
    kind: SealedSecret
    metadata:
      name: admin-cred
      namespace: sonarqube
    spec:
      encryptedData:
        password: AgB4Hd6S/ORdxC9LlKCbR5NMFe8iJn5wKDdO+wa7IxNMwGpQqkH4rza8HweZ...
        username: AgBmI65fFZLygTs+YkGQx5OArXDNDdyF5dt2GHmahKoVCbcohiAauXUfFVcB...
      template:
        metadata:
          name: admin-cred
          namespace: sonarqube
        type: kubernetes.io/basic-auth
    ---
    apiVersion: bitnami.com/v1alpha1
    kind: SealedSecret
    metadata:
      name: monitoring-passcode
      namespace: sonarqube
    spec:
      encryptedData:
        passcode: AgBLjK3wbtS/yuxVgEZxbEEkgpHtetS432fnpttlIYS1QQ84i+8b70ct...
      template:
        metadata:
          name: monitoring-passcode
          namespace: sonarqube
        type: Opaque
    

Thiết lập SonarQube

Bước tiếp theo, mình sẽ thêm phần cấu hình dành cho Helm Chart SonarQube, chúng ta viết tếp cho file sonarqube.yaml ở trên:

sonarqube.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: sonarqube
  namespace: argocd
  finalizers:
    - resources-finalizer.argocd.argoproj.io
  labels:
    name: sonarqube
spec:
  syncPolicy:
    automated:
      selfHeal: true
      prune: true
      allowEmpty: false
    syncOptions:
      - Validate=false
      - CreateNamespace=true
      - PrunePropagationPolicy=foreground
      - PruneLast=true
      - RespectIgnoreDifferences=true
      - Replace=true
  project: default
  sources:
    - chart: sonarqube
      repoURL: https://sonarsource.github.io/helm-chart-sonarqube
      targetRevision: 2025.*
      helm:
        releaseName: sonarqube
        passCredentials: false
        parameters:
          - name: "fullnameOverride"
            value: "sonarqube"
          - name: "revisionHistoryLimit"
            value: "3"
          - name: "persistence.enabled"
            value: "true"
          - name: "ingress.enabled"
            value: "true"
          - name: "persistence.storageClass"
            value: "nfs-csi"
          - name: "jdbcOverwrite.enabled"
            value: "true"
          - name: "jdbcOverwrite.enable"
            value: "true"
          - name: "jdbcOverwrite.jdbcUrl"
            value: "jdbc:postgresql://sonarqube-db-cluster-rw.sonarqube.svc/sonarqube"
          - name: "jdbcOverwrite.jdbcUsername"
            value: "sonarqube"
          - name: "jdbcOverwrite.jdbcSecretName"
            value: "admin-cred"
          - name: "jdbcOverwrite.jdbcSecretPasswordKey"
            value: "password"
          - name: "postgresql.enabled"
            value: "false"
          - name: "community.enabled"
            value: "true"
          - name: "monitoringPasscodeSecretName"
            value: "monitoring-passcode"
          - name: "monitoringPasscodeSecretKey"
            value: "passcode"
        valuesObject:
          ingress:
            enabled: true
            hosts:
              - name: your-sonarqube-domain.com
            annotations:
              cert-manager.io/cluster-issuer: letsencrypt-prod
            ingressClassName: nginx
            tls:
              - secretName: sonarqube-tls
                hosts:
                  - your-sonarqube-domain.com
    - chart: cluster
      repoURL: https://cloudnative-pg.github.io/charts
      targetRevision: 0.*
      ....
    - repoURL: https://github.com/your-repo/gitops
      targetRevision: HEAD
      path: deploys/sonarqube-community/manifests
  destination:
    server: "https://kubernetes.default.svc"
    namespace: sonarqube
  revisionHistoryLimit: 3
  ignoreDifferences:
    - jsonPointers:
        - /spec/volumeName
        - /spec/storageClassName
      kind: PersistentVolumeClaim

Cuối cùng chỉ cần chạy kubectl apply -f sonarqube.yaml và kiểm tra trên ArgoCD

Sau khi deploy thành công, bước đầu tiên là đăng nhập với username: admin và mật khẩu là admin

Bản SonarQube Community thì không hỗ trợ thiết lập SSO, bạn muốn dùng phải cài thêm plugin khác.

Tiếp theo là đổi mật khẩu cho user admin

Giao diện chính sẽ như thế này

HomeLab Kubernetes cluster của mình khá yêu nên không thể chạy thử vài job scan để giới thiệu được, bài viết tới đây là kết thúc

Chúc thành công,

ANH NGUYỄN

Hiện tại mình đang tìm kiếm công việc mới với nhiều thử thách để chinh phục.

Mọi thông tin có thể gửi về me@nvtienanh.info.