Published on

Dùng Argo CD triển khai hệ thống giám sát cho cụm Kubernetes bằng Prometheus và Grafana

Giới thiệu

Trong bài đầu tiên của năm 2024 mình sẽ tiếp tục với chủ đề về Kubernetes bởi vì nó có liên quan đến công việc hiện tại đang làm. Các bài viết trong năm 2023 chủ yếu mình có đề cập đến việc làm sao để xây dựng được một Kubernetes on-premise và triển khai các ứng dụng cơ bản trên đó. Khi cluster được sử dụng để deploy (triển khai) nhiều ứng dụng với muc đích khác nhau thì chúng ta cần thiết phải quản lý, giám sát tình trạng hoạt động, tình hình tài nguyên của hệ thống, ...

Bài viết này mình sẽ đề cập đến giải pháp giám sát (monitoring) các ứng dụng được triển khai trên Kubernetes cluster, từ đó giúp chúng ta có cái nhìn tổng thể về trạng thái của hệ thống, của từng ứng dụng được giám sát từ đó tìm ra nguyên nhân khi hệ thống gặp vấn đề.

kube-prometheus-stack

Kube-prometheus-stack là một bộ công cụ giúp bạn cài đặt và cấu hình Prometheus và Grafana trên Kubernetes cluster một cách dễ dàng và nhanh chóng. Kube-prometheus-stack sử dụng Helm chart để quản lý các thành phần của Prometheus và Grafana, bao gồm các service, deployment, configmap, secret, service monitor, alert manager, dashboard, rule, và các tài nguyên khác. Kube-prometheus-stack cũng tích hợp sẵn các cảnh báo và dashboard sẵn sàng cho các thành phần của Kubernetes như node, pod, service, ingress, và các ứng dụng chạy trên cluster.

Với kube-prometheus-stack, bạn có thể dễ dàng giám sát và hiển thị các thông số của hệ thống Kubernetes, như tình trạng của các node, pod, service, tài nguyên CPU, RAM, disk, network, lưu lượng truy cập, thời gian phản hồi, số lượng yêu cầu, lỗi, và nhiều thông số khác. Bạn cũng có thể thiết lập các cảnh báo khi có sự cố xảy ra, và nhận được thông báo qua email, telegram, hoặc các kênh khác.

Chi tiết có thể xem thêm charts/kube-prometheus-stack

Sử dụng Argo CD để triển khai kube-prometheus-stack

Dưới đây mình sẽ giới thiệu sơ qua manifest mà mình sử dụng để các bạn có thể tham khảo

Argo CD Applications

monitoring.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: monitoring
  namespace: argocd
  finalizers:
    - resources-finalizer.argocd.argoproj.io
spec:
  syncPolicy:
    automated:
      selfHeal: true
      prune: true
      allowEmpty: false
    syncOptions:
      - Validate=false
      - CreateNamespace=true
      - PrunePropagationPolicy=foreground
      - PruneLast=true
      - RespectIgnoreDifferences=true
      - Replace=false
      - ApplyOutOfSyncOnly=true
      - ServerSideApply=true
  project: default
  sources:
    - chart: kube-prometheus-stack
      repoURL: https://prometheus-community.github.io/helm-charts
      targetRevision: 56.*
      helm:
        releaseName: monitoring
        passCredentials: false
        parameters:
        - name: "windowsMonitoring.enabled"
          value: "false"
        - name: "grafana.ingress.enabled"
          value: "true"
        valueFiles:
          - $values/configs/monitoring/values/prometheus.yaml
          - $values/configs/monitoring/values/grafana.yaml
    - repoURL: https://github.com/your-user/your-gitops-repo.git
      targetRevision: HEAD
      path: configs/monitoring
      ref: values
    - repoURL: https://github.com/dotdc/grafana-dashboards-kubernetes
      targetRevision: HEAD
      path: ./
  destination:
    server: "https://kubernetes.default.svc"
    namespace: monitoring
  revisionHistoryLimit: 5
  ignoreDifferences:
  - jsonPointers:
    - /spec/volumeName
    - /spec/storageClassName
    kind: PersistentVolumeClaim

Một vài điểm lưu ý:

  • Dòng 39-42: là nơi lấy các cấu hình dành cho Helm chart, nó khá dài vì vậy mình lưu hở một repo riêng để dễ dàng quản lý. Nội dung của file này có thể xem thêm ở dưới. Sau thì thiết lập xong thì đẩy lên git repo của bạn.
  • Dòng 43-45: là repo nơi mình lấy một vài dashboard khá hữu ích dành cho Grafana

Cấu hình Prometheus

Hầu như mình để tất cả giá trị mặc định, mình chỉ chỉnh sửa phần storage cho giống với storage class mà cluster của mình đang sử dụng

prometheus.yaml
prometheusSpec:
  storageSpec:
    volumeClaimTemplate:
      spec:
        storageClassName: nfs-storage
        accessModes: ["ReadWriteOnce"]
        resources:
          requests:
            storage: 4Gi
      selector: {}

Cấu hình Grafana

grafana.yaml
grafana:
  envFromSecret: "azure-ad-client-secret"
  sidecar:
    dashboards:
      annotations:
        grafana_folder: "default"
      folderAnnotation: grafana_folder
      provider:
        foldersFromFilesStructure: true
  ingress:
    enabled: true
    ingressClassName: nginx
    annotations:
      cert-manager.io/cluster-issuer: letsencrypt-prod
    hosts:
      - your-grafana-domain.com
    tls:
    - secretName: ssl-your-grafana-domain.com
      hosts:
        - your-grafana-domain.com
  persistence:
    enabled: true
    type: pvc
    storageClassName: "nfs-storage"
    accessModes:
      - ReadWriteOnce
    size: 10Gi
    finalizers:
      - kubernetes.io/pvc-protection
  resources:
    limits:
      cpu: 200m
      memory: 512Mi
    requests:
      cpu: 100m
      memory: 256Mi
  grafana.ini:
    server:
      root_url: https://your-grafana-domain.com
    auth.azuread:
      icon: microsoft
      enabled: true
      allow_sign_up: true
      auto_login: false
      client_id: <your-azure-client-id>
      scopes: openid email profile
      auth_url: https://login.microsoftonline.com/<your-azure-tenant-id>/oauth2/v2.0/authorize
      token_url: https://login.microsoftonline.com/<your-azure-tenant-id>/oauth2/v2.0/token
      role_attribute_strict: false
      allow_assign_grafana_admin: true
      # prevent synchronizing users organization roles
      skip_org_role_sync: false

Trong cấu hình cho Grafana mình sử dụng SSO dùng Microsoft Entra ID (Azure AD), dưới đây là một vài giải thích cơ bản:

  • Dòng 2: là Kubernetes Secret chửa Client Secret của Microsoft Entra ID application mà bạn sử dụng để thiết lập SSO cho Grafana
  • Dòng 10-20: là cấu hình ingress dùng để truy cập vào Grafana. Mình sử dụng Ingress Nginx + SSL (letsencrypt). Bạn có thể xem thêm bài viết trước của mình Tạo chứng chỉ Let’s Encrypt trên Kubernetes
  • Dòng 24: Đây là storage class mà cluster mình sử dụng. Nếu bạn dùng loại khác thì nhớ đổi lại.
  • Dòng 39: Đây là tên miền dùng để truy cập vào Grafana. Nó sẽ giống với tên miền trong phần cấu hình Ingress.
  • Dòng 45: Cập nhật giá trị <your-azure-client-id> của bạn
  • Dòng 47-48: Cập nhật giá trị <your-azure-tenant-id> của bạn
  • Cách thiết lập SSO cho Grafana các bạn có thể đọc thêm Configure Azure AD OAuth2 authentication

Grafana envFromSecret

Như đã nói ở trên mình sử dụng cần lưu Client Secret của Microsoft Entra ID trên cluster, nên mình sẽ tạo 1 secret tên azure-ad-client-secret. Trên cluster của mình sử dụng SealedSecret để cho phép quản lý secrets và đẩy lên git một cách an toàn.

secrets.yaml
apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
metadata:
  name: azure-ad-client-secret
spec:
  encryptedData:
    GF_AUTH_AZUREAD_CLIENT_SECRET: <your-encrypted-secret>
  template:
    metadata:
      name: azure-ad-client-secret
      namespace: monitoring

Sau khi mọi thứ đã chuẩn bị xong, chúng ta chỉ cần chạy vài câu lệnh đơn giản

kubectl create namespace monitoring
kubectl -n monitoring apply -f secrets.yaml
kubectl -n monitoring apply -f monitoring.yaml

Như vậy mỗi khi bạn cập nhật cấu hình của prometheus hoặc grafana thì sẽ được Argo CD tự động cập nhật nhờ tính năng auto sync.

Dưới đây là một dashboard mẫu trên cluster của mình

Chúc thành công!

Anh Nguyễn