Monitoring Kubernetes Cluster với Prometheus-Grafana Stack (kỳ 2)

Nội dung

  • Giới thiệu
  • Prometheus
  • Thành phần chính của Prometheus
  • Install Prometheus thông qua Rancher catalog UI
  • Install Prometheus sử dụng Helm
  • Kết luận
  • Tài liệu tham khảo

Giới thiệu

Ở kỳ 1, mình đã giới thiệu qua về Prometheus, Grafana và có demo cài đặt và tạo biểu đồ monitoring đơn giản. Bài viết này sẽ không nói lại những kiến thức cũ mà sẽ nói thêm các kiến thức bổ sung, giới thiệu 2 cách cài đặt Prometheus bằng Rancher catalog UI và Helm. Khi sử dụng Helm có phát sinh vấn đề, mình sẽ chia sẻ vấn đề đó và cách giải quyết nó.
Các bạn có thể đọc lại bài viết ở kỳ 1 để năm qua các khai niệm, cũng như hình dung cách Prometheus hoặt động (chỉ tham khảo thôi nhé). Kỳ 2 này mình sẽ fix lại một số điểm trong quá trình cài đặt, làm sao cho chuẩn hơn, thuận tiện hơn.

Đặt vấn đề

Rancher UI là một công cụ khá hữu ích trong việc monitoring cluter để có thể giải quyết các vấn đề phát sinh, tuy nhiên nó chưa phải là công cụ monitoring tuyệt vời nhất. Các đại diện công cụ monitoring cho Kubernetes là DatadogPrometheus . Lần này mình sẽ tìm hiểu về Prometheus và tiến hành cài đặt. Đi với Prometheus mình có công cụ Grafana, công cụ này thường được chọn để đi kèm với Prometheus. Sử dụng 2 công cụ trên cho phép ta tạo các biểu đồ cự đẹp và dễ nhìn để monitoring Kubernetes resource.

Prometheus

Vốn dĩ Prometheus là project của công ty SoundCloud phát hành, là công cụ dùng để monitoring và Alert. Từ năm 2016, gia nhập vào công ty CNCF, tháng 8/2018 chính thức release.
Tổng quan về kiến trúc của Prometheus như hình bên dưới.

Các thành phần quan trọng

Để có thể hiểu được cơ chế monitoring của Prometheus, đầu tiên chúng ta cần biết được 2 thành phần chính sau đây:

Tên Nội dung
exporter
  • Chương trình chạy trên các máy đối tượng để monitoring
  • Giống như một Web API để công khai các thông tin resource dưới dạng text
  • Tương ứng với mỗi loại resource khác nhau sẽ có các exporter khác nhau
  • prometheus
  • Là một monitoring server program
  • Thăm dò tất cả các exporter và thu thập thông tin resource thời gian định kỳ
  • Dữ liệu monitoring được lưu trữ trong DB của Prometheus
  • Mỗi thành phần phía trên hiện tại đã được cung cấp bằng docker images, chỉ bằng cách thiết lập đơn giản như sau, chúng ta đã có thể monitoring (resource) được rồi.

    • Tại server muốn monitor, khởi chạy exporter docker container
    • Tại server muốn lưu trữ data monitor chạy Prometheus docker conatainer

    Các loại Exporter

    Trên các server đối tượng monitor, Với mỗi loại resource mình muốn monitor, mình sẽ khởi chạy các exporter tương ứng. Mỗi middleware vendor khác nhau sẽ cung cấp các exporter khác nhau. Vì vậy có rất nhiều loại Exporter.
    https://prometheus.io/docs/instrumenting/exporters/
    Loại Exporter thông dụng nhất là node_exporter: Thu thập các thông tin như CPU, Memory vv của máy vật lý.
    https://github.com/prometheus/node_exporter
    Để thu thập thông tin từ máy GPU thì chúng ta cần thêm nvidia_exporter.
    https://github.com/Nextremer/nvidia_exporter

    Data được thu tập từ Exporter

    Ví dụ chúng ta truy cập trực tiếp bằng lệnh curl đến data được công khai của node_exporter, kiểu data như dưới đây sẽ được trả về. Nó chỉ trả về giá trị do được của resource tại thời điểm truy cập ở định dạng text.
    Prometheus server sẽ thu thập data và lưu trữ data này theo định kỳ

    $ curl http://hogehoge:9100/metrics
    # HELP go_gc_duration_seconds A summary of the GC invocation durations.
    # TYPE go_gc_duration_seconds summary
    go_gc_duration_seconds{quantile="0"} 0.000111075
    go_gc_duration_seconds{quantile="0.25"} 0.000244251
    go_gc_duration_seconds{quantile="0.5"} 0.000264236
    go_gc_duration_seconds{quantile="0.75"} 0.000295209
    go_gc_duration_seconds{quantile="1"} 0.000693045
    go_gc_duration_seconds_sum 187.504344849
    go_gc_duration_seconds_count 237336
    ・・・
    

    Application cũng có thể trở thành 1 Exporter

    Nếu chúng ta hiểu được tổng quan về Exporter, có lẽ chúng ta sẽ muốn làm nhưng điều như là: số lương user tại thời điểm đó, hay số lượng đăng ký vv.
    Nếu chúng ta chuẩn bị sẵn API thu thập các thông tin ứng dụng trả về dưới định dạng Json thì dễ dàng tích hợp với exporter.
    Để thu thập log xuất ra từ Application giống như kiểu Kibana, khi xem phần FAQ của Prometheus thì chúng ta sẽ thấy có một công cụ gọi là "mtail". Công cụ này sẽ thu thập log, sau đo chuyển đổi thành dạng metrics.
    https://prometheus.io/docs/introduction/faq/#how-to-feed-logs-into-prometheus?
    https://github.com/google/mtail
    Thật ra nếu nói đến thu thập log thì tốt nhất chúng ta nên dùng ELK stack, hoặc EFK stack. log và metrics là khác nhau, sử dụng công cụ phù hợp để đạt hiệu quả tốt nhất.

    Biểu đồ hóa dữ liệu

    Data được thu thập từ các server đối tượng sẽ được lưu trữ vào DB của Prometheus dưới dạng time series, sử dụng GUI cung cấp mặc định của Prometheus, chúng ta có Graph như bên dưới:

    Để thu thập data ta sử dụng Prometheus query, quả thật cách sử dụng Prometheus query cũng rất khó khăn, tuy nhiên cứ hỏi google thì kiểu gì cũng có ai đó chỉ cho thôi :)
    https://prometheus.io/docs/querying/examples/

    Biểu đồ hóa bằng công cụ Grafana

    GUI cung cấp bởi Prometheus quả thật quá đơn giản, không có nhiều loại biểu đồ, ít tính năng. Cũng không trách được vì bản thân chức năng chính của Prometheus là Monitoring server và cung cấp DB để lưu trữ data.
    Biểu đồ hóa data bằng Grafana quả thật không gì tuyệt vời hơn.

    Quan hệ giữa Prometheus và Grafana cũng giống như Elasticsearch và Kibana

    Môi trường cài đặt

    Bây giờ chúng ta sẽ đi vào trọng tâm bài viết này là 2 cách cài đặt Prometheus.
    Môi trường mình sử dụng:

    • Kubernetes (1 master and 1 node)
    • Rancher v2.1.8 (Nếu các bạn không sử dụng Rancher thì cài đặt bằng cách 2 - sử dụng Helm)
    $ kubectl version
    Client Version: version.Info{Major:"1", Minor:"10", GitVersion:"v1.10.1", GitCommit:"d4ab47518836c750f9949b9e0d387f20fb92260b", GitTreeState:"clean", BuildDate:"2018-04-12T14:26:04Z", GoVersion:"go1.9.3", Compiler:"gc", Platform:"linux/amd64"}
    Server Version: version.Info{Major:"1", Minor:"10", GitVersion:"v1.10.1", GitCommit:"d4ab47518836c750f9949b9e0d387f20fb92260b", GitTreeState:"clean", BuildDate:"2018-04-12T14:14:26Z", GoVersion:"go1.9.3", Compiler:"gc", Platform:"linux/amd64"}
    

    Install Prometheus thông qua Rancher catalog UI

    Install

    Tham khảo: Phần Use Prometheus for Monitoring trong link: https://rancher.com/blog/2018/2018-10-18-monitoring-kubernetes/
    Khi Install Prometheus thì mặc định cũng cài luôn Grafana, nhớ setting passwork cho Grafana nhé, Namespace cứ để nguyên như vậy cũng OK, quá trình cài đặt có thể mất vài phút. Sau khi cài đặt xong chúng ta kiểm tra lại, giả sử mình cài đặt với namespace là prometheus-rnztg

    $ kubectl get all -n prometheus-rnztg
    NAME                                                       READY     STATUS    RESTARTS   AGE
    pod/prometheus-rnztg-alertmanager-976b66445-xk6jm          2/2       Running   0          21h
    pod/prometheus-rnztg-grafana-6b456867f9-lktgd              2/2       Running   0          21h
    pod/prometheus-rnztg-kube-state-metrics-6d9954479c-929jx   1/1       Running   0          21h
    pod/prometheus-rnztg-node-exporter-9g7vv                   1/1       Running   0          21h
    pod/prometheus-rnztg-node-exporter-c4kns                   1/1       Running   0          21h
    pod/prometheus-rnztg-server-64474768cb-57xff               2/2       Running   0          21h
     
    NAME                                          TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
    service/prometheus-rnztg-alertmanager         NodePort    10.43.248.98    <none>        80:31537/TCP   21h
    service/prometheus-rnztg-grafana              NodePort    10.43.11.155    <none>        80:31260/TCP   21h
    service/prometheus-rnztg-kube-state-metrics   ClusterIP   10.43.95.203    <none>        80/TCP         21h
    service/prometheus-rnztg-node-exporter        ClusterIP   10.43.222.130   <none>        9100/TCP       21h
    service/prometheus-rnztg-server               NodePort    10.43.32.172    <none>        80:31981/TCP   21h
     
    NAME                                            DESIRED   CURRENT   READY     UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE
    daemonset.apps/prometheus-rnztg-node-exporter   2         2         2         2            2           <none>          21h
     
    NAME                                                  DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
    deployment.apps/prometheus-rnztg-alertmanager         1         1         1            1           21h
    deployment.apps/prometheus-rnztg-grafana              1         1         1            1           21h
    deployment.apps/prometheus-rnztg-kube-state-metrics   1         1         1            1           21h
    deployment.apps/prometheus-rnztg-server               1         1         1            1           21h
     
    NAME                                                             DESIRED   CURRENT   READY     AGE
    replicaset.apps/prometheus-rnztg-alertmanager-976b66445          1         1         1         21h
    replicaset.apps/prometheus-rnztg-grafana-6b456867f9              1         1         1         21h
    replicaset.apps/prometheus-rnztg-kube-state-metrics-6d9954479c   1         1         1         21h
    replicaset.apps/prometheus-rnztg-server-64474768cb               1         1         1         21h
    

    Quan sát Pod với Service của Grafana và access đến http://192.168.33.50:31260

    Đến đây có vẻ như quá trình cài đặt ổn rồi.

    Update Manifest file

    $ kubectl get pods -o wide -n prometheus-rnztg
    NAME                                                   READY     STATUS    RESTARTS   AGE       IP              NODE
    prometheus-rnztg-alertmanager-976b66445-xk6jm          2/2       Running   2          22h       10.42.0.140     192.168.33.50
    prometheus-rnztg-grafana-6b456867f9-lktgd              2/2       Running   2          22h       10.42.0.141     192.168.33.50
    prometheus-rnztg-kube-state-metrics-6d9954479c-929jx   1/1       Running   1          22h       10.42.0.137     192.168.33.50
    prometheus-rnztg-node-exporter-9g7vv                   1/1       Running   1          22h       192.168.33.50   192.168.33.50
    prometheus-rnztg-node-exporter-c4kns                   1/1       Running   0          22h       192.168.33.51   192.168.33.51
    prometheus-rnztg-server-64474768cb-57xff               2/2       Running   2          22h       10.42.0.139     192.168.33.50
    

    Hiện tại đang thấy Prometheus server được schedule đến node 192.168.33.50, mình muốn thay đổi để prometheus server schedule đến server 192.168.33.51. Có 2 cách làm như sau:

    1. Update manifest file bằng Rancher UI


    Chúng ta sẽ thêm setting (chọn server để schedule) như bên dưới vào file -> Save

    affinity:
      nodeAffinity:
        requiredDuringSchedulingIgnoredDuringExecution:
          nodeSelectorTerms:
          - matchExpressions:
            - key: "app"
              operator: In
              values:
                - "consumer"
    

    "consumer" là label của node có IP 192.168.33.51

    Sau khi save thì kiểm tra lại:

    $ kubectl get pods -o wide -n prometheus-rnztg
    NAME                                                   READY     STATUS    RESTARTS   AGE       IP              NODE
    prometheus-rnztg-alertmanager-976b66445-xk6jm          2/2       Running   2          22h       10.42.0.140     192.168.33.50
    prometheus-rnztg-grafana-6b456867f9-lktgd              2/2       Running   2          22h       10.42.0.141     192.168.33.50
    prometheus-rnztg-kube-state-metrics-6d9954479c-929jx   1/1       Running   1          22h       10.42.0.137     192.168.33.50
    prometheus-rnztg-node-exporter-9g7vv                   1/1       Running   1          22h       192.168.33.50   192.168.33.50
    prometheus-rnztg-node-exporter-c4kns                   1/1       Running   0          22h       192.168.33.51   192.168.33.51
    prometheus-rnztg-server-7d44d88b9c-l9np5               2/2       Running   0          4m        10.42.1.81      192.168.33.51
    

    Ok rồi!

    2. Copy và lưu manifest file

    Bằng cách trên thì chúng ta có thể thay đổi setting theo ý muốn, nhưng khi gặp lỗi phải cài đặt lại vv thì nhưng setting đó cũng bị reset về default, bằng cách nào đó mình muốn lưu giữ file manifest. Đơn giản thôi, copy từ Rancher về rồi lưu ở đâu đó, nhưng cũng phải xóa đi những phần không cần thiết, thêm nhưng setting mong muốn vào, mình đã làm thử và nó trong như thế này. Ở đây mình chỉ copy mỗi file manifest của prometheus server thôi.

    # prometheus_deployment.yml
    apiVersion: apps/v1beta2
    kind: Deployment
    metadata:
      generation: 3
      labels:
        app: prometheus
        chart: prometheus-6.2.1
        component: server
        heritage: Tiller
        io.cattle.field/appId: prometheus-rnztg
        release: prometheus-rnztg
      name: prometheus-rnztg-server
      namespace: prometheus-rnztg
    spec:
      progressDeadlineSeconds: 600
      replicas: 1
      revisionHistoryLimit: 2
      selector:
        matchLabels:
          app: prometheus
          component: server
          release: prometheus-rnztg
      strategy:
        rollingUpdate:
          maxSurge: 25%
          maxUnavailable: 25%
        type: RollingUpdate
      template:
        metadata:
          creationTimestamp: null
          labels:
            app: prometheus
            component: server
            release: prometheus-rnztg
          annotations:
            reloaded-at: "{{ ansible_date_time.date }}_{{ ansible_date_time.hour}}{{ ansible_date_time.minute }}{{ ansible_date_time.second }}"
        spec:
          affinity:
            nodeAffinity:
              requiredDuringSchedulingIgnoredDuringExecution:
                nodeSelectorTerms:
                - matchExpressions:
                  - key: app
                    operator: In
                    values:
                    - consumer
          containers:
          - args:
            - --volume-dir=/etc/config
            - --webhook-url=http://localhost:9090/-/reload
            image: jimmidyson/configmap-reload:v0.1
            imagePullPolicy: IfNotPresent
            name: prometheus-server-configmap-reload
            resources: {}
            terminationMessagePath: /dev/termination-log
            terminationMessagePolicy: File
            volumeMounts:
            - mountPath: /etc/config
              name: config-volume
              readOnly: true
          - args:
            - --config.file=/etc/config/prometheus.yml
            - --storage.tsdb.path=/data
            - --web.console.libraries=/etc/prometheus/console_libraries
            - --web.console.templates=/etc/prometheus/consoles
            - --web.enable-lifecycle
            image: prom/prometheus:v2.2.1
            imagePullPolicy: IfNotPresent
            livenessProbe:
              failureThreshold: 3
              httpGet:
                path: /-/healthy
                port: 9090
                scheme: HTTP
              initialDelaySeconds: 30
              periodSeconds: 10
              successThreshold: 1
              timeoutSeconds: 30
            name: prometheus-server
            ports:
            - containerPort: 9090
              protocol: TCP
            readinessProbe:
              failureThreshold: 3
              httpGet:
                path: /-/ready
                port: 9090
                scheme: HTTP
              initialDelaySeconds: 30
              periodSeconds: 10
              successThreshold: 1
              timeoutSeconds: 30
            resources: {}
            terminationMessagePath: /dev/termination-log
            terminationMessagePolicy: File
            volumeMounts:
            - mountPath: /etc/config
              name: config-volume
            - mountPath: /data
              name: storage-volume
          dnsPolicy: ClusterFirst
          initContainers:
          - command:
            - chown
            - -R
            - 65534:65534
            - /data
            image: busybox:latest
            imagePullPolicy: IfNotPresent
            name: init-chown-data
            resources: {}
            terminationMessagePath: /dev/termination-log
            terminationMessagePolicy: File
            volumeMounts:
            - mountPath: /data
              name: storage-volume
          restartPolicy: Always
          schedulerName: default-scheduler
          securityContext: {}
          serviceAccount: prometheus-rnztg-server
          serviceAccountName: prometheus-rnztg-server
          terminationGracePeriodSeconds: 300
          volumes:
          - configMap:
              defaultMode: 420
              name: prometheus-rnztg-server
            name: config-volume
          - emptyDir: {}
            name: storage-volume
    

    bây giờ thì chúng ta thử apply xem

    kubectl apply -f prometheus_deployment.yml
    

    Sau vài chục giây thực hiện Rolling update xong, chung ta kiểm tra lại

    $ kubectl get pods -n prometheus-rnztg
    NAME                                                   READY     STATUS    RESTARTS   AGE
    prometheus-rnztg-alertmanager-976b66445-xk6jm          2/2       Running   2          1d
    prometheus-rnztg-grafana-6b456867f9-lktgd              2/2       Running   2          1d
    prometheus-rnztg-kube-state-metrics-6d9954479c-929jx   1/1       Running   1          1d
    prometheus-rnztg-node-exporter-9g7vv                   1/1       Running   1          1d
    prometheus-rnztg-node-exporter-c4kns                   1/1       Running   0          1d
    prometheus-rnztg-server-64dcd6dbb7-8l4q5               2/2       Running   0          1m
    

    Oh! nó đã update được rồi!

    Đến đây cơ bản mình đã giới thiệu cách cài đặt Prometheus-Grafana bằng Rancher UI cùng với cách update cấu hình bằng file manifest. Cách lưu giữ file manifest và dùng kubectl là một cách hay tuy nhiên có quá nhiều pod, service, deployment, deamonset vv, với việc copy như vậy không ổn lắm. Mình sẽ qua cách cài đặt thứ 2.

    Install Prometheus sử dụng Helm

    Helm đóng vai trò là một Package Manager cho Kubernetes, các bạn có thể tham khảo thêm tại đây.

    Install Helm

    https://github.com/helm/helm/blob/master/docs/install.md -> From Script

    $ curl -LO https://git.io/get_helm.sh
    $ chmod 700 get_helm.sh
    $ ./get_helm.sh
    

    Initialize Helm (Install Tiller)

    https://rancher.com/docs/rancher/v2.x/en/installation/ha/helm-init/

    kubectl -n kube-system create serviceaccount tiller
     
    kubectl create clusterrolebinding tiller \
      --clusterrole=cluster-admin \
      --serviceaccount=kube-system:tiller
     
    helm init --service-account tiller
    

    Install prometheus

    Tham khảo: https://github.com/helm/charts/tree/master/stable/prometheus-operator

    helm install stable/prometheus-operator --name prometheus-operator --namespace prometheus-test
    

    Quá trình cài đặt mất tầm 1 đến vài phút, kiểm tra lại:

    $ kubectl get all -n prometheus-test
     
    NAME                                                          READY     STATUS    RESTARTS   AGE
    pod/alertmanager-prometheus-operator-alertmanager-0           2/2       Running   0          1m
    pod/prometheus-operator-grafana-5dd5865bc-7h9p7               2/2       Running   0          1m
    pod/prometheus-operator-kube-state-metrics-6b4b87f6fd-r82jt   1/1       Running   0          1m
    pod/prometheus-operator-operator-5b9f65b595-8tk69             1/1       Running   0          1m
    pod/prometheus-operator-prometheus-node-exporter-drrqt        1/1       Running   0          1m
    pod/prometheus-operator-prometheus-node-exporter-nb85g        1/1       Running   0          1m
    pod/prometheus-prometheus-operator-prometheus-0               3/3       Running   1          1m
     
    NAME                                                   TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)             AGE
    service/alertmanager-operated                          ClusterIP   None            <none>        9093/TCP,6783/TCP   1m
    service/prometheus-operated                            ClusterIP   None            <none>        9090/TCP            1m
    service/prometheus-operator-alertmanager               ClusterIP   10.43.180.29    <none>        9093/TCP            1m
    service/prometheus-operator-grafana                    ClusterIP   10.43.103.82    <none>        80/TCP              1m
    service/prometheus-operator-kube-state-metrics         ClusterIP   10.43.46.65     <none>        8080/TCP            1m
    service/prometheus-operator-operator                   ClusterIP   10.43.51.253    <none>        8080/TCP            1m
    service/prometheus-operator-prometheus                 ClusterIP   10.43.212.205   <none>        9090/TCP            1m
    service/prometheus-operator-prometheus-node-exporter   ClusterIP   10.43.10.41     <none>        9100/TCP            1m
     
    NAME                                                          DESIRED   CURRENT   READY     UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE
    daemonset.apps/prometheus-operator-prometheus-node-exporter   2         2         2         2            2           <none>          1m
     
    NAME                                                     DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
    deployment.apps/prometheus-operator-grafana              1         1         1            1           1m
    deployment.apps/prometheus-operator-kube-state-metrics   1         1         1            1           1m
    deployment.apps/prometheus-operator-operator             1         1         1            1           1m
     
    NAME                                                                DESIRED   CURRENT   READY     AGE
    replicaset.apps/prometheus-operator-grafana-5dd5865bc               1         1         1         1m
    replicaset.apps/prometheus-operator-kube-state-metrics-6b4b87f6fd   1         1         1         1m
    replicaset.apps/prometheus-operator-operator-5b9f65b595             1         1         1         1m
     
    NAME                                                             DESIRED   CURRENT   AGE
    statefulset.apps/alertmanager-prometheus-operator-alertmanager   1         1         1m
    statefulset.apps/prometheus-prometheus-operator-prometheus       1         1         1m
    

    Có vẻ như quá trình cài đặt Ok rồi.

    Delete chart

    To uninstall/delete the my-release deployment:
    $ helm delete prometheus-operator
    The command removes all the Kubernetes components associated with the chart and > deletes the release.
    CRDs created by this chart are not removed by default and should be manually cleaned up:

    kubectl delete crd prometheuses.monitoring.coreos.com
    kubectl delete crd prometheusrules.monitoring.coreos.com
    kubectl delete crd servicemonitors.monitoring.coreos.com
    kubectl delete crd alertmanagers.monitoring.coreos.com
    

    Prometheus Configuration

    Tham khảo:
    https://github.com/helm/charts/tree/master/stable/prometheus-operator#configuration
    Bây giờ chúng ta thử update config xem như thế nào!
    Như kiểm tra phía trên thì hiện tại Service của Gragana đang làm ClusterIP, vì vậy chúng ta không thể access từ bên ngoài vào được. Mình sẽ thay đổi thành NodePort

    helm upgrade prometheus-operator stable/prometheus-operator --set grafana.service.type=NodePort
    
    $ kubectl get svc -n prometheus-test
    NAME                                           TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)             AGE
    alertmanager-operated                          ClusterIP   None            <none>        9093/TCP,6783/TCP   1h
    prometheus-operated                            ClusterIP   None            <none>        9090/TCP            1h
    prometheus-operator-alertmanager               ClusterIP   10.43.180.29    <none>        9093/TCP            1h
    prometheus-operator-grafana                    NodePort    10.43.103.82    <none>        80:30414/TCP        1h
    prometheus-operator-kube-state-metrics         ClusterIP   10.43.46.65     <none>        8080/TCP            1h
    prometheus-operator-operator                   ClusterIP   10.43.51.253    <none>        8080/TCP            1h
    prometheus-operator-prometheus                 ClusterIP   10.43.212.205   <none>        9090/TCP            1h
    prometheus-operator-prometheus-node-exporter   ClusterIP   10.43.10.41     <none>        9100/TCP            1h
    

    Login thử xem
    http://192.168.33.50:30414/login (admin/prom-operator)

    Chúng ta thay đổi để có thể xem được GUI mặc định của Prometheus luôn.

    helm upgrade prometheus-operator prometheus-operator --set prometheus.service.type=NodePort,grafana.service.type=NodePort,grafana.service.type=NodePort,kubelet.serviceMonitor.https=false
    

    Lỗi không thu thập được Pod data


    Như các bạn thấy ở hình trên, Grafana không hiển thị được dữ liệu của K8s Pod, vậy nguyên nhân là do đâu?
    Sau khi điều tra khá lâu thì đây là nguyên nhân
    https://qiita.com/MahoTakara/items/21090863674368e6aae3#cadvisorについて
    Kiểm chứng lại xem đúng vậy không? quả thật là như vậy.

    Mình sẽ tạm dịch nội dung liên quan đến cAdvisor từ bài blog trên.

    cAdvisor

    cAdvisor là một agent mả nguồn mở dùng để phân tích perfomance và trạng thái sử dụng tài nguyên container. Vì nó được thiết lập chuyên dụng cho container, nên thực sự nó suppport cho các Docker container.
    Trong Kubernetes, cAdvisor được tích hợp vào kubelet binary. cAdvisor tự động phát hiện tất cả các container trong máy và thu thập toàn bộ các thông tin thống kê như CPU, Memory, file system cũng như trạng thái sử dụng network. Nói tóm lại cAdvisor là một phần của kubelet.
    Chúng ta không thể thu thập data nếu như không đổi cadvisor-port thành 10255.
    Nếu bạn đang sử dụng Kuberadm thì sẽ tìm thấy setting như bên dưới.

    vagrant@node-1:~$ cat /etc/systemd/system/kubelet.service.d/10-kubeadm.conf |grep cadvisor
    Environment="KUBELET_CADVISOR_ARGS=--cadvisor-port=0"
    
    Giải quyết vấn đề

    Tình hình lỗi như vậy, bây giờ chúng ta đi kiểm tra có đúng cadvisor-port=0 hay không.
    Đầu tiên chúng ta vào máy node, exec đến container kubelet và tìm option cadvisor-port

    $ docker ps -f name=kubelet
    CONTAINER ID        IMAGE                                COMMAND                  CREATED             STATUS              PORTS               NAMES
    87426ecd271d        rancher/hyperkube:v1.10.1-rancher2   "/opt/rke/entrypoi..."   11 minutes ago      Up 11 minutes                           kubelet
    [vagrant@consumer ~]$ docker exec -it kubelet bash
    root@consumer:/# ps -ef | grep cadvisor
    root      1229  1217  2 03:52 ?        00:00:20 kubelet --cloud-provider= --tls-cipher-suites=TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305 --resolv-conf=/etc/resolv.conf --anonymous-auth=false --feature-gates=MountPropagation=false --read-only-port=0 --network-plugin=cni --cni-bin-dir=/opt/cni/bin --cgroups-per-qos=True --cni-conf-dir=/etc/cni/net.d --allow-privileged=true --volume-plugin-dir=/var/lib/kubelet/volumeplugins --cluster-domain=cluster.local --v=2 --address=0.0.0.0 --cadvisor-port=0 --pod-infra-container-image=rancher/pause-amd64:3.1 --kubeconfig=/etc/kubernetes/ssl/kubecfg-kube-node.yaml --fail-swap-on=false --client-ca-file=/etc/kubernetes/ssl/kube-ca.pem --root-dir=/var/lib/kubelet --enforce-node-allocatable= --hostname-override=192.168.33.51 --cluster-dns=10.43.0.10 --cgroup-driver=cgroupfs
    root      5759  5663  0 04:04 pts/2    00:00:00 grep cadvisor
    root@consumer:/#
    

    Quả nhiên là --cadvisor-port=0, sau khi điều tra cách để thay đổi port này mình thêm setting cho rancher-cluser như bên dưới. (Như đã nói mình đang dùng rancher để create kubernetes cluster, nếu bạn dùng Kuberadm thì có khi dễ dàng hơn).

    kubelet:
      extra_args:
        cadvisor-port: 10255
    

    Restart lại rancher cluster.

    ./rke up --config rancher-cluster.yml
    

    Kiểm tra lại port như cách làm phía trên, hoặc access vài prometheus GUI, http://192.168.33.50:30090/targets.

    Trông có vẻ Ok rồi nhỉ, giờ thì kiểm tra Grafana đã nhận data pod được chưa?

    Tuyệt vời! Dữ liệu của K8s pod bắt đầu được thu thập rồi. Đến đây xem như nội dung cần truyền tải trong bài blog này là hết, tuy nhiên mình sẽ bổ sung thêm một chút - tương đối là có ích.

    Helm More Installation Methods

    Tham khảo: https://helm.sh/docs/using_helm/#more-installation-methods
    Các bạn có để ý command khi mình cài đặt Prometheus.

    helm install stable/prometheus-operator --name prometheus-operator --namespace prometheus-test
    

    Khi install chart, cách đơn giản là dùng chart của official là "stable". Tuy nhiên, chúng ta có thể tự tạo chart riêng cho riêng mình để có thể dễ dàng modify.
    Tham khảo: https://docs.bitnami.com/kubernetes/how-to/create-your-first-helm-chart/
    Chúng ta cũng thử xem, mình sẽ tải nguyên source prometheus-operator về, và cài đặt chart bằng source đó

    $ helm fetch stable/prometheus-operator
    $ tar -zxvf ~/prometheus-operator-5.10.4.tgz
    $ helm install prometheus-operator --name prometheus-operator --namespace prometheus-test
    

    Chúng ta cũng được kết quả tương tự, bằng cách này mình có thể tùy chỉnh các giá trị trong các chart theo ý mình và upgrade source này. Thật tiện lợi phải không.

    Kết luận

    Bài viết cũng khá dài rồi, hy vọng mọi người có thể hiểu được cách thức hoặc động cũng như cài đặt được prometheus-grafane để monitoring cho hệ thống của mình. Tương lai mình sẽ viết tiếp phần 3 để hướng dẫn cách tạo các biểu đồ monitoring dữ liệu, tạo các alert cần thiết vv

    Tài liệu tham khảo

    1. https://qiita.com/MahoTakara/items/21090863674368e6aae3#cadvisorについて
    2. https://qiita.com/Chanmoro/items/ac0eb1bf93760566b338
    3. https://helm.sh/docs/using_helm/
    4. https://docs.bitnami.com/kubernetes/how-to/create-your-first-helm-chart/
    5. https://github.com/helm/charts/tree/master/stable/prometheus-operator