Prometheus Blackbox Exporter: Kiểm tra HTTP, DNS, TCP và SSL Certificate hết hạn

Monitoring tutorial - IT technology blog
Monitoring tutorial - IT technology blog

Tại sao mình cần Blackbox Exporter?

Hệ thống monitoring của mình gồm Prometheus + Grafana theo dõi 15 server, và setup này đã phát hiện sự cố trước khi user báo nhiều lần rồi. Nhưng có một điểm mù khá nguy hiểm: mình biết CPU/RAM/disk của server ổn, mà không biết website có thực sự trả lời được không, DNS có phân giải đúng không, hay SSL certificate còn bao nhiêu ngày nữa thì bay.

Blackbox Exporter giải quyết đúng chỗ đó. Thay vì cài agent lên từng server (white-box monitoring), nó kiểm tra từ bên ngoài — đúng như cách user thực tế gõ URL vào browser. Blackbox probe các endpoint qua HTTP, HTTPS, DNS, TCP, ICMP rồi đẩy kết quả về cho Prometheus scrape.

Tình huống thực tế mình gặp: SSL certificate của một subdomain hết hạn mà không ai hay, đến khi browser văng lỗi thì đã muộn mất rồi. Sau khi setup Blackbox với alert “còn 14 ngày”, mình nhận Telegram notification sớm và gia hạn kịp — không còn cảnh chạy vá víu lúc nửa đêm nữa.

Cài đặt Blackbox Exporter

Mình cài trực tiếp trên server đang chạy Prometheus, không cần Docker cho setup đơn giản này.

Tải và cài đặt binary

# Tải phiên bản mới nhất (kiểm tra tại github.com/prometheus/blackbox_exporter)
wget https://github.com/prometheus/blackbox_exporter/releases/download/v0.25.0/blackbox_exporter-0.25.0.linux-amd64.tar.gz

tar xvf blackbox_exporter-0.25.0.linux-amd64.tar.gz
cd blackbox_exporter-0.25.0.linux-amd64

# Copy binary và config
sudo cp blackbox_exporter /usr/local/bin/
sudo mkdir -p /etc/blackbox_exporter
sudo cp blackbox.yml /etc/blackbox_exporter/

Tạo systemd service

sudo tee /etc/systemd/system/blackbox_exporter.service <<EOF
[Unit]
Description=Prometheus Blackbox Exporter
After=network.target

[Service]
User=prometheus
Group=prometheus
Type=simple
ExecStart=/usr/local/bin/blackbox_exporter \
  --config.file=/etc/blackbox_exporter/blackbox.yml \
  --web.listen-address=:9115
Restart=on-failure

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl daemon-reload
sudo systemctl enable --now blackbox_exporter
sudo systemctl status blackbox_exporter

Xong xuôi thì vào http://<server-ip>:9115 để xác nhận service đang chạy. Có giao diện web đơn giản liệt kê các module đã cấu hình.

Cấu hình các module probe

File /etc/blackbox_exporter/blackbox.yml định nghĩa các “module” — mỗi module là một kiểu kiểm tra khác nhau. Đây là config mình đang dùng thực tế trên production:

modules:
  # Kiểm tra HTTP 2xx — dùng cho các trang web thông thường
  http_2xx:
    prober: http
    timeout: 10s
    http:
      valid_http_versions: ["HTTP/1.1", "HTTP/2.0"]
      valid_status_codes: [200, 201, 301, 302]
      method: GET
      follow_redirects: true
      preferred_ip_protocol: "ip4"

  # Kiểm tra HTTPS + SSL certificate
  http_2xx_tls:
    prober: http
    timeout: 10s
    http:
      valid_http_versions: ["HTTP/1.1", "HTTP/2.0"]
      valid_status_codes: [200]
      method: GET
      follow_redirects: true
      tls_config:
        insecure_skip_verify: false   # Bắt buộc verify SSL

  # Kiểm tra TCP port mở (MySQL, Redis, custom service)
  tcp_connect:
    prober: tcp
    timeout: 5s

  # Kiểm tra DNS phân giải đúng
  dns_check:
    prober: dns
    timeout: 5s
    dns:
      query_name: "google.com"      # Tên domain kiểm tra
      query_type: "A"               # A, AAAA, MX, CNAME...
      valid_rcodes:
        - NOERROR

Cấu hình Prometheus scrape

Đây là chỗ Blackbox Exporter khác hẳn các exporter thông thường. Thay vì scrape trực tiếp, Prometheus dùng cơ chế relabeling để truyền target URL vào lúc scrape — tức là cùng một Blackbox instance có thể probe hàng chục URL khác nhau, không cần chạy nhiều process:

# Thêm vào prometheus.yml
scrape_configs:

  # Kiểm tra HTTP/HTTPS các website
  - job_name: 'blackbox_http'
    metrics_path: /probe
    params:
      module: [http_2xx_tls]
    static_configs:
      - targets:
          - https://itfromzero.com
          - https://example.com
          - https://api.yourdomain.com/health
    relabel_configs:
      - source_labels: [__address__]
        target_label: __param_target
      - source_labels: [__param_target]
        target_label: instance
      - target_label: __address__
        replacement: localhost:9115   # Địa chỉ Blackbox Exporter

  # Kiểm tra TCP port
  - job_name: 'blackbox_tcp'
    metrics_path: /probe
    params:
      module: [tcp_connect]
    static_configs:
      - targets:
          - db-server:3306     # MySQL
          - cache-server:6379  # Redis
          - app-server:8080    # App port
    relabel_configs:
      - source_labels: [__address__]
        target_label: __param_target
      - source_labels: [__param_target]
        target_label: instance
      - target_label: __address__
        replacement: localhost:9115

  # Kiểm tra DNS
  - job_name: 'blackbox_dns'
    metrics_path: /probe
    params:
      module: [dns_check]
    static_configs:
      - targets:
          - 8.8.8.8    # DNS server cần kiểm tra
          - 1.1.1.1
    relabel_configs:
      - source_labels: [__address__]
        target_label: __param_target
      - source_labels: [__param_target]
        target_label: instance
      - target_label: __address__
        replacement: localhost:9115

Reload Prometheus sau khi sửa config:

curl -X POST http://localhost:9090/-/reload

Kiểm tra kết quả và thiết lập cảnh báo

Test nhanh bằng curl trước khi chờ Prometheus

Không cần đợi Prometheus scrape chu kỳ tiếp theo — gọi thẳng vào endpoint của Blackbox để kiểm tra ngay:

# Kiểm tra HTTP
curl -s "http://localhost:9115/probe?target=https://itfromzero.com&module=http_2xx_tls" | grep probe_success
# Kết quả mong đợi: probe_success 1

# SSL còn bao nhiêu giây nữa hết hạn
curl -s "http://localhost:9115/probe?target=https://itfromzero.com&module=http_2xx_tls" | grep ssl_earliest_cert_expiry
# probe_ssl_earliest_cert_expiry 1.7XXXXXXXXX+09  ← Unix timestamp lúc cert hết hạn

# Kiểm tra TCP
curl -s "http://localhost:9115/probe?target=db-server:3306&module=tcp_connect" | grep probe_success

Alerting Rules cho Prometheus

Alert rules mới là thứ biến Blackbox từ “công cụ xem cho vui” thành hệ thống monitoring thực sự. Mình tách thành file riêng cho dễ quản lý:

# /etc/prometheus/rules/blackbox.yml
groups:
  - name: blackbox_alerts
    rules:

      # Website down
      - alert: WebsiteDown
        expr: probe_success{job="blackbox_http"} == 0
        for: 2m
        labels:
          severity: critical
        annotations:
          summary: "Website DOWN: {{ $labels.instance }}"
          description: "{{ $labels.instance }} không phản hồi hơn 2 phút."

      # HTTP response time chậm
      - alert: SlowResponseTime
        expr: probe_duration_seconds{job="blackbox_http"} > 3
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "Response chậm: {{ $labels.instance }}"
          description: "Thời gian phản hồi {{ $value | humanizeDuration }} > 3 giây."

      # SSL Certificate sắp hết hạn (14 ngày)
      - alert: SSLCertExpiringSoon
        expr: (probe_ssl_earliest_cert_expiry - time()) / 86400 < 14
        for: 1h
        labels:
          severity: warning
        annotations:
          summary: "SSL sắp hết hạn: {{ $labels.instance }}"
          description: "Certificate còn {{ $value | humanize }} ngày. Gia hạn ngay!"

      # SSL Certificate đã hết hạn
      - alert: SSLCertExpired
        expr: (probe_ssl_earliest_cert_expiry - time()) / 86400 < 0
        for: 0m
        labels:
          severity: critical
        annotations:
          summary: "SSL HẾT HẠN: {{ $labels.instance }}"

      # TCP port đóng
      - alert: TCPPortDown
        expr: probe_success{job="blackbox_tcp"} == 0
        for: 1m
        labels:
          severity: critical
        annotations:
          summary: "Port DOWN: {{ $labels.instance }}"
          description: "Không kết nối được tới {{ $labels.instance }}"

Thêm rule file vào prometheus.yml:

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

Grafana Dashboard

Import dashboard ID 7587 từ Grafana.com — không cần tự build từ đầu. Dashboard này hiển thị đầy đủ: trạng thái probe, response time, SSL days remaining, HTTP status code. Mình dùng nó làm màn hình overview chính.

Một vài PromQL query để tự build panel nếu cần tùy chỉnh:

# Số ngày SSL còn lại
(probe_ssl_earliest_cert_expiry{job="blackbox_http"} - time()) / 86400

# Uptime % trong 24h
avg_over_time(probe_success{job="blackbox_http"}[24h]) * 100

# HTTP status code
probe_http_status_code{job="blackbox_http"}

Một vài lưu ý từ thực tế

  • Firewall: Server chạy Blackbox phải đi ra được internet (port 80, 443, 53). Server nằm trong private network mà không có NAT/proxy thì probe HTTP ra ngoài sẽ fail — dễ nhầm tưởng website down.
  • DNS module: Mặc định config dùng google.com cho query_name. Nếu muốn kiểm tra DNS server nội bộ, đổi thành domain nội bộ của bạn — kiểm tra google.com qua DNS nội bộ không có nhiều ý nghĩa lắm.
  • Timeout vs scrape interval: Timeout phải nhỏ hơn scrape interval. Prometheus mặc định scrape mỗi 30s — nếu timeout HTTP set 30s trở lên, các probe sẽ bị overlap và metrics không còn chính xác. Mình dùng 10s cho HTTP, 5s cho TCP/DNS là ổn.
  • TLS insecure: Đừng bao giờ set insecure_skip_verify: true trên production. Mục đích cốt lõi của Blackbox là phát hiện SSL lỗi — bỏ qua verify là bắn vào chân mình.
  • Alert routing: Mình route severity: critical sang Telegram, còn warning sang email. Critical lúc nửa đêm mà cũng chỉ gửi email thì sáng hôm sau mới biết — không kịp xử lý gì rồi.

Share: