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.comchoquery_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: truetrê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: criticalsang Telegram, cònwarningsang 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.
