+24

Sử dụng Prometheus, Blackbox Exporter, Alert Manager và Grafana để theo dõi trạng thái uptime website như updown.io

Uptime là gì? Tại sao cần theo dõi nó ?

image.png Uptime (thường biểu thị theo phần trăm) cho biết tỉ lệ phần trăm hoạt động đầy đủ của website. Tỷ lệ phần trăm còn lại là mức độ thường xuyên mà nó không hoạt động. Nếu dịch vụ hosting web nói uptime là 93%, nghĩa là server của họ bị downtime trung bình 7% thời gian Một trong những tính quan trọng nhất của trang web là tính khả dụng. Bạn có thể sở hữu nội dung tuyệt vời, hình ảnh sản phẩm đẹp mắt, và những tính năng đặc biệt đầy thu hút, nhưng khi người dùng cần sử dụng tới thì website lại không hoạt động, điều đó thật sự đem lại trải nghiệm xấu cho người dùng, họ sẵn sàng trải nghiệm 1 website khác thay thế. Đó là lý do tại sao việc theo dõi hiệu suất trang web là cần thiết. Chỉ 1 phút ngừng hoạt động có thể khiến công ty của bạn mất hàng ngàn đô la. Hãy tưởng tượng đến những mất mát từ phút kéo dài sang hàng giờ hoặc thậm chí vài ngày.

Làm thế nào để theo dõi trạng thái Uptime của website ?

Có một số công cụ giám sát uptime website miễn phí sẽ cho bạn biết khi nào trang web ngừng hoạt động ví dụ như https://updown.io, https://uptime.com,... Tuy nhiên đa số chúng đều giới hạn số lượng website được sử dụng. Vì vậy, sẽ thật tuyệt khi bạn tự xây dựng cho mình 1 công cụ và tuỳ ý sử dụng chúng cho bao nhiêu website, bao nhiêu endpoint mà bạn mong muốn.

Hiện tại, mình đang sử dụng bộ công cụ gồm: Prometheus, Blackbox Exporter, Alert Manager và Grafana để theo dõi trạng thái của các website

image.png

Trong bài viết này, mình sẽ chia sẻ cách mình tự xây dựng công cụ giám sát uptime như thế nào, đây là cấu trúc thư mục của project:

.
├── config
│   ├── alertmanager.yml
│   ├── blackbox
│   │   └── blackbox.yml
│   ├── grafana
│   │   └── provisioning
│   │       ├── dashboards
│   │       │   ├── Prometheus\ Blackbox\ Exporter-1653754328923.json
│   │       │   └── dashboard.yml
│   │       └── datasources
│   │           └── datasource.yml
│   ├── nginx
│   │   └── default.conf
│   ├── prometheus.yml
│   └── rules.yml
├── data
│   ├── alertmanager
│   ├── grafana
│   └── prometheus
│       
└── docker-compose.yml
└── .env

nào mình cùng bắt đầu thôiiii.

Cài đặt Docker

Docker là nền tảng cung cấp cho các công cụ, service để các lập trình viên và người quản trị hệ thống có thể phát triển, thực thi, chạy các ứng dụng với containers. Việc sử dụng các Linux containers để triển khia ứng dụng được gọi là containerization, sử dụng container giúp dễ dàng hơn trong việc triển khai ứng dụng.

Ngoài ra, mình còn sử dụng thêm Docker Compose, là công cụ giúp định nghĩa và khởi chạy multi-container Docker applications. Với Compose, chúng ta sử dụng Compose file để cấu hình application’s services. Chỉ với một câu lệnh, mình có thể dễ dàng create và start toàn bộ các services phục vụ cho việc chạy ứng dụng.

Cách cài đặt 2 công cụ trên các bạn có thể tham khảo trực tiếp trên trang chủ của Docker:

Cài đặt Prometheus

Prometheus là gì ?

Prometheus là một dịch vụ theo dõi và cảnh báo về hệ thống. Đây là một dịch vụ mã nguồn mở (Open source) hoàn toàn miễn phí. SoundCloud đã khởi đầu xây dựng Prometheus từ năm 2012. Prometheus đã được rất nhiều hệ thống tin tưởng áp dụng. Dự án có một cộng đồng người đóng góp, phát triển rất tích cực.

Giờ đây Prometheus đã được tách khỏi SoundCloud và là một dự án mã nguồn mở độc lập. Năm 2016, Prometheus tham gia vào tổ chức CNCF (Cloud Native Computing Foundation) với vị trí được ưu tiên phát triển thứ hai sau K8s (Kubernetes).

Tính năng quan trọng nhất của Prometheus là thu thập thông số, dữ liệu từ các mục tiêu (dịch vụ) được nhắm đến theo khoảng thời gian nhất định đã được cài đặt trước. Ngoài ra còn các API khác thể hiện được kết quả, đánh giá bằng biểu thức quy tắc và đưa ra cảnh báo. Prometheus còn cung cấp một ngôn ngữ truy vấn rất mạnh PromQL, cực kì hữu ích khi giao tiếp với các dịch vụ monitor khác.

Cài đặt

Các công cụ mình sử dụng đều đã được đóng gói thành các Docker Image và publish trên Docker Hub thế nên đơn giản chúng ta chỉ cần sử dụng chúng vào trong file docker-compose.yml của mình, bổ sung thêm config cho từng công cụ.

Đầu tiên với Prometheus, chúng ta có file config đặt ở config/prometheus.yml như sau:

rule_files:
  - "/etc/prometheus/rules.yml"

alerting:
  alertmanagers:
    - static_configs:
        - targets:
          - alertmanager:9093
scrape_configs:
- job_name: 'blackbox'
  scrape_interval: 10s
  metrics_path: /probe
  static_configs:
    - targets:
      - https://google.com
      - https://viblo.asia
      - https://viblo.asia/api/web-init-404
  params:
    module: [http_2xx]
  relabel_configs:
    - source_labels: [ __address__ ]
      target_label: __param_target
    - source_labels: [ __param_target ]
      target_label: instance
    - target_label: __address__
      replacement: "blackbox_exporter:9115"
Thuộc tính Ghi chú
rule_file Là mảng chứa thông tin là đường dẫn tới các điều kiện gửi cảnh báo của Alert Manager
alerting Định nghĩa cấu hình của instance Alert Manager
scrape_ configs Blackbox Exporter sẽ trả ra các metrics liên quan tới website, trong section này, chúng ta cần cấu hình cách Prometheus lấy chúng về
scrape_configs.*.static_configs Chứa các url mà chúng ta cần theo dõi
scrape_configs.*.metrics_path Endpoint mà Blackbox Exporter trả về metrics
scrape_configs.*.params.module Đây là các module của Blackbox Exporter
scrape_configs.*.relabel_configs Định nghĩa cho Prometheus viết lại các nhãn trước khi nó kéo metrics từ Blackbox về

Với rule_files là thông tin đường dẫn tới file cấu hình gửi cảnh báo của Alert Manager:

groups:
  - name: AllInstances
    rules:
      - alert: InstanceDown
        # Condition for alerting
        expr: up == 0
        for: 5s
        # Annotation - additional informational labels to store more information
        annotations:
          title: 'Instance {{ $labels.instance }} down'
          description: '{{ $labels.instance }} of job {{ $labels.job }} has been down for more than 5 seconds.'
        # Labels - additional labels to be attached to the alert
        labels:
          severity: 'critical'

Tiếp theo, chúng ta cần mount các file cấu hình trên vào service Prometheus trong Docker Compose nữa:

version: '2.2'

networks:
  frontend:
    name: frontend

services:
  prometheus:
    image: prom/prometheus
    restart: always
    command:
      - '--config.file=/etc/prometheus/prometheus.yml'
      - '--web.enable-lifecycle'
    labels:
      - traefik.enable=true
      - traefik.http.routers.${COMPOSE_PROJECT_NAME}-prometheus.rule=Host(`prometheus`)
      - traefik.http.services.${COMPOSE_PROJECT_NAME}-prometheus.loadbalancer.server.port=9090
    networks:
      - default
    volumes:
      - ./data/prometheus:/prometheus
      - ./config/prometheus.yml:/etc/prometheus/prometheus.yml
      - ./config/rules.yml:/etc/prometheus/rules.yml
    ports:
      - 9090:9090

Cài đặt Blackbox Exporter

Blackbox Exporter là một chương trình exporter cho phép gọi tới các endpoint thông qua các giao thức HTTP, HTTPS, DNS, TCPICMP. Điều này cũng có nghĩa bạn có thể sử dụng nó để monitor các endpoint bất kì, có sử dụng một trong các giao thức trên.

Với Blackbox Exporter, chúng ta cần cấu hình các module thực thi việc thăm dò tới các target được định nghĩa ở Prometheus. Do cơ chế Service Discovery, nên các target này được đặt ở Prometheus và ở Blackbox Exporter chúng ta chỉ cần cấu hình các module thôi

modules:
  http_2xx:
    http:
      fail_if_not_ssl: false
      ip_protocol_fallback: false
      method: GET
      no_follow_redirects: false
      preferred_ip_protocol: ip4
      valid_http_versions:
        - HTTP/1.1
        - HTTP/2.0
    prober: http
    timeout: 15s
    
Thuộc tính Ghi chú
modules Định nghĩa danh sách modules mà Blackbox Exporter sử dụng
http_2xx Là tên của module
modules.<tên modules>.http Cấu hình cho giao thức module này sử dụng, trong đó với giao thức HTTP ta có thể cấu hình method, điều kiện fail khi target không có SSL, cách resolve target,...
modules.<tên modules>.prober Prober thực thi việc thăm dò
modules.<tên modules>.timeout Thời gian timeout của mỗi lần thăm dò

Tiếp theo chúng ta bổ sung đoạn dưới đây vào file docker-compose.yml mà chúng ta đang xây dựng:

....
  blackbox_exporter:
    image: prom/blackbox-exporter
    restart: always
    tty: true
    labels:
      - traefik.enable=true
      - traefik.http.routers.${COMPOSE_PROJECT_NAME}-backbox.rule=Host(`blackbox_exporter`)
      - traefik.http.services.${COMPOSE_PROJECT_NAME}-backbox.loadbalancer.server.port=9115
    ports:
      - 9115:9115
    dns: 8.8.8.8
    command: --config.file=/etc/blackbox/blackbox.yml
    volumes:
      - ./config/blackbox/:/etc/blackbox/
    networks:
      - default

Cài đặt Alert Manager

Alert manager sẽ xử lý các cảnh báo gửi từ ứng dụng Prometheus. Thông qua các rules mà ta định nghĩa ở file cấu hình Prometheus. Alert Manager sẽ hoạt động theo:

  • Prometheus sẽ thu thập dữ liệu monitor là metrics từ các endpoint và lưu trong database Prometheus.
  • Bạn tạo các rule alert trong Prometheus, ví dụ như cấu hình của mình ở trên thì: Bất cứ 1 instance nào có trạng thái up == 0 trong 5s, endpoint down trong 5s.
  • Prometheus đẩy các alert này về Alert manager, nó sẽ xử lý việc trùng lặp alert, group các alert và gửi alert tới kênh thông báo mà bạn muốn: mail, telegram, slack,… Nội dung thông báo bạn có thể cấu hình như dưới đây trong file config/alertmanager.yml
global:
  resolve_timeout: 1m
  slack_api_url: 'https://hooks.slack.com/services/xxx'

route:
  receiver: 'slack-notifications'

receivers:
  - name: 'slack-notifications'
    slack_configs:
      - channel: 'test'
        send_resolved: true
        icon_url: https://avatars3.githubusercontent.com/u/3380462
        title: |-
          [{{ .Status | toUpper }}{{ if eq .Status "firing" }}:{{ .Alerts.Firing | len }}{{ end }}] {{ .CommonLabels.alertname }} for {{ .CommonLabels.job }}
          {{- if gt (len .CommonLabels) (len .GroupLabels) -}}
            {{" "}}(
            {{- with .CommonLabels.Remove .GroupLabels.Names }}
              {{- range $index, $label := .SortedPairs -}}
                {{ if $index }}, {{ end }}
                {{- $label.Name }}="{{ $label.Value -}}"
              {{- end }}
            {{- end -}}
            )
          {{- end }}
        text: >-
          {{ range .Alerts -}}
          *Alert:* {{ .Annotations.title }}{{ if .Labels.severity }} - `{{ .Labels.severity }}`{{ end }}

          *Description:* {{ .Annotations.description }}

          *Details:*
            {{ range .Labels.SortedPairs }} • *{{ .Name }}:* `{{ .Value }}`
            {{ end }}
          {{ end }}
...
  alertmanager:
    image: prom/alertmanager
    restart: always
    labels:
      - traefik.enable=true
      - traefik.http.routers.${COMPOSE_PROJECT_NAME}-alertmanager.rule=Host(`alertmanager`)
      - traefik.http.services.${COMPOSE_PROJECT_NAME}-alertmanager.loadbalancer.server.port=9093
    ports:
      - 9093:9093
    volumes:
      - ./data/alertmanager/:/etc/alertmanager/
      - ./config/alertmanager.yml:/etc/alertmanager/alertmanager.yml
    networks:
      - default
    depends_on:
      - prometheus

Với cách cấu hình như trên thì mỗi khi có downtime, 1 alert sẽ được gửi tới Slack channel image.png

Cài đặt Grafana

Cuối cùng để visualize các metrics của các website, chúng ta sử dụng Grafana. Grafana là một giao diện/dashboard theo dõi hệ thống (opensource), hỗ trợ rất nhiều loại dashboard và các loại graph khác nhau để người quản trị dễ dàng theo dõi.

Grafana là một nền tảng open-source chuyên phục vụ mục đích theo dõi và đánh giá các số liệu thu được. Grafana có thể truy xuất dữ liệu từ Graphite, Elasticsearch, OpenTSDB, Prometheus và InfluxDB. Grafana là một công cụ mạnh mẽ để truy xuất và biểu diễn dữ liệu dưới dạng các đồ thị và biểu đồ.

Mình sẽ cấu hình cho Grafana lấy data từ datasourcePrometheus

apiVersion: 1

datasources:
  - name: Prometheus
    type: prometheus
    access: proxy
    orgId: 1
    url: http://prometheus:9090
    basicAuth: false
    isDefault: true
    editable: true

Trong thư mục config của Grafana, ngoài cấu hình datasource còn có cấu hình dashboard và 1 file dashboard mình đã export sẵn ra, bạn có thể sử dụng các Dashboard có sẵn từ Grafana cũng được. Tiếp theo là đến cấu hình của service Grafana trong docker-compose.yml

...
  grafana:
    image: grafana/grafana-enterprise
    restart: always
    tty: true
    labels:
      - traefik.enable=true
      - traefik.http.routers.${COMPOSE_PROJECT_NAME}-grafana.rule=Host(`grafana`)
      - traefik.http.services.${COMPOSE_PROJECT_NAME}-grafana.loadbalancer.server.port=3000
    ports:
      - ${PORT:-80}:3000
    volumes:
    - ./data/grafana:/var/lib/grafana
    - ./config/grafana/provisioning:/etc/grafana/provisioning
    networks:
      - frontend
      - default

Test thử thôi

Sau các bước ở trên, chúng ta có 1 file docker-compose.yml hoàn chỉnh sẽ trông như này

version: '2.2'

networks:
  frontend:
    name: frontend

services:
  traefik:
    image: traefik:2.2
    restart: always
    command:
      - --api.dashboard=true
      - --entrypoints.http.address=:80
      - --providers.docker
      - --providers.docker.network=frontend
      - --providers.docker.watch=true
      - --providers.docker.exposedbydefault=false
    ports:
      - 8080:80
    networks:
      - frontend
    labels:
      - traefik.enable=true
      - traefik.http.routers.${COMPOSE_PROJECT_NAME}-traefik.rule=Host(`traefik.${DOMAIN}`)
      - traefik.http.routers.${COMPOSE_PROJECT_NAME}-traefik.service=api@internal
      - traefik.http.middlewares.${COMPOSE_PROJECT_NAME}-traefik-dashboard.redirectRegex.regex=/
      - traefik.http.middlewares.${COMPOSE_PROJECT_NAME}-traefik-dashboard.redirectRegex.replacement=/dashboard/
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock

  prometheus:
    image: prom/prometheus
    restart: always
    command:
      - '--config.file=/etc/prometheus/prometheus.yml'
      - '--web.enable-lifecycle'
    labels:
      - traefik.enable=true
      - traefik.http.routers.${COMPOSE_PROJECT_NAME}-prometheus.rule=Host(`prometheus`)
      - traefik.http.services.${COMPOSE_PROJECT_NAME}-prometheus.loadbalancer.server.port=9090
    networks:
      - default
    volumes:
      - ./data/prometheus:/prometheus
      - ./config/prometheus.yml:/etc/prometheus/prometheus.yml
      - ./config/rules.yml:/etc/prometheus/rules.yml
    ports:
      - 9090:9090
  alertmanager:
    image: prom/alertmanager
    restart: always
    labels:
      - traefik.enable=true
      - traefik.http.routers.${COMPOSE_PROJECT_NAME}-alertmanager.rule=Host(`alertmanager`)
      - traefik.http.services.${COMPOSE_PROJECT_NAME}-alertmanager.loadbalancer.server.port=9093
    ports:
      - 9093:9093
    volumes:
      - ./data/alertmanager/:/etc/alertmanager/
      - ./config/alertmanager.yml:/etc/alertmanager/alertmanager.yml
    networks:
      - default
    depends_on:
      - prometheus

  blackbox_exporter:
    image: prom/blackbox-exporter
    restart: always
    tty: true
    labels:
      - traefik.enable=true
      - traefik.http.routers.${COMPOSE_PROJECT_NAME}-backbox.rule=Host(`blackbox_exporter`)
      - traefik.http.services.${COMPOSE_PROJECT_NAME}-backbox.loadbalancer.server.port=9115
    ports:
      - 9115:9115
    dns: 8.8.8.8
    command: --config.file=/etc/blackbox/blackbox.yml
    volumes:
      - ./config/blackbox/:/etc/blackbox/
    networks:
      - default

  grafana:
    image: grafana/grafana-enterprise
    restart: always
    tty: true
    labels:
      - traefik.enable=true
      - traefik.http.routers.${COMPOSE_PROJECT_NAME}-grafana.rule=Host(`grafana`)
      - traefik.http.services.${COMPOSE_PROJECT_NAME}-grafana.loadbalancer.server.port=3000
    ports:
      - ${PORT:-80}:3000
    volumes:
    - ./data/grafana:/var/lib/grafana
    - ./config/grafana/provisioning:/etc/grafana/provisioning
    networks:
      - frontend
      - default

Ta chỉ cần chạy command cuối cùng là

$ docker-compose up -d

Để truy cập Grafana các bạn truy cập http://localhost/login image.png tài khoản mặc định là admin/admin. Sau khi đăng nhập bước đầu tiên là bạn cần đổi mật khẩu mặc định sang 1 mật khẩu an toàn hơn.

Từ giao diện Grafana, bạn chọn Dashboard > Home > Prometheus Blackbox Exporter là sẽ thấy được các dashboard hiển thị thông tin liên quan tới website, cái mà Prometheus đã thu thập được

image.png

Mỗi instance được thu thập các thông tin trạng thái Up/Down, thời gian phản hồi của trang, trạng thái của SSL,... bạn có thể tuỳ ý thêm các Panel, ngoài ra bạn có thể share dashboard để các thành viên khác cũng có thể theo dõi trạng thái của website cùng.

Tài liệu tham khảo


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí