Uptime là gì? Tại sao cần theo dõi nó ?
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
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, TCP và ICMP. Đ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. - Và 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
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ừ datasource là Prometheus
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}-_@.com - 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
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
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.